LogXide vs Structlog¶
This page provides a detailed deep-dive comparing LogXide to Structlog. For a high-level compatibility overview, see the Compatibility Overview.
Structlog focuses on structured/context-rich logging, while LogXide focuses on raw performance with stdlib compatibility. They serve different use cases but overlap in production Python logging.
Architecture¶
| Aspect | LogXide | Structlog |
|---|---|---|
| Implementation | Rust native core via PyO3 | Pure Python |
| GIL Strategy | Zero-GIL (drops immediately) | Holds GIL for entire pipeline |
| Core concept | stdlib logging compatible |
Processor pipeline |
| Log Record | Rust Arc<LogRecord> |
Python dict (event dict) |
| Thread Safety | Rust RwLock |
Thread-local context |
Performance: Handler-by-Handler Benchmark¶
All benchmarks run on macOS ARM64 (Apple Silicon), Python 3.12 / 3.14, averaged across 3 runs.
Handler-by-handler benchmarks use 10,000 iterations (basic_handlers_benchmark.py); File I/O scenario benchmarks (Simple / Structured / Error Logging) use 100,000 iterations (compare_loggers.py).
LogXide drops the GIL immediately and delegates formatting and I/O to Rust-native BufWriter (file) or crossbeam channels (stream/HTTP), avoiding Python overhead entirely.
Performance Summary¶
| Handler / Scenario | Structlog | LogXide | LogXide vs Structlog |
|---|---|---|---|
| FileHandler (Raw I/O) | ~98,000 Ops/sec | 281,741 Ops/sec | 2.8x faster |
| Simple Logging | 122,995 Ops/sec | 281,741 Ops/sec | 2.2x faster |
| Structured Logging | 96,546 Ops/sec | 266,242 Ops/sec | 2.7x faster |
| Error Logging | ~85,000 Ops/sec | 251,238 Ops/sec | 2.9x faster |
*Note: Structlog relies on Python's stdlib for actual file output, so its theoretical maximum is capped by stdlib throughput, minus the overhead of its JSON/Console render processors. LogXide bypasses this completely via Rust BufWriter.
Feature Comparison Matrix¶
| Feature | LogXide | Structlog |
|---|---|---|
| stdlib API compatible | ⚠️ (common patterns; subclassing/custom formatters limited) | ❌ (wrapper layer) |
basicConfig() |
✅ | ❌ |
dictConfig() |
✅ | ❌ (requires stdlib bridge) |
| Processor pipeline | ❌ | ✅ (core feature) |
Context binding (bind()) |
❌ | ✅ |
| JSON rendering | ✅ (HTTPHandler) | ✅ (JSONRenderer) |
| Console rendering | ✅ (ColorFormatter) |
✅ (ConsoleRenderer) |
| FileHandler | ✅ (Rust BufWriter) | ⚠️ (via stdlib) |
| HTTPHandler (async batch) | ✅ | ❌ |
| OTLPHandler | ✅ | ❌ |
| TimedRotatingFileHandler | ✅ (Rust + gzip) | ⚠️ (via stdlib) |
| Sentry integration | ✅ (native) | ⚠️ (stdlib bridge) |
⚠️ Compatibility Caveats¶
LogXide prioritizes performance over full stdlib compatibility. Before adopting, note:
- Custom Python formatters:
logging.Formattersubclasses are not called; format strings are processed natively in Rust - Subclassing:
LogRecordandLoggerare Rust types and cannot be subclassed - Custom Python handlers: Accepted via
addHandler()but bypass the Rust performance pipeline - pytest
caplog: LogXide provides a custom plugin (auto-registered via entry point); requires explicitlogger.addHandler(caplog.handler)— see Testing Guide
For the complete compatibility matrix, see Compatibility.
When to Use Which¶
Choose LogXide when:¶
- Performance is the priority — 2.2–2.9x faster across real-world scenarios, leveraging Rust to bypass the GIL.
- You have existing stdlib code — Minimal migration cost; API-compatible for common patterns.
- You need native production handlers — Async HTTP batching, OTLP export, and native Sentry integration without Python-side overhead.
- Framework integration — Transparently hooks into Django/FastAPI
dictConfig.
Choose Structlog when:¶
- Structured data is core — A chainable processor pipeline for field transformation/filtering is essential.
- Context binding is a must — You heavily rely on
.bind()or thread-local context variables to track requests. - Custom processors — You need extreme flexibility in mutating log records before they hit the output.
- JSON-first architecture — Every single output must be rigidly structured JSON.