Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
python-logging-loki
python-logging-loki (with structured metadata support)
===================

[![PyPI version](https://img.shields.io/pypi/v/python-logging-loki.svg)](https://pypi.org/project/python-logging-loki/)
[![Python version](https://img.shields.io/badge/python-3.6%20%7C%203.7%20%7C%203.8-blue.svg)](https://www.python.org/)
[![License](https://img.shields.io/pypi/l/python-logging-loki.svg)](https://opensource.org/licenses/MIT)
[![Build Status](https://travis-ci.org/GreyZmeem/python-logging-loki.svg?branch=master)](https://travis-ci.org/GreyZmeem/python-logging-loki)

Python logging handler for Loki.
A fork of the python logging handler for Loki, supporting structured metadata.

https://grafana.com/loki

Installation
Expand Down Expand Up @@ -44,7 +45,16 @@ Example above will send `Something happened` message along with these labels:
- Logger's name as `logger`
- Labels from `tags` item of `extra` dict

The given example is blocking (i.e. each call will wait for the message to be sent).
To log structured metadata, simply add a `metadata` field to `extra`:

```python
logger.info(
f'Epoch [{epoch+1}/{epochs}], Loss: {loss:.4f}',
extra={"tags": {"experiment": "example"}, "metadata": {"epoch": f"{epoch}", "loss": f"{loss:.4f}"}},
)
```

The given examples are blocking (i.e. each call will wait for the message to be sent).
But you can use the built-in `QueueHandler` and` QueueListener` to send messages in a separate thread.

```python
Expand Down
9 changes: 7 additions & 2 deletions logging_loki/emitter.py
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,13 @@ def build_payload(self, record: logging.LogRecord, line) -> dict:
labels = self.build_tags(record)
ns = 1e9
ts = str(int(time.time() * ns))

# Include structured metadata
metadata = getattr(record, "metadata", {})
value = [ts, line, metadata] if metadata else [ts, line]

stream = {
"stream": labels,
"values": [[ts, line]],
"values": [value],
}
return {"streams": [stream]}
return {"streams": [stream]}