Перейти к основному содержимому

Приёмники

Приёмник (sink) — это получатель LogRecord'ов. Логгер веером рассылает каждую отправленную запись всем подключённым приёмникам, прошедшим их фильтр min_severity. Приёмники независимы — сбой в одном не влияет на остальные.

Протокол Sink

Каждый приёмник реализует четыре метода:

Sink {
id: string # диагностический идентификатор (например, "console:auto", "file:/var/log/app.jsonl")
emit(record): void # неблокирующий; ставит запись в очередь на доставку
flush(timeout): void # блокирует до доставки буфера или истечения timeout
close(): void # flush + освобождение ресурсов
supports_severity(severity_number): bool # подсказка для фильтра; отклонённые уровни пропускаются заранее
}

Метод emit не блокирует вызывающий код. Блокирующий I/O (сетевые экспортёры, flush в файл) проходит через внутренний буфер и worker; при переполнении буфера приёмник по умолчанию отбрасывает самую старую запись и инкрементирует счётчик отброшенных. Связка буфер / worker зависит от приёмника — Phase 1 ConsoleSink и FileSink синхронизируют запись в stdout / файл под локом, а запланированный OTLPSink (Phase 2) использует фоновый worker.

Приёмники Phase 1

Три приёмника поставляются в первом релизе каждого биндинга:

ПриёмникКуда уходят записиРежим по умолчаниюКонфигурация
ConsoleSinksys.stderr (по умолчанию) или любой текстовый потокauto (TTY → pretty, не-TTY → JSON)mode, stream, min_severity
FileSinkФайл на диске, JSON-linesJSON-lines с ротацией по размеруpath, max_bytes, keep, min_severity
InMemorySinkКольцевой буфер в процессеотбрасывание при переполненииcapacity, min_severity

ConsoleSink

ConsoleSink пишет записи в sys.stderr (или выбранный текстовый поток) либо как цветной читаемый текст, либо как компактный JSON-lines. По умолчанию mode="auto" переключается по детектированию TTY — интерактивный терминал получает pretty-режим; перенаправленный или захваченный вывод — JSON.

from dagstack.logger import ConsoleSink

# Auto: pretty в TTY, JSON в остальных случаях.
sink = ConsoleSink(mode="auto")

# Принудительно JSON для логов в контейнере.
sink = ConsoleSink(mode="json", min_severity=9)

# Принудительно pretty для отладочного терминала.
sink = ConsoleSink(mode="pretty")

FileSink

FileSink пишет Canonical JSON-lines в файл и ротирует его по размеру. Биндинг Python использует RotatingFileHandler из stdlib под капотом — проверенную в бою реализацию ротации — и поверх применяет dagstack-формат JSON-lines.

from dagstack.logger import FileSink

sink = FileSink(
"/var/log/order-service.jsonl",
max_bytes=100_000_000, # ротировать на 100 МБ
keep=10, # хранить 10 архивных файлов
min_severity=9, # INFO и выше
)

max_bytes=0 отключает ротацию (файл растёт, пока оператор не урежет или не переместит его). keep=0 удаляет архивные файлы сразу при ротации — остаётся только текущий.

InMemorySink

InMemorySink копит записи в ограниченном кольцевом буфере; при заполнении буфера самые старые записи отбрасываются. Предназначен для тестов и кратковременных диагностических захватов.

from dagstack.logger import InMemorySink

sink = InMemorySink(capacity=100)
# ... отправляем какие-то записи ...

records = sink.records() # снимок (копия)
assert any(r.body == "expected message" for r in records)

sink.clear() # сброс перед следующим тестом

InMemorySink не реализует сериализацию в формат передачи — он хранит объекты LogRecord напрямую, так что assertion'ы тестов могут читать типизированные body, attributes и severity_number без парсинга JSON.

Маршрутизация по нескольким приёмникам

Логгер можно настроить с несколькими приёмниками. Каждый применяет собственный фильтр min_severity независимо от остальных. Типичная production-конфигурация пишет предупреждения и выше в консоль, все INFO+ — в файл для разбора инцидентов, а ошибки — отдельно в удалённый приёмник.

from dagstack.logger import ConsoleSink, FileSink, configure

configure(
root_level="DEBUG",
sinks=[
ConsoleSink(mode="pretty", min_severity=13), # WARN+ в консоль
FileSink("/var/log/app.jsonl", max_bytes=100_000_000, keep=10, min_severity=9),
],
)

Roadmap

Набор Phase 1 поставляется в каждом биндинге. Phase 2 добавляет OTel-экспортёр и несколько распространённых production-приёмников; Phase 3 добавляет облачные и высоконагруженные интеграции.

ПриёмникPhaseЗаметки
OTLPSink2OTLP/gRPC или OTLP/HTTP — основной production-экспортёр.
SyslogSink2BSD syslog и транспорт RFC 5424.
SentrySink2Только ERROR и выше; body и attrs становятся событием Sentry.
LokiSink2Для развёртываний без OTel-коллектора.
FluentBitForwardSink2Протокол Fluent Bit Forward — распространённый sidecar-паттерн.
CloudWatchLogsSink3AWS CloudWatch Logs с пакетной отправкой.
GCPCloudLoggingSink3Google Cloud Logging с OAuth / service account.
KafkaSink3Высокопроизводительные конвейеры.
ElasticsearchSink3Elasticsearch bulk API.

См. также