| Crates.io | shared-logging |
| lib.rs | shared-logging |
| version | 0.1.0 |
| created_at | 2026-01-11 17:09:18.986149+00 |
| updated_at | 2026-01-11 17:09:18.986149+00 |
| description | Structured logging library with context propagation, redaction, and HTTP middleware |
| homepage | |
| repository | https://github.com/kelleyblackmore/shared-logging |
| max_upload_size | |
| id | 2036107 |
| size | 119,704 |
A Rust library for structured logging with context propagation, redaction, and HTTP middleware support.
Add to your Cargo.toml:
[dependencies]
shared-logging = "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"] }
If you're developing locally or want to use a Git version:
# Local path
shared-logging = { path = "../shared-logging" }
# Git repository
shared-logging = { git = "https://github.com/kelleyblackmore/shared-logging" }
use shared_logging::{init_logger, Logger};
fn main() {
// Initialize the logger (call once at startup)
init_logger("my-service", "info").unwrap();
// Create a logger instance
let logger = Logger::new("auth");
// Simple logging
logger.info("User authenticated");
logger.warn("Rate limit approaching");
logger.error("Authentication failed");
// Logging with fields
logger.info_with("User logged in", |e| {
e.field("user_id", "user123");
e.field("ip_address", "192.168.1.1");
});
// Logging errors
let result: Result<(), &str> = Err("Database connection failed");
if let Err(e) = result {
logger.log_error("Failed to connect to database", &e);
}
}
use shared_logging::{Logger, ContextBuilder};
// Create context with correlation IDs
let context = ContextBuilder::new()
.trace_id("abc123")
.span_id("def456")
.generate_request_id()
.user_id("user789")
.tenant_id("tenant001")
.build();
// Create logger with context
let logger = Logger::with_context("api", context);
// All logs will include the context fields
logger.info("Processing request");
The library automatically redacts sensitive data:
use shared_logging::Logger;
let logger = Logger::new("api");
// These will be automatically redacted:
logger.info_with("User data", |e| {
e.field("email", "user@example.com"); // Redacted as partial
e.field("password", "secret123"); // Fully redacted
e.field("api_key", "sk_live_abc123xyz"); // Fully redacted
e.field("token", "Bearer eyJhbGc..."); // Fully redacted
});
For HTTP frameworks (e.g., Axum, Actix-web), use the middleware to inject request IDs and log request lifecycle:
use shared_logging::middleware::LoggingMiddleware;
use tower::ServiceBuilder;
// Example with Axum (pseudo-code)
let app = Router::new()
.route("/", get(handler))
.layer(
ServiceBuilder::new()
.layer_fn(|service| LoggingMiddleware::new(service, "my-service"))
);
The middleware will:
use shared_logging::{init_logger, otel};
// Initialize OpenTelemetry (optional)
#[cfg(feature = "otel")]
otel::init_otel_tracing("my-service").unwrap();
// Initialize logger
init_logger("my-service", "info").unwrap();
// Extract context from OTel span
#[cfg(feature = "otel")]
let context = otel::extract_context_from_otel();
Set log level via environment variable:
RUST_LOG=debug cargo run
RUST_LOG=shared_logging=info,my_module=debug cargo run
The logger outputs structured JSON by default. Example output:
{
"timestamp": "2024-01-15T10:30:45.123Z",
"level": "info",
"message": "User authenticated",
"service": "my-service",
"module": "auth",
"request_id": "550e8400-e29b-41d4-a716-446655440000",
"user_id": "user123",
"fields": {
"ip_address": "192.168.1.1"
}
}
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 millisecondsThe library automatically detects and redacts:
Redaction modes:
[REDACTED]****1234 (shows last 4 characters)hash:1234567890 (hashed value)Errors are formatted with:
std::any::type_name)logger.log_error("Operation failed", &my_error);
// Output includes:
// {
// "error": {
// "error_type": "MyError",
// "error_message": "Operation failed",
// "error_stack": ["Error 1", "Error 2"]
// }
// }
field())See the examples/ directory for complete examples.
MIT OR Apache-2.0