Skip to main content

A loguru sink that sends structured logs to Seq using CLEF format

Project description

loguru-seq

A loguru sink that sends structured logs to Seq using the CLEF format over HTTP with background batching.

Features

  • Non-blocking background thread with configurable batch interval and size
  • Structured fields via loguru's bind() forwarded as CLEF properties
  • Exception traces forwarded as the CLEF @x field
  • Optional API key authentication
  • Graceful shutdown that flushes remaining events on process exit

Installation

pip install loguru-seq

Or with uv:

uv add loguru-seq

Quick start

from loguru import logger
from loguru_seq import SeqSink

sink = SeqSink(url="http://localhost:5341")
logger.add(sink)

logger.info("Application started")
logger.warning("Low disk space")

With an API key

sink = SeqSink(
    url="http://seq.example.com",
    api_key="your-api-key",
)
logger.add(sink)

Structured properties with bind()

Extra fields passed to logger.bind() are forwarded as top-level CLEF properties and become searchable in Seq.

logger.bind(user_id=42, order_id="ORD-999").info("Order placed")
logger.bind(component="auth").warning("Token about to expire")

Structured properties via message arguments

Named keyword arguments passed directly to the log call are also forwarded as CLEF properties, and additionally rendered into the message text:

logger.info("User {name} logged in from {ip}", name="alice", ip="192.168.1.1")
# @mt  → "User alice logged in from 192.168.1.1"
# name → "alice"   (searchable property in Seq)
# ip   → "192.168.1.1"  (searchable property in Seq)

The difference from bind() is that the values are also baked into @mt, so they appear twice: in the message text and as discrete properties. With bind() the message text stays as a clean template and the values only live in their respective properties.

Positional arguments (e.g. logger.info("value is {}", 42)) are used for rendering only and do not become CLEF properties.

Use bind() for context that applies to multiple log calls (e.g. a request ID). Use inline kwargs when the value is specific to a single message and you want it visible in the message text as well.

Exception capture

try:
    result = 1 / 0
except ZeroDivisionError:
    logger.exception("Unexpected error in calculation")

The full traceback is sent in the CLEF @x field and displayed in Seq's exception viewer.

Configuration reference

SeqSink(
    url,                          # Base URL of the Seq server, e.g. "http://localhost:5341"
    api_key=None,                 # Seq API key (Settings → API Keys in the Seq UI)
    batch_interval_seconds=5.0,   # Seconds between automatic flushes
    batch_size=100,               # Flush early when this many events are buffered
    timeout_seconds=10.0,         # HTTP request timeout, in seconds
    max_queue_size=10_000,        # Drop events (with a stderr warning) when queue exceeds this
)
Parameter Default Description
url Base URL of the Seq instance
api_key None API key for authenticated Seq instances
batch_interval_seconds 5.0 Maximum seconds to wait before flushing
batch_size 100 Flush immediately when this many events are queued
timeout_seconds 10.0 HTTP timeout, in seconds, for each flush request
max_queue_size 10_000 Hard cap on the in-memory event queue

Manual flush

Call sink.flush() to send all buffered events immediately, for example before a scheduled job ends.

sink = SeqSink(url="http://localhost:5341", batch_interval_seconds=60)
logger.add(sink)

logger.info("Job started")
# ... work ...
logger.info("Job finished")
sink.flush()

Log level mapping

loguru CLEF / Seq
TRACE Verbose
DEBUG Debug
INFO Information
SUCCESS Information
WARNING Warning
ERROR Error
CRITICAL Fatal

Contributing

Contributions are welcome. Please open an issue before submitting large changes so we can discuss approach first.

Prerequisites

  • Python 3.9 or later
  • uv — used for environment and dependency management

Setting up the development environment

# Clone the repository
git clone https://github.com/gabrielgt/loguru-seq.git
cd loguru-seq

# Create the virtual environment and install all dependencies (including dev extras)
uv sync

