Minimalistic context-aware structured logging for Python
Project description
tinystructlog
Minimalistic context-aware structured logging for Python. Add contextual information to your logs effortlessly with thread-safe and async-safe context management.
Features
- 🎯 Context-Aware: Automatically inject contextual information (user IDs, request IDs, etc.) into all log messages
- 🔒 Thread & Async Safe: Built on Python's
contextvarsfor perfect isolation across threads and async tasks - 🎨 Colored Output: Beautiful ANSI-colored terminal output for better readability
- 🎛️ Flexible Formats: Customizable output with sensible defaults and preset formats (v0.1.1+)
- ⚡ Zero Dependencies: No runtime dependencies - just pure Python
- 📦 Minimal & Focused: Does one thing well - context-aware logging
- 🔧 Zero Configuration: Sensible defaults, works out of the box
- 💡 Type Hints: Full type hint support for better IDE experience
Installation
pip install tinystructlog
Quick Start
from tinystructlog import get_logger, set_log_context
# Create a logger
log = get_logger(__name__)
# Log without context
log.info("Application started")
# Set context - will be included in all subsequent logs
set_log_context(user_id="12345", request_id="abc-def")
log.info("Processing request")
# Output: [2024-01-17 10:30:45] [INFO] [main.<module>:10] [request_id=abc-def user_id=12345] Processing request
log.error("An error occurred")
# Output: [2024-01-17 10:30:46] [ERROR] [main.<module>:11] [request_id=abc-def user_id=12345] An error occurred
Why tinystructlog?
When building applications, especially web services or async workers, you often need to track context across multiple operations:
- Multi-tenant applications: Track which tenant each log belongs to
- Request tracing: Follow a request's journey through your application
- User tracking: Know which user triggered each log event
- Distributed systems: Correlate logs across different parts of your system
tinystructlog makes this trivial while staying out of your way.
Advanced Usage
Temporary Context
Use the log_context context manager for temporary context that automatically cleans up:
from tinystructlog import get_logger, log_context
log = get_logger(__name__)
with log_context(operation="cleanup", task_id="task-123"):
log.info("Starting cleanup") # Includes operation and task_id
perform_cleanup()
# Context automatically removed after the block
log.info("Done") # No operation/task_id context
Async Context Isolation
Each async task gets its own isolated context - no cross-contamination:
import asyncio
from tinystructlog import get_logger, set_log_context
log = get_logger(__name__)
async def handle_request(user_id: str, request_id: str):
set_log_context(user_id=user_id, request_id=request_id)
log.info("Processing request") # Each task logs its own context
await do_work()
# These run concurrently, each with isolated context
await asyncio.gather(
handle_request("user1", "req001"),
handle_request("user2", "req002"),
)
Web Framework Integration
Perfect for web applications - set context per request:
from fastapi import FastAPI, Request
from tinystructlog import get_logger, set_log_context, clear_log_context
import uuid
app = FastAPI()
log = get_logger(__name__)
@app.middleware("http")
async def add_context(request: Request, call_next):
# Add request context
set_log_context(
request_id=str(uuid.uuid4()),
path=request.url.path,
method=request.method,
)
response = await call_next(request)
# Clean up after request
clear_log_context()
return response
Configuration
Control log level via the LOG_LEVEL environment variable:
export LOG_LEVEL=DEBUG
python your_app.py
Supported levels: DEBUG, INFO, WARNING, ERROR, CRITICAL
Custom Log Formats (v0.1.1+)
While tinystructlog comes with sensible defaults, you can customize the output format to match your needs:
Using Preset Formats
from tinystructlog import get_logger, MINIMAL_FORMAT, DETAILED_FORMAT, SIMPLE_FORMAT
# Minimal format - just level and message
log = get_logger(__name__, fmt=MINIMAL_FORMAT)
log.info("Clean output")
# Output: INFO: Clean output
# Detailed format - includes process ID
log = get_logger(__name__, fmt=DETAILED_FORMAT)
log.info("Detailed output")
# Output: [2026-01-18 10:30:45] [INFO] [12345] [module.function:10] Message
# Simple format - level and context only
log = get_logger(__name__, fmt=SIMPLE_FORMAT)
log.info("Simple output")
# Output: [INFO] Message
Custom Format Strings
from tinystructlog import get_logger
# Fully custom format
log = get_logger(__name__, fmt="%(levelname)s | %(message)s")
log.info("Custom")
# Output: INFO | Custom
# Custom with timestamp
log = get_logger(__name__,
fmt="[%(asctime)s] %(message)s",
datefmt="%H:%M:%S"
)
log.info("Time only")
# Output: [10:30:45] Time only
Available Format Variables
Standard Python logging attributes:
%(asctime)s- Timestamp (customize withdatefmt)%(levelname)s- Log level (DEBUG, INFO, etc.)%(module)s- Module name%(funcName)s- Function name%(lineno)d- Line number%(message)s- Log message%(process)d- Process ID
tinystructlog-specific attributes:
%(context)s- Raw context string (e.g., "key1=val1 key2=val2")%(context_str)s- Bracketed context (e.g., " [key1=val1 key2=val2]")- Individual context keys as attributes
Note: Version 0.1.0 had an opinionated, hardcoded format. Starting with v0.1.1, you can customize it while maintaining full backward compatibility. The default format (when no fmt parameter is provided) remains identical to v0.1.0.
Use Cases
- Microservices: Track requests across service boundaries
- Multi-tenant SaaS: Isolate logs by tenant
- Async workers: Track background job context
- APIs: Add request/user context to all endpoints
- Data pipelines: Track which dataset/batch is being processed
Comparison with Alternatives
vs. loguru
loguru is popular for its simplicity and rich features. Key differences:
- Dependencies: tinystructlog has zero dependencies; loguru includes additional libraries
- Context: tinystructlog uses
contextvarsfor automatic thread/async isolation; loguru requires explicitbind()calls - Focus: tinystructlog focuses purely on context management; loguru provides rotation, retention, compression, and more
- Integration: tinystructlog works with standard logging infrastructure; loguru replaces it
Choose tinystructlog for minimal footprint and automatic context propagation. Choose loguru for rich features and advanced error handling.
See the full comparison for details on reproducing tinystructlog's format in loguru.
vs. Standard logging
Standard library logging requires manual context passing or using filters on every logger. tinystructlog handles this automatically with proper async/thread safety.
vs. structlog
structlog is feature-rich but heavier. tinystructlog is minimalistic (zero dependencies!) and focuses purely on context management with sensible defaults for common use cases.
API Reference
get_logger(name: str) -> logging.Logger
Create a configured logger with context support.
set_log_context(**kwargs) -> None
Set context variables that will be included in all subsequent log messages.
clear_log_context(*keys: str) -> None
Clear specific context keys, or all context if no keys provided.
log_context(**kwargs) -> ContextManager
Context manager for temporary context that automatically cleans up.
Documentation
Full documentation is available at tinystructlog.readthedocs.io
Contributing
Contributions are welcome! Please see CONTRIBUTING.md for guidelines.
License
MIT License - see LICENSE for details.
Credits
Created by Andrey Vykhodtsev (Aprova GmbH)
Inspired by the need for simple, reliable context management in production Python applications.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file tinystructlog-0.1.2.tar.gz.
File metadata
- Download URL: tinystructlog-0.1.2.tar.gz
- Upload date:
- Size: 87.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
54575289983bc5bc66ff55e78bf12b4fca978a523d0c6fd12214e9e73e9f363b
|
|
| MD5 |
0ce962d2a6294e7ccf577a9c9273f10a
|
|
| BLAKE2b-256 |
bba3aba1ddcbbbacdc8418b3cbacade2c60a332c969f158821942242071b3f23
|
File details
Details for the file tinystructlog-0.1.2-py3-none-any.whl.
File metadata
- Download URL: tinystructlog-0.1.2-py3-none-any.whl
- Upload date:
- Size: 9.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
326234084dbc6cb79429ab862a79c125516f3d50157aba626b7f90d8212eabb1
|
|
| MD5 |
9b2873e988e1345d2ec4a470688d6b8c
|
|
| BLAKE2b-256 |
a7ff911c64a6a868dc0500b69eb4341c1a916bcde2bbcffd24698e51878b7d37
|