Skip to main content

tg-logging-handler logo

tg-logging-handler

CI CodeQL codecov PyPI Python versions License: MIT

Production-grade Telegram destination for Python's standard logging module.

Attach one handler and your logs go to a Telegram chat — asynchronously, so a slow or down Bot API never blocks your application. Batching, retries with backoff, 429 handling, oversized-message splitting, bounded-queue back-pressure, and parse_mode escaping are all handled for you.

Install

pip install tg-logging-handler

Requires Python 3.10+. The only runtime dependency is httpx.

Quickstart

import logging
from tg_logging_handler import TelegramLoggingHandler

# Reads TG_TOKEN / TG_CHAT_ID from the environment.
logging.getLogger().addHandler(TelegramLoggingHandler())

logging.error("Something broke")  # delivered to your Telegram chat

TGLoggingHandler is a shorter alias for the same class.

Provide credentials explicitly instead of via the environment:

handler = TelegramLoggingHandler(token="123456:ABC-DEF", chat_id=-100123456789)
logging.getLogger().addHandler(handler)

Why this handler

  • Never blocks your app. emit() only snapshots the record and enqueues it; a single daemon thread does all network I/O. A dead Bot API can never stall a request handler.
  • Never crashes your app. Send failures are retried, then reported to stderr and counted — never raised into your code. The only exception you can catch is TelegramConfigError, and only at construction time.
  • No logging recursion. Internal diagnostics go to stderr, never back through logging.

Configuration

All constructor arguments after token / chat_id are keyword-only.

Argument Default Purpose
token None Bot token; falls back to TG_TOKEN.
chat_id None Target chat; falls back to TG_CHAT_ID.
topic_id None Forum topic id; falls back to TG_TOPIC_ID. When set on a forum supergroup, messages go to that topic; when unset, to the group's General topic.
level logging.WARNING Minimum level (passed to setLevel).
batch_size 1 Max records per message (>= 1). 1 = send each record immediately.
flush_interval 5.0 Max seconds a partial batch waits (>= 0).
max_retries 3 Retry budget for network/5xx errors (>= 0). 429s honor Retry-After without spending this budget (capped at 10 consecutive waits).
overflow "split" Oversized-message policy: "split", "truncate", or "drop".
parse_mode None None, "Markdown", "MarkdownV2", or "HTML". Formatter output is escaped for the chosen mode.
queue_maxsize 10_000 Bounded queue size. 0 = unbounded (memory risk).
queue_full_policy "drop_newest" When the queue is full: "block", "drop_newest", or "drop_oldest".
shutdown_timeout 5.0 Max seconds close() waits for the worker to drain.
validate True Make a synchronous getMe check at construction. Set False offline/in tests.
api_base_url "https://api.telegram.org" Override for self-hosted Bot API servers.

Environment variables

Variable Used when
TG_TOKEN token argument is omitted.
TG_CHAT_ID chat_id argument is omitted.
TG_TOPIC_ID topic_id argument is omitted.

Batching

Batch records into fewer messages to stay well under Telegram's rate limits:

handler = TelegramLoggingHandler(
    level=logging.ERROR,
    batch_size=10,  # up to 10 records per message
    flush_interval=10.0,  # ...or flush a partial batch after 10s
)

A batch is sent when it fills (batch_size) or when flush_interval elapses, whichever comes first.

parse_mode / rich formatting

Set parse_mode and the handler escapes each formatted record so log content (tracebacks, arbitrary user data) can never break Telegram's parser:

handler = TelegramLoggingHandler(parse_mode="MarkdownV2")

Because the whole formatter output is escaped, a message like v1.2_final is delivered literally rather than 400-ing the request or rendering as accidental formatting.

dictConfig

LOGGING = {
    "version": 1,
    "handlers": {
        "telegram": {
            "()": "tg_logging_handler.TelegramLoggingHandler",
            "level": "ERROR",
            "batch_size": 5,
        },
    },
    "root": {"handlers": ["telegram"], "level": "WARNING"},
}

import logging.config

logging.config.dictConfig(LOGGING)

Inspecting delivery

handler.stats returns an immutable snapshot of cumulative counters:

s = handler.stats
print(s.queued, s.sent, s.batches_sent, s.retries, s.failed, s.dropped)

Shutdown

close() drains the queue (bounded by shutdown_timeout), stops the worker, and releases the HTTP client. It is idempotent and registered via atexit, so it runs automatically at interpreter exit. For deterministic tests, call it explicitly or use logging.shutdown().

Development

uv sync                          # create .venv + install package + dev deps
uv run pytest                    # run the test suite
uv run ruff check . && uv run mypy   # lint + type-check

Release files for tg-logging-handler 0.1.4

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

Source distribution (sdist)

Source distribution for tg-logging-handler 0.1.4
File Size Uploaded
tg_logging_handler-0.1.4.tar.gz 375.2 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tg-logging-handler 0.1.4
File Interpreter ABI Platform
tg_logging_handler-0.1.4-py3-none-any.whl Python 3 none any Details

Total release size: 404.2 kB

Release files / tg_logging_handler-0.1.4.tar.gz

Download URL tg_logging_handler-0.1.4.tar.gz
Size 375.2 kB
Tags Source
SHA-256 checksum
How to use checksums
498dc3401a19037edd7119eaee50af8506f72c4d598808ef9d9eb98f0a6da32e
BLAKE2b-256 checksum
How to use checksums
09be89ab520e9ce37ccb7079e6530a462d6a6b21e61e7ba6bdec86ea0458a34b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 17, 2026.

Transparency log

Release files / tg_logging_handler-0.1.4-py3-none-any.whl

Download URL tg_logging_handler-0.1.4-py3-none-any.whl
Size 29.1 kB
Tags Python 3
SHA-256 checksum
How to use checksums
0bdf340730a9ae9a99bacb928dcac46182bd18506d2806ea08bf85cecdb68088
BLAKE2b-256 checksum
How to use checksums
2a12cf4d6e8e569655e7ac3d5551eec33289f3c2282e415c0a44f021cf6b2cf5
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

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 Aug 17, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.1.4 This release

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.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