uv sync reads pyproject.toml and uv.lock, creates a .venv directory, and installs the package in editable mode along with the dev dependency group (pytest, pytest-mock, ruff, pyright).

Alternatively, open the repository in the provided dev container (VS Code's "Reopen in Container", or GitHub Codespaces) for a preconfigured Python 3.11 environment with uv and the recommended VS Code extensions already installed.

Project structure

src/loguru_seq/
    __init__.py     # Public API — exports SeqSink
    sink.py         # SeqSink: buffering, batching, background thread
    sender.py       # SeqSender: httpx client, sends CLEF to Seq's /api/events/raw
    clef.py         # loguru record → CLEF dict, list of dicts → NDJSON string
tests/
    unit/           # Fast, no network required
    integration/    # Require a running Seq instance

Running unit tests

Unit tests use mocks and require no external services.

uv run pytest tests/unit

Running integration tests

Integration tests send real HTTP requests to a Seq instance.

  1. Start a local Seq instance (Docker is the easiest way):
docker run --name seq -d --restart unless-stopped \
  -e ACCEPT_EULA=Y \
  -e SEQ_PASSWORD=<initial-password> \
  -p 5341:80 \
  datalust/seq:latest
  1. Copy the example environment file and fill in your values:
cp example.env .env
# Edit .env — set SEQ_URL and optionally SEQ_API_KEY

The defaults in .env point to http://host.docker.internal:5341, which resolves correctly from inside another Docker container (for example a dev container). If you are running tests directly on your host machine, change SEQ_URL to http://localhost:5341.

  1. Run the integration tests:
uv run pytest tests/integration

Running all tests

uv run pytest

Code style

This project uses ruff for linting/formatting and pyright for type checking. All public functions and methods should be fully type-annotated.

Run everything CI checks (lint, format, type check, unit tests, integration tests) with one command:

./scripts/check.sh

Integration tests skip automatically with a clear message if no Seq instance is reachable — see Running integration tests to set one up locally.

Or run the checks individually:

uv run ruff check .            # Lint
uv run ruff format --check .   # Format (check only; use `ruff format .` to apply)
uv run pyright                  # Type check (checks src/ only)
uv run pytest tests/unit        # Unit tests
uv run pytest tests/integration # Integration tests (skipped if Seq isn't reachable)

Submitting changes

  1. Fork the repository and create a branch from main.
  2. Make your changes with tests.
  3. Run ./scripts/check.sh and verify it passes (this mirrors CI's test job; the integration job runs the same tests/integration suite against a real Seq service container in CI).
  4. Open a pull request with a clear description of what and why.

License

MIT

Project details


Download files

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

Source Distribution

loguru_seq-0.1.0.tar.gz (11.1 kB view details)

Uploaded Source

Built Distribution

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

loguru_seq-0.1.0-py3-none-any.whl (8.1 kB view details)

Uploaded Python 3

File details

Details for the file loguru_seq-0.1.0.tar.gz.

File metadata

  • Download URL: loguru_seq-0.1.0.tar.gz
  • Upload date:
  • Size: 11.1 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for loguru_seq-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d0da8ca6e239c2e6dec44dc21a14775f9b7d425e9c6d8a3e03651e9008fc02d2
MD5 d0d7458dc121aac0707b7fdf84167e8e
BLAKE2b-256 359673c4392b7c6d00f55642961151e020e9ae8ef74e38dd4259fd1494650a03

See more details on using hashes here.

File details

Details for the file loguru_seq-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: loguru_seq-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 8.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: uv/0.11.23 {"installer":{"name":"uv","version":"0.11.23","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"Ubuntu","version":"24.04","id":"noble","libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":true}

File hashes

Hashes for loguru_seq-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 144cbb6d56b3ec9afbcbd3324ce336e2de11aabcc03ee095efee05a4d0ab29c5
MD5 5f235c9b33b8d3ed3b2e2c4b60125b40
BLAKE2b-256 0aff5cf58cfd91ebe51773132759e7e07dc2f78717db4e2d2cc4c377f90f3ed1

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page