python-logging-loki
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
tagsitem ofextradict - Property
foofrom 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
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file inuits_python_logging_loki-1.5.0.tar.gz.
File metadata
- Download URL: inuits_python_logging_loki-1.5.0.tar.gz
- Upload date:
- Size: 15.5 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d986cba9084e46c641166bfd6e0be7bcb9c2351f87a4b1fef1d7d8e835cb6b5f
|
|
| MD5 |
0c8eb86a8bbbc3946cc3faff5269fefa
|
|
| BLAKE2b-256 |
d289afa6837e48ece0c8ef9bfcbb708b0e291cbfb7014d597df2851cc64e3706
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inuits_python_logging_loki-1.5.0.tar.gz -
Subject digest:
d986cba9084e46c641166bfd6e0be7bcb9c2351f87a4b1fef1d7d8e835cb6b5f - Sigstore transparency entry: 2672965921
- Sigstore integration time:
-
Permalink:
inuits/inuits-python-logging-loki@fa3b4a4e0a20dc107e863a290fca3ca404b465f8 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/inuits
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@fa3b4a4e0a20dc107e863a290fca3ca404b465f8 -
Trigger Event:
release
-
Statement type:
File details
Details for the file inuits_python_logging_loki-1.5.0-py3-none-any.whl.
File metadata
- Download URL: inuits_python_logging_loki-1.5.0-py3-none-any.whl
- Upload date:
- Size: 15.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via:
twine/7.0.0 CPython/3.13.14
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
c071705175a8581902eac60d5e72bc3edfc0811d04078bd63b4a699df27cac00
|
|
| MD5 |
ebabd4f4a81d5f284ab368f0d5014aaa
|
|
| BLAKE2b-256 |
70041c0f7d39b0785c3c8e9e7030a7542e2a862ade6ddd34477adaaa2822dc6c
|
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
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
inuits_python_logging_loki-1.5.0-py3-none-any.whl -
Subject digest:
c071705175a8581902eac60d5e72bc3edfc0811d04078bd63b4a699df27cac00 - Sigstore transparency entry: 2672965979
- Sigstore integration time:
-
Permalink:
inuits/inuits-python-logging-loki@fa3b4a4e0a20dc107e863a290fca3ca404b465f8 -
Branch / Tag:
refs/tags/v1.5.0 - Owner: https://github.com/inuits
-
Access:
public
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
python-publish.yml@fa3b4a4e0a20dc107e863a290fca3ca404b465f8 -
Trigger Event:
release
-
Statement type: