shared-logging

Crates.ioshared-logging
lib.rsshared-logging
version0.1.0
created_at2026-01-11 17:09:18.986149+00
updated_at2026-01-11 17:09:18.986149+00
descriptionStructured logging library with context propagation, redaction, and HTTP middleware
homepage
repositoryhttps://github.com/kelleyblackmore/shared-logging
max_upload_size
id2036107
size119,704
Kris (kelleyblackmore)

documentation

README

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:

[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"] }

For Local Development

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" }

Quick Start

Basic Usage

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);
    }
}

Context Propagation

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");

Redaction

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
});

HTTP Middleware

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:

  • 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 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();

Configuration

Log Levels

Set log level via environment variable:

RUST_LOG=debug cargo run
RUST_LOG=shared_logging=info,my_module=debug cargo run

JSON Output

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"
  }
}

Standard Fields

The library uses consistent field names:

  • service: Service name
  • module: Module/component name
  • level: Log level (trace, debug, info, warn, error)
  • message: Log message
  • timestamp: ISO 8601 timestamp
  • trace_id: OpenTelemetry trace ID
  • span_id: OpenTelemetry span ID
  • request_id: HTTP request identifier
  • user_id: Authenticated user identifier
  • tenant_id: Multi-tenant organization identifier
  • error: Error details (when logging errors)
  • http.method: HTTP method
  • http.path: HTTP path
  • http.status: HTTP status code
  • http.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("Operation failed", &my_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

Commit count: 1

cargo fmt