Skip to main content

Thinlog

Python 3.12+ PyPI version License Typed

A lightweight, fully-typed Python logging toolkit — a thin wrapper on the standard logging library with extra wheels.

Table of Contents

Features

  • Wildcard logger configuration — define a "*" logger and have it applied to every registered logger.
  • Keyword-friendly logging — pass keyword arguments directly; they become extra fields.
  • Advanced filters — whitelist, blocklist, and conditional attribute assignment via TOML config.
  • Structured JSON output — rich exception context powered by structlog.
  • Remote logging — send logs to an HTTP endpoint or Telegram chat out of the box.
  • Fully typed — strict MyPy compliance with a py.typed PEP 561 marker.

Installation

pip install thinlog

Quick Start

config.toml:

[logging]
root = {level = "DEBUG", handlers = ["queue"]}

[logging.formatters]
json = {"()" = "thinlog.formatters.json.JsonFormatter", show_locals = false}
msg = {"()" = "thinlog.formatters.msg.MsgFormatter"}

[logging.handlers]
stream = {class = "logging.StreamHandler", level = "DEBUG", stream = "ext://sys.stderr", formatter = "msg"}
queue = {class = "logging.handlers.QueueHandler", handlers = ["stream"], formatter = "json", respect_handler_level = true}

app.py:

import tomllib
from pathlib import Path
from thinlog import configure_logging

config = tomllib.loads(Path("config.toml").read_text())
logger = configure_logging("myapp", config["logging"])

logger.info("app_started")
logger.warning("processing_payment_failed", user_id=42, ip="10.0.0.1")

From any other component or file if you need a specific logger you can simply do:

from thinlog import get_logger

logger = get_logger("my_other_specific_logger", dict(more="data", we="can pass"))

# Rest of the file...

A recommendation: Context(ctx) is good, use context everywhere, your app can have its own context, every request can have its own ctx so you can easily access your resources(e.g myapp logger) from ctx.

Concepts

Structured Log Keys

Thinlog treats the first argument of a log call as a machine-readable key, not a human-readable sentence. Use lowercase, underscore-separated identifiers that describe the event:

# Preferred — a stable, searchable key
logger.error("payment_gateway_timeout", order_id=512, gateway="stripe")

# Avoid — a free-form sentence that is hard to filter or aggregate
logger.error("The payment gateway timed out while processing order 512")

Structured keys are easy to match with filters, trivial to GROUP BY in a log aggregation system, and never require fragile regular expressions to parse. Pair them with keyword arguments for all variable data and you get logs that are both compact and rich in context.

Since this library is optimized so that each component have its own logger, the key can be short and optimized.

from thinlog import get_logger

logger = get_logger("my_other_specific_logger", dict(more="data", we="can pass"))
logger.error("request_failed", id=2)
# If there are multiple loggers with the key set to `request_failed`, it won't conflict.
# since it belongs to `my_other_specific_logger`, 
# we can easily find the cause and easily filterable in logging stacks.

configure_logging

configure_logging is a plain function that returns a ready-to-use logger. It registers an atexit handler that automatically stops QueueHandler listeners and flushes handlers on interpreter exit.

Wildcard Loggers

Define a "*" logger in your config and it will be applied to all registered loggers. Use "merge": true on a specific logger to extend rather than replace the wildcard config.

[logging.loggers]
"*" = {level = "INFO", handlers = ["queue"]}

[logging.loggers.trace_log]
merge = true
handlers = ["trace_handler"]

Filters

  • WhitelistFilter — allow records matching name, message, or attribute patterns.
  • BlocklistFilter — block matching records (inverse of whitelist).
  • AssignerFilter — conditionally assign attributes to matching records without blocking any.
[logging.filters]
skip_noisy = {"()" = "thinlog.filters.blocklist.BlocklistFilter", by_name = ["urllib3", "httpx"]}

Handlers

  • JsonHTTPHandler — send JSON logs via HTTP POST with per-record URL/header overrides.
  • TelegramHandler — send logs to Telegram; auto-splits long messages into document attachments.
  • CtxPrintHandler — print record context as JSON to stdout for development.

Formatters

  • JsonFormatter — full record as JSON with structured exception tracebacks.
  • MsgFormatter — plain message string only.
  • TelegramFormatter — HTML-formatted output with length-aware splitting.

Documentation

Full documentation is available at minfrastructure.github.io/thinlog.

This module is fully typed and compatible with MyPy out of the box. Please open an issue for any suggestions or bugs.

Release files for thinlog 26.2.3

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for thinlog 26.2.3
File Size Uploaded
thinlog-26.2.3.tar.gz 15.7 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for thinlog 26.2.3
File Interpreter ABI Platform
thinlog-26.2.3-py3-none-any.whl Python 3 none any Details

Total release size: 37.0 kB

Release files / thinlog-26.2.3.tar.gz

Download URL thinlog-26.2.3.tar.gz
Size 15.7 kB
Tags Source
SHA-256 checksum
How to use checksums
18b80857661b9e5127fa43ac24573314ec51d59d4a46151e1bb40bb5857e1880
BLAKE2b-256 checksum
How to use checksums
e8c7bdcdb9a096263ce044c77977fe2c98704e405789b34aa460dd940c76b82a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 27, 2026.

Transparency log

Release files / thinlog-26.2.3-py3-none-any.whl

Download URL thinlog-26.2.3-py3-none-any.whl
Size 21.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
50bdbd4d3c5b8f42ff2ffecbdae40a3b4e55d4deebc425d4ff1ecd97f39124dc
BLAKE2b-256 checksum
How to use checksums
c78f979cb15a7635bd90be35640025e7430a838306e3c317ca278945a9accf24
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/6.1.0 CPython/3.13.7

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Feb 27, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

26.2.3 This release

2 release files

26.2.2

2 release files

26.2.1

2 release 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