Grafana Loki Sink

Send structured logs to Grafana Loki with batching, labels, and retry/backoff.

Quick start

from fapilog.plugins.sinks.contrib.loki import LokiSink, LokiSinkConfig

sink = LokiSink(
    LokiSinkConfig(
        url="http://localhost:3100",
        labels={"service": "myapp", "env": "dev"},
        label_keys=["level", "component"],
    )
)

Environment-based setup:

export FAPILOG_CORE__SINKS='["loki"]'
export FAPILOG_LOKI__URL=http://localhost:3100
export FAPILOG_LOKI__LABELS='{"service":"myapp","env":"dev"}'
export FAPILOG_LOKI__LABEL_KEYS='["level","component"]'

Configuration

  • url: Loki base URL (required)

  • tenant_id: Optional multi-tenant header (X-Scope-OrgID)

  • labels: Static labels applied to every stream

  • label_keys: Event keys promoted to labels (sanitized)

  • batch_size / batch_timeout_seconds: Flush conditions

  • timeout_seconds: HTTP timeout

  • max_retries / retry_base_delay: Retry/backoff on errors/429

  • Auth: auth_username/auth_password (basic) or auth_token (bearer)

  • Circuit breaker: circuit_breaker_enabled, circuit_breaker_threshold

Behavior

  • Groups events by label combinations and pushes to /loki/api/v1/push

  • Timestamps use nanoseconds since epoch; defaults to time.time() when absent

  • Handles 429 with backoff, client errors (400/401/403) with diagnostics, and retries other failures

  • Implements write_serialized for pipelines using serialize_in_flush

  • Health check calls /ready

Label best practices

  1. Keep cardinality low (level, service, env are safe).

  2. Avoid high-cardinality fields (user_id, request_id).

  3. Label values are sanitized to [A-Za-z0-9_-]; long values are truncated.

Structured metadata (Loki 2.9+)

Loki 2.9+ supports structured metadata alongside labels. This feature is planned for a future fapilog release. Currently, all event data is serialized as the log line content. Track progress in the project roadmap.

Local testing (Docker)

docker run -d -p 3100:3100 grafana/loki:latest
export FAPILOG_LOKI__URL=http://localhost:3100
python - <<'PY'
from fapilog import runtime
with runtime() as logger:
    logger.info("hello loki", component="demo")
PY

See tests/integration/test_loki_sink.py for CI-ready patterns and examples/loki_logging for a complete FastAPI + Docker Compose setup.