Skip to main content

A lightweight, GDPR-safe, threadsafe, async-ready Python logger with zero dependencies.

Project description

taipan-logger

A lightweight, GDPR-safe, threadsafe, async-ready Python logger. No external dependencies. Drop it in, configure once, log forever.

Python License Version Community


The Taipan is one of the most venomous snakes in the world, known for striking with extreme precision - never missing its target.

That philosophy carries over here. Taipan-logger hits exactly what matters: structural metadata, timing, thread context and error traces. Nothing more, nothing less. No user data, no guesswork, no bloat. Precise by design. GDPR-safe by default.


The Problem

Building a microservice architecture means building multiple services. Each service runs in its own container, each container needs its own logger.

The alternative - copy-pasting and rewriting a logger six times - was never an option. So instead, one day was spent building it properly once. The result is taipan-logger: a logger you drop in, import, and forget about. No per-project configuration hell, no over-engineered setup, no copy-paste maintenance.

A centralized logging service might seem like a cleaner solution at first glance - it is not. A shared logger across containers is a single point of failure. If it goes down, every service goes blind at exactly the moment you need visibility the most. Finding bugs without logs in a microservice environment is not debugging, it is guesswork.

Each service logs for itself. Isolated, reliable, always available.

And because every service handles real user requests, GDPR-compliance was non-negotiable from day one. No user data, no content, no addresses. Only structural metadata - timing, threads, function traces, errors.

One import. One optional configure call. Done.


Features

  • Class-based singleton - all state lives at class level, no instance needed, one logger across your entire service
  • GDPR-safe - no user data, no content, only structural metadata logged by default
  • Threadsafe - uses threading.Lock for all write operations
  • Async-ready - @trace detects and wraps both sync and async functions automatically
  • Zero dependencies - pure Python standard library only
  • Debug toggle at runtime - switch debug mode via environment variable without restart
  • Automatic project root detection - finds your project root by scanning for known anchor files, no path config needed
  • Log rotation - daily rotation with configurable backup count and optional keep-open mode
  • Custom log format - configure field order, datetime format, and a per-service prefix
  • Smart exception deduplication - the @trace decorator logs each exception object only once, even when it is re-raised and caught multiple times across nested call frames

Installation

pip install taipan-logger

taipan-logger on PyPI


Usage

Quickstart

from taipan_logger import taipan, configure, trace

# Optional: configure before first log call
configure(special_prefix="MY-SERVICE", debug=True)

# Manual logging
taipan.info("Service started")
taipan.warning("Something looks off")
taipan.error("Something broke")
taipan.debug("Verbose trace info")

# Automatic function tracing
@trace
def add(x: int, y: int) -> int:
    return x + y

@trace
async def fetch_data(url: str) -> dict:
    ...

For full working examples see:


Naming Conventions

This are the public interfaces you can use:

Name Type Description
taipan SimpleNamespace Logging interface: .debug(), .info(), .warning(), .error(), .configure()
configure function Direct alias for TaipanLogger.configure
trace decorator Wraps sync and async functions with automatic trace logging

configure()

Call this once before the first log entry. If the logger has already written anything, it raises an exception. Nothing needs to be configured - all defaults work out of the box.

from taipan_logger import configure

configure(special_prefix="MY-SERVICE", debug=True)
Parameter Type Default Description
field_order list[str] ['DATETIME', 'LOG_STATUS', 'TRACEID', 'THREAD', 'FUNC_NAME', 'MESSAGE'] Order of fields in each log line
datetime_format str 'YYYY-MM-DD - hh:mm:ss:mimimi' Custom datetime format using taipan placeholders
log_path Path|str auto-detected Override log directory
log_path_relative bool True Resolve log_path relative to the caller's file
log_name str 'taipan.log' Base log file name (date prefix is added automatically)
max_old_logs int 10 Max number of rotated log files to keep
delete_older_logs bool True Delete old logs beyond max_old_logs
special_prefix str None String prepended to every log line, useful to identify the service
debug bool False Enable debug level logging
keep_log_open bool False Disable daily rotation - keep one log file until restart
env_check_interval int 120 Seconds between environment variable polls
exception_hook_in_is_set bool False If True, @trace skips logging exception details and only logs that a hook is active - the hook itself is responsible for the output

Minimum required fields if you override field_order: DATETIME, LOG_STATUS, MESSAGE.

Datetime format placeholders

yyyy / YYYY  -> 2026              yy / YY  -> 26
MM           -> 04 (with zero)    M  -> 4
dd / DD      -> 05 (with zero)    d  -> 5
hh / HH      -> 13 (with zero)    h  -> 13
mm           -> 45 (with zero)    m  -> 45
ss           -> 07 (with zero)    s  -> 7
mimimi       -> 234 (ms, 3 digits)
mimi         -> 23  (ms, 2 digits)
mi           -> 2   (ms, 1 digit)

You could use it like this (You decide how you want to read it):

configure(datetime_format="dd~MM~yy §hh:mm'ss§ [mimimi]")

Output:

