Skip to main content

python-logging-loki

PyPI version Python version License Build Status

Python logging handler for Loki.
https://grafana.com/loki

Installation

pip install inuits-python-logging-loki

Usage

import logging
import logging_loki


handler = logging_loki.LokiHandler(
    url="https://my-loki-instance/loki/api/v1/push",
    tags={"application": "my-app"},
    headers={"X-Scope-OrgID": "example-id"},
    auth=("username", "password"),
    props_to_labels = ["foo"]
)

logger = logging.getLogger("my-logger")
logger.addHandler(handler)
logger.error(
    "Something happened",
    extra={"tags": {"service": "my-service"}},
)

Example above will send Something happened message along with these labels:

  • Default labels from handler
  • Message level as serverity
  • Logger's name as logger
  • Labels from tags item of extra dict
  • Property foo from log record will be sent as loki label

Properties to label

Using a dict instead of a list for props_to_labels will enable renaming labels

handler = logging_loki.LokiHandler(
    url="https://my-loki-instance/loki/api/v1/push",
    tags={"application": "my-app"},
    props_to_labels = {
        "otelTraceID": "trace_id"
        "otelSpanID":  "span_id"
    }
)

In this case, the properties otelTraceID & otelSpanID will be renamed to trace_id & span_id loki labels

Non-blocking mode

Adding a LokiHandler to a logger directly is blocking: every log call does an HTTP POST to Loki on the calling thread and waits for the response. In a request handler that puts Loki's latency (and Loki's rate limiting) straight into your own response time.

Use LokiQueueHandler instead. It attaches to the logger, creates the LokiHandler and a QueueListener, and starts the listener, so the calling thread only puts the record on a queue.

import logging_loki
from queue import Queue


handler = logging_loki.LokiQueueHandler(
    Queue(-1),
    batch_interval=2,  # seconds; omit or pass 0 to push every record separately
    url="https://my-loki-instance/loki/api/v1/push",
    tags={"application": "my-app"},
    headers={"X-Scope-OrgID": "example-id"},
    auth=("username", "password"),
    props_to_labels=["foo"],
)

logger = logging.getLogger("my-logger")
logger.addHandler(handler)
logger.error(...)

If you wire the queue up by hand, you must start the listener yourself — a QueueListener that is never started means nothing ever drains the queue and no log line reaches Loki:

queue = Queue(-1)
handler = logging.handlers.QueueHandler(queue)
handler_loki = logging_loki.LokiHandler(url=..., tags=...)
listener = logging.handlers.QueueListener(queue, handler_loki)
listener.start()  # <- required

Batching and timeouts

With batch_interval set, records are buffered and pushed as one request. This is what keeps Loki from answering with 429 Too Many Requests: without it every log line is its own POST and its own stream.

Variable Default Meaning
LOKI_BATCH_INTERVAL 2 Seconds between batched pushes (LokiLogger only). 0 disables batching.
LOKI_MAX_BATCH_BUFFER_SIZE 1000 Records buffered before a push happens regardless of the interval.
LOKI_CONNECT_TIMEOUT 2 Connect timeout, in seconds, for a push to Loki.
LOKI_READ_TIMEOUT 5 Read timeout, in seconds, for a push to Loki.

A push that Loki rejects (429, or any other unexpected status) raises logging_loki.emitter.LokiPushError and the records in that batch are dropped. The HTTP session is kept open, since the connection is still healthy — only a transport-level failure closes it and forces a reconnect.

Forking servers

LokiQueueHandler does its work on background threads, and threads do not survive fork(). Handlers built before the fork — a logger created at import time under gunicorn --preload, for example — recreate their queue, listener and flush threads in the child automatically, so each worker delivers its own records and does not re-send the parent's.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

inuits_python_logging_loki-1.5.0.tar.gz (15.5 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

inuits_python_logging_loki-1.5.0-py3-none-any.whl (15.2 kB view details)

Uploaded Python 3

File details

Details for the file inuits_python_logging_loki-1.5.0.tar.gz.

File metadata

File hashes

Hashes for inuits_python_logging_loki-1.5.0.tar.gz
Algorithm Hash digest
SHA256 d986cba9084e46c641166bfd6e0be7bcb9c2351f87a4b1fef1d7d8e835cb6b5f
MD5 0c8eb86a8bbbc3946cc3faff5269fefa
BLAKE2b-256 d289afa6837e48ece0c8ef9bfcbb708b0e291cbfb7014d597df2851cc64e3706

See more details on using hashes here.

Provenance

The following attestation bundles were made for inuits_python_logging_loki-1.5.0.tar.gz:

Publisher: python-publish.yml on inuits/inuits-python-logging-loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file inuits_python_logging_loki-1.5.0-py3-none-any.whl.

File metadata

File hashes

Hashes for inuits_python_logging_loki-1.5.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c071705175a8581902eac60d5e72bc3edfc0811d04078bd63b4a699df27cac00
MD5 ebabd4f4a81d5f284ab368f0d5014aaa
BLAKE2b-256 70041c0f7d39b0785c3c8e9e7030a7542e2a862ade6ddd34477adaaa2822dc6c

See more details on using hashes here.

Provenance

The following attestation bundles were made for inuits_python_logging_loki-1.5.0-py3-none-any.whl:

Publisher: python-publish.yml on inuits/inuits-python-logging-loki

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Release history Release notifications | RSS feed

This release

1.5.0 This release

2 files

1.4.1

2 files

1.4.0

2 files

1.3.0

2 files

1.2.1

2 files

1.2.0

2 files

1.1.4

2 files

1.1.3

2 files

1.1.2

2 files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page