Skip to content

Structured logging

Коротко:

Structured logging — logs в machine-readable format (JSON) вместо plain text. Key benefits: searchable ("error AND user.id=123"), aggregatable (count errors by endpoint), correlatable (trace_id links logs к trace). 2026 stack: Pino (Node fastest), Zap (Go), Zerolog (Rust), structlog (Python). Backend: Loki (Grafana), Elasticsearch, Datadog.

Ниже: пошаговая инструкция, рабочие примеры, типичные ошибки, FAQ.

Попробовать бесплатно →

Пошаговая настройка

  1. Install logger: npm install pino (Node), Python: pip install structlog
  2. Configure JSON output: logger = pino({ level: "info" })
  3. Add context: trace_id, user_id, request_id в every log line
  4. Fluent Bit / Promtail collects logs → ships к backend
  5. Backend: Loki (cheap), Elasticsearch (full-text), Datadog (managed)
  6. Query UI: Grafana + Loki, Kibana, Datadog Logs
  7. Sensitive redaction: pino-redact для passwords/tokens

Рабочие примеры

СценарийКонфиг
Node.js Pinoconst pino = require('pino'); const logger = pino({ level: process.env.LOG_LEVEL || 'info', redact: ['password', 'token', '*.creditCard'], timestamp: pino.stdTimeFunctions.isoTime }); logger.info({ user_id: 123, action: 'login' }, 'User logged in'); // Output: {"level":30,"time":"2026-04-18T...","user_id":123,"action":"login","msg":"User logged in"}
Python structlogimport structlog logger = structlog.get_logger() logger.info('user_login', user_id=123, method='oauth') # Output: event='user_login' user_id=123 method='oauth' # With JSON renderer structlog.configure( processors=[structlog.processors.JSONRenderer()] )
Correlation ID middleware// Express app.use((req, res, next) => { req.correlationId = req.headers['x-correlation-id'] || crypto.randomUUID(); req.logger = logger.child({ correlationId: req.correlationId }); res.setHeader('x-correlation-id', req.correlationId); next(); }); // Then: req.logger.info({ path: req.path }, 'Request received');
Promtail (ship to Loki)# promtail-config.yaml clients: - url: http://loki:3100/loki/api/v1/push scrape_configs: - job_name: app static_configs: - targets: [localhost] labels: job: myapp __path__: /var/log/myapp/*.log
Grafana Loki query# LogQL {job="myapp"} |= "error" | json | user_id="123" # Visual: rate of errors sum by (path) (rate({job="myapp"} |= "error" [5m]))

Типичные ошибки

  • Log sensitive data (credit cards, SSN, passwords) → compliance breach. Redact во logger config
  • No correlation ID → невозможно trace request across microservices
  • Writing logs synchronously на hot path — blocks event loop. Pino async transport
  • Too much info logging (10k lines/sec) — storage $$. Info для business events, debug для debug
  • Pretty-print JSON в prod — hard to parse. Single-line JSON always в prod

Больше по теме

Часто задаваемые вопросы

Loki vs Elasticsearch?

Loki: index labels only (not log content), cheap ($0.50/GB), Grafana-native. Elasticsearch: full-text index, expensive ($5/GB), powerful search. Для most — Loki enough.

Logs vs traces?

Logs: discrete events ("Error in checkout"). Traces: request flow + timing. Modern: logs include trace_id → cross-reference.

Retention?

Hot (instant search): 7-30 days. Warm (S3): 90 days. Cold (Glacier): 1+ год для compliance.

Enterno logging?

Enterno использует PSR-3 compatible + Papertrail backend. Для end-users — <a href="/monitors">monitor endpoint</a> covers availability.