[08~05~26 §19:51'51§ [381]]

@trace Decorator

Wraps any function or method - sync or async - and automatically logs entry, exit, duration, and exceptions. Each call gets its own unique trace_id, which groups the before/after/error lines together in the log.

from taipan_logger import trace

@trace
def my_function(x: int, y: int) -> int:
    return x + y

@trace
async def my_async_function(url: str) -> dict:
    ...

Works with other decorators. Always place @trace closest to the function definition:

@repeat(times=3)
@trace
def say_hello(name: str) -> str:
    return f"Hello {name}"

Exception deduplication: when an exception is re-raised and passes through multiple @trace-wrapped frames, it is logged only once - at the frame where it originally occurred. A new exception object (e.g. wrapping the original via raise RuntimeError(...) from e) is treated as a distinct exception and logged separately.


Runtime Debug Toggle

Set the environment variable DEBUG_ENABLED to switch debug mode at runtime without restarting:

DEBUG_ENABLED=true
DEBUG_ENABLED=false

Taipan polls this every env_check_interval seconds (default 120s).


Log Output

Each line follows the configured field order. Default format:

[DATETIME][LOG_STATUS][TRACEID][THREAD][FUNC_NAME]MESSAGE

With an optional special_prefix prepended before the first bracket.

[2026-05-08 - 19:51:51:381][DEBUG][acaea09e][MainThread][path2_level1]|BeforeFunction| Argument infos: 0 xargs and 0 kwargs
[2026-05-08 - 19:51:51:382][DEBUG][f29e443d][MainThread][path2_level2]|BeforeFunction| Argument infos: 0 xargs and 0 kwargs
[2026-05-08 - 19:51:51:382][ERROR][f29e443d][MainThread][path2_level2]RuntimeError: Wrapped error in path 2

Notice [f29e443d] appears on the DEBUG before-entry and the ERROR line - the shared trace_id lets you follow a single call through any depth of nesting or threading.

See a full log example at example_files/2026-05-08_23-16-47_taipan.log.


Project Root Detection

On first import, Taipan walks upward from the entry point file and scores each parent directory by how many known anchor files it contains:

.venv, requirements.txt, .gitignore, README.md, pyproject.toml, setup.py, setup.cfg, .git

The directory with the highest score is used as project root. Logs are written to <project_root>/logs/.

Override with configure(log_path=...) if the detection does not match your layout.


Exceptions

Exception When it is raised
TaipanRootNotFoundError Project root could not be detected during init
TaipanLogPathError Log directory could not be created or the given path does not exist
TaipanToLateConfiguredExceptionTaipan configure() called after the first log entry was written
TaipanWrongConfiguredError Internal field configuration is invalid

All exceptions extend TaipanOOPException, which adds .message, .error_code, and .data attributes directly on the exception object for structured error handling.


What this is not for and what we excluded

Feature / Class Reason excluded
Network / remote logging Out of scope - use a dedicated log aggregator per service
Log parsing or querying Taipan writes logs, it does not read them
Structured JSON output Plain text format is intentional - line-based, human-readable
User data in log lines GDPR requirement - never log content, only structure
BaseException subclassing Not caught by @trace intentionally - KeyboardInterrupt etc. must not be swallowed
Centralized shared logger Architectural decision - every service owns its own logger

Compatibility

Python 3.12 or higher. No external dependencies. Works on Linux, macOS, and Windows.


License

This project is licensed under the Sora Open Source Software License (SOSS) v1.0.
See LICENSE for full terms.
Always refer to the latest version at: github.com/soss-community


Community and contributing

Part of the Sora Open Source Software community.
Visit github.com/soss-community
for contribution guidelines, issue tracking, and discussion.

This software is provided without official support.
For business support, contact the author via GitHub before offering support services.
Approved providers will be listed here. The author reserves the right to revoke any listing.

Author: sora7672
Organization: soss-community
Website: soss.page

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

taipan_logger-2.0.0.tar.gz (24.4 kB view details)

Uploaded Source

Built Distribution

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

taipan_logger-2.0.0-py3-none-any.whl (21.1 kB view details)

Uploaded Python 3

File details

Details for the file taipan_logger-2.0.0.tar.gz.

File metadata

  • Download URL: taipan_logger-2.0.0.tar.gz
  • Upload date:
  • Size: 24.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for taipan_logger-2.0.0.tar.gz
Algorithm Hash digest
SHA256 d8ba31f6c6ade4a6fae471f20d2032c466961d17f29fed35c844984530c55b07
MD5 19e83c3db67a6ff7b3807674b015d1e5
BLAKE2b-256 d9f1b712df51ddccac74a1a8fa94f4caba4267ea0d47e4107dbddf32ec1b4bef

See more details on using hashes here.

File details

Details for the file taipan_logger-2.0.0-py3-none-any.whl.

File metadata

  • Download URL: taipan_logger-2.0.0-py3-none-any.whl
  • Upload date:
  • Size: 21.1 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.12.4

File hashes

Hashes for taipan_logger-2.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 d1fadd76160043ed90f87dd94c69f59fd6ffb401e3f9c0d067a814cff53d97df
MD5 6ec9c660a00aae3d8ff26d9a94d0050d
BLAKE2b-256 0073bad635c2b667f957c1cc210601a0315e0c36efd5edacd5f1a678e46f70c1

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