Compatibility Overview¶
LogXide is a high-performance logging library with a familiar API inspired by Python's standard logging module. It delivers significant performance improvements through its Rust native core, prioritizing speed over perfect compatibility.
For common use cases, LogXide provides a highly compatible experience. Standard patterns like getLogger(), basicConfig(), dictConfig, and built-in handlers work with minimal or no code changes. However, LogXide is not a drop-in replacement for every stdlib logging scenario. Its Zero-GIL architecture means some advanced patterns, particularly those involving custom Python subclasses or deep monkeypatching, are not supported.
This document provides a high-level compatibility overview. For detailed comparisons against specific logging libraries, see the deep-dive guides below.
Quick Compatibility Summary¶
| Feature | Status | Notes |
|---|---|---|
Basic logging API (getLogger, info, debug, etc.) |
✅ | Familiar stdlib-like API |
basicConfig() |
✅ | Direct mapping to LogXide handlers |
dictConfig() |
✅ | Use logxide.config.dictConfig for Django/FastAPI |
Standard formatters (%-style, {}-style) |
✅ | Processed natively in Rust |
| FileHandler, StreamHandler, RotatingFileHandler | ✅ | Rust-native implementations |
Custom Python formatters (subclassed Formatter) |
❌ | Format strings work; custom format() methods don't |
| Custom Python handlers | ⚠️ | Accepted; run synchronously in Python alongside Rust pipeline |
Subclassing LogRecord or Logger |
❌ | Rust types, not subclassable |
pytest caplog |
⚠️ | Use caplog_logxide fixture instead |
| StringIO capture | ❌ | Use file-based logging for tests |
The Zero-GIL Architecture¶
LogXide's performance comes from its fundamental architectural differences:
Standard library logging: Creates a Python LogRecord object for every log call, then recursively bubbles it through all loggers while holding the GIL with threading.RLock().
LogXide: Drops the GIL immediately and packs raw attributes into a natively dispatched Rust Arc<LogRecord>. Formatting, filtering, bubbling, and I/O all happen outside Python's GIL in Rust.
Because of this, any custom logic that overrides standard Python implementations, such as subclassed Formatters with custom format() methods, will not execute natively.
Supported Patterns ✅¶
- Basic Configuration:
logging.basicConfig()maps directly to LogXide - Structural Configuration:
logxide.config.dictConfigtranslates Python dictionary configurations (Django, FastAPI) to native Rust objects - Logger Hierarchy: Dot-delimited logger names (e.g.,
app.db.sql) bubble matching Python's resolution logic - Standard Formatting:
%-style and{}-style placeholders, including{asctime}, map to Rust's Chrono formats - Standard Handlers: StreamHandler, FileHandler, RotatingFileHandler behavior replicated in Rust
- Exception Logging:
exc_info=Truecorrectly fetches and logs stack traces - Third-party Interception:
logxide.intercept_stdlib()captures logs from libraries using standard logging
Unsupported Patterns ❌¶
1. Custom Python Formatters¶
LogXide maps the format pattern string directly into Rust. If you subclass logging.Formatter to mutate records in a custom format(self, record) method, this method will not be called because no pure-Python LogRecord is materialized.
Alternative: Use JSON templates via logxide.HTTPHandler or transform output at the application edge.
2. Custom Python Handlers¶
If you create a custom Python handler (e.g., class MailLog(logging.Handler)), LogXide accepts it via addHandler(). LogXide will execute its .handle() method with a Python LogRecord alongside the Rust native pipeline. This means the event fires in both pipelines, but the Python handler runs synchronously on the Python side, losing the Rust native zero-GIL concurrency benefits.
3. Standard Library Unit Tests¶
LogXide fails CPython's test_logging.py unit tests. These tests validate locking behavior, internal .handlers array mutability, and .disabled states using memory assertions that conflict with Rust's encapsulated states and RwLocks.
Detailed Comparison Guides¶
For side-by-side comparisons with specific logging libraries, including benchmark data and migration guidance:
| Comparison | Description |
|---|---|
| LogXide vs stdlib | Handler-by-handler performance vs Python's logging module, feature matrix, and migration path for standard use cases |
| LogXide vs Loguru | Architecture differences, performance benchmarks, feature trade-offs, and when to choose each |
| LogXide vs Structlog | Structured logging capabilities, processor pipelines, context binding, and performance comparison |
| LogXide vs Picologging | Rust vs Cython implementation, Python 3.13+ compatibility, and feature ecosystem comparison |
Migration Checklist¶
When migrating an application to LogXide:
- Initialize early: Import and initialize LogXide before framework initialization (Django/Flask/FastAPI)
- Intercept stdlib: Call
logxide.intercept_stdlib()to capture logs from third-party dependencies - Use structural config: Prefer
logxide.config.dictConfigover custom instantiation - Check custom handlers: Verify any custom Python handlers are acceptable. They are accepted via
addHandler()and run alongside the Rust pipeline, which means each log event may be processed twice (once by the Rust pipeline and once by the Python handler) and the Python handler does not run on the zero-GIL Rust path. - Update tests: Replace
caplogwithcaplog_logxideand use file-based logging instead of StringIO
For detailed third-party library compatibility information, see the Third-Party Compatibility Guide.