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.
Metadata
Release files for tinystructlog 0.1.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| tinystructlog-0.1.2.tar.gz | 87.1 kB | Without provenance | Details for tinystructlog-0.1.2.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| tinystructlog-0.1.2-py3-none-any.whl | Python 3 | none | any | Details for tinystructlog-0.1.2-py3-none-any.whl |
Total release size: 97.1 kB
Release files / tinystructlog-0.1.2.tar.gz
| Download URL | tinystructlog-0.1.2.tar.gz |
|---|---|
| Size | 87.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
54575289983bc5bc66ff55e78bf12b4fca978a523d0c6fd12214e9e73e9f363b
|
|
BLAKE2b-256 checksum How to use checksums |
bba3aba1ddcbbbacdc8418b3cbacade2c60a332c969f158821942242071b3f23
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / tinystructlog-0.1.2-py3-none-any.whl
| Download URL | tinystructlog-0.1.2-py3-none-any.whl |
|---|---|
| Size | 9.9 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
326234084dbc6cb79429ab862a79c125516f3d50157aba626b7f90d8212eabb1
|
|
BLAKE2b-256 checksum How to use checksums |
a7ff911c64a6a868dc0500b69eb4341c1a916bcde2bbcffd24698e51878b7d37
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for tinystructlog 0.1.2
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.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.