shared-logging
A Rust library for structured logging with context propagation, redaction, and HTTP middleware support.
Features
- Structured Logger: JSON-formatted logs with consistent field names
- Context Propagation: Automatic propagation of trace_id, span_id, request_id, user_id, and tenant_id
- Redaction Helpers: Automatic redaction of PII, secrets, and tokens
- Standard Event Schema: Consistent field names, levels, and error formatting
- HTTP Middleware: Request ID injection and request lifecycle logging
- OpenTelemetry Support: Optional log correlation with OpenTelemetry traces
Installation
Add to your Cargo.toml:
[]
= "0.1.0"
# Optional: Enable HTTP middleware support
# shared-logging = { version = "0.1.0", features = ["http"] }
# Optional: Enable OpenTelemetry support
# shared-logging = { version = "0.1.0", features = ["otel"] }
# Both optional features
# shared-logging = { version = "0.1.0", features = ["http", "otel"] }
For Local Development
If you're developing locally or want to use a Git version:
# Local path
= { = "../shared-logging" }
# Git repository
= { = "https://github.com/kelleyblackmore/shared-logging" }
Quick Start
Basic Usage
use ;
Context Propagation
use ;
// Create context with correlation IDs
let context = new
.trace_id
.span_id
.generate_request_id
.user_id
.tenant_id
.build;
// Create logger with context
let logger = with_context;
// All logs will include the context fields
logger.info;
Redaction
The library automatically redacts sensitive data:
use Logger;
let logger = new;
// These will be automatically redacted:
logger.info_with;
HTTP Middleware
For HTTP frameworks (e.g., Axum, Actix-web), use the middleware to inject request IDs and log request lifecycle:
use LoggingMiddleware;
use ServiceBuilder;
// Example with Axum (pseudo-code)
let app = new
.route
.layer;
The middleware will:
- Generate or extract request IDs from headers
- Inject request IDs into request and response headers
- Log request start and completion with timing
- Extract trace/span IDs from headers (if present)
OpenTelemetry Integration
use ;
// Initialize OpenTelemetry (optional)
init_otel_tracing.unwrap;
// Initialize logger
init_logger.unwrap;
// Extract context from OTel span
let context = extract_context_from_otel;
Configuration
Log Levels
Set log level via environment variable:
RUST_LOG=debug
RUST_LOG=shared_logging=info,my_module=debug
JSON Output
The logger outputs structured JSON by default. Example output:
Standard Fields
The library uses consistent field names:
service: Service namemodule: Module/component namelevel: Log level (trace, debug, info, warn, error)message: Log messagetimestamp: ISO 8601 timestamptrace_id: OpenTelemetry trace IDspan_id: OpenTelemetry span IDrequest_id: HTTP request identifieruser_id: Authenticated user identifiertenant_id: Multi-tenant organization identifiererror: Error details (when logging errors)http.method: HTTP methodhttp.path: HTTP pathhttp.status: HTTP status codehttp.duration_ms: Request duration in milliseconds
Redaction Patterns
The library automatically detects and redacts:
- PII: Email addresses, credit cards, SSNs, phone numbers
- Secrets: API keys, bearer tokens, JWTs, AWS keys, private keys
Redaction modes:
- Full:
[REDACTED] - Partial:
****1234(shows last 4 characters) - Hash:
hash:1234567890(hashed value)
Error Formatting
Errors are formatted with:
- Error type (from
std::any::type_name) - Error message
- Error chain (if multiple sources)
logger.log_error;
// Output includes:
// {
// "error": {
// "error_type": "MyError",
// "error_message": "Operation failed",
// "error_stack": ["Error 1", "Error 2"]
// }
// }
Architecture
What This Library Owns
- Structured logger wrapper
- Context propagation (trace_id, span_id, request_id, user_id, tenant_id)
- Redaction helpers (PII, secrets, tokens)
- Standard event schema (field names, levels, error formatting)
- HTTP middleware for request IDs and lifecycle logging
- Optional OpenTelemetry log correlation
What This Library Does NOT Own
- Auth token parsing/verification (services handle this)
- Business-specific log fields (services add them via
field())
Examples
See the examples/ directory for complete examples.
License
MIT OR Apache-2.0