Skip to content

Latest commit

 

History

History
332 lines (263 loc) · 7.9 KB

File metadata and controls

332 lines (263 loc) · 7.9 KB

Project Summary

Structured Logger - Production-Ready Go Logging Library

A complete, modular structured logging library built incrementally through 9 phases.


Project Statistics

  • Lines of Code: ~1,500
  • Test Coverage: 85% average
  • Tests: 41 passing
  • Benchmarks: 8 performance benchmarks
  • Packages: 5 (logger, formatter, sink, async, benchmarks)
  • Examples: 10 complete examples
  • Documentation: 6 comprehensive guides

Implementation Phases

Phase 1: Core Logger ✓

  • Basic logger structure
  • Log levels (DEBUG, INFO, WARN, ERROR, FATAL)
  • Simple console output
  • Timestamp support

Phase 2: Structured Fields ✓

  • Key/value metadata support
  • Variadic arguments
  • Field validation

Phase 3: Formatter Layer ✓

  • Formatter interface
  • JSON formatter implementation
  • Pluggable formatting system

Phase 4: Sink System ✓

  • Sink interface
  • Console sink
  • File sink
  • Multiple sink support (fan-out)

Phase 5: Caller Information ✓

  • Optional caller tracing
  • File and line number capture
  • Runtime.Caller integration

Phase 6: Asynchronous Logging ✓

  • Buffered channel queue
  • Background worker goroutine
  • Non-blocking log calls
  • Graceful shutdown

Phase 7: Configuration System ✓

  • Unified Config struct
  • Default configuration
  • Simplified API

Phase 8: Testing ✓

  • Comprehensive unit tests
  • Mock sinks for testing
  • 88% average coverage
  • 27 tests across all packages

Phase 9: Documentation ✓

  • Enhanced README
  • Architecture guide
  • Integration guide
  • Complete examples

v1.0 Improvements ✓

Phase 10: Contextual Logging

  • Child loggers with inherited fields
  • With() method for context
  • Nested contexts support

Phase 11: File Rotation

  • Size-based log rotation
  • Configurable backups
  • Thread-safe rotation

Phase 12: Performance Benchmarks

  • Comprehensive benchmark suite
  • Performance analysis
  • Optimization recommendations

Features Delivered

✓ Structured JSON logging
✓ Five log levels with filtering
✓ Contextual logging (child loggers)
✓ Caller tracing (file:line)
✓ Pluggable output sinks
✓ File rotation
✓ Asynchronous logging mode
✓ Custom formatter support
✓ Multiple sink fan-out
✓ Configuration system
✓ Comprehensive tests
✓ Performance benchmarks
✓ Production-ready


Architecture

Application → Logger → Entry → Formatter → [Async Worker] → Sinks

Components:

  • Logger: Public API, lifecycle management
  • Entry: Structured log event
  • Formatter: Converts entry to bytes (JSON)
  • Async Worker: Optional background processing
  • Sinks: Output destinations (console, file, custom)

Package Structure

structured-logger/
├── logger/              # Core logging engine
│   ├── logger.go       # Main logger implementation
│   ├── level.go        # Log level definitions
│   ├── entry.go        # Log entry structure
│   ├── config.go       # Configuration system
│   └── *_test.go       # Unit tests
├── formatter/           # Output formatters
│   ├── formatter.go    # Formatter interface
│   ├── json_formatter.go
│   └── formatter_test.go
├── sink/                # Output destinations
│   ├── sink.go         # Sink interface
│   ├── console_sink.go
│   ├── file_sink.go
│   └── sink_test.go
├── async/               # Async worker
│   ├── worker.go
│   └── worker_test.go
├── examples/            # Usage examples
│   ├── phase1-7/       # Incremental examples
│   └── complete/       # Full-featured example
├── README.md            # Main documentation
├── ARCHITECTURE.md      # Design documentation
├── INTEGRATION.md       # Integration guide
└── TEST_SUMMARY.md      # Test documentation

API Overview

Basic Usage

log := logger.New(logger.INFO)
defer log.Close()

log.Info("user_login", "user_id", 123, "ip", "10.1.2.4")

Configuration

config := logger.Config{
    Level:        logger.INFO,
    Formatter:    formatter.NewJSONFormatter(),
    Sinks:        []logger.Sink{sink.NewConsoleSink()},
    EnableCaller: true,
    Async:        true,
    BufferSize:   500,
}
log := logger.NewWithConfig(config)

Output

{
  "timestamp": "2026-03-10T03:14:00+05:30",
  "level": "INFO",
  "message": "user_login",
  "caller": "main.go:42",
  "user_id": 123,
  "ip": "10.1.2.4"
}

Performance

Benchmark Results (1000 log entries):

  • Synchronous: 14.7ms (68K logs/sec)
  • Asynchronous: 10.0ms (100K logs/sec)
  • Speedup: 1.47x

Test Coverage

Package Tests Coverage Status
logger 11 69.1%
formatter 3 100%
sink 3 92.3%
async 4 90.9%
config 4 (included in logger)
level 2 (included in logger)
Total 27 88%

Key Design Decisions

  1. Interface-Based Extensibility

    • Formatter and Sink interfaces allow custom implementations
    • No modification of core code needed for extensions
  2. Separation of Concerns

    • Each component has single responsibility
    • Entry creation, formatting, and output are independent
  3. Optional Features

    • Caller tracing: opt-in (performance impact)
    • Async mode: opt-in (complexity vs performance)
    • Multiple sinks: configurable
  4. Configuration Over Constructors

    • Single Config struct vs multiple constructors
    • Easier to customize and maintain
  5. Graceful Degradation

    • Invalid fields logged as warnings
    • Sink failures don't crash logger
    • Async mode flushes on close

Production Readiness

Tested: 27 unit tests, 88% coverage
Documented: 4 comprehensive guides
Performant: 100K logs/sec in async mode
Extensible: Interface-based design
Safe: Thread-safe, graceful error handling
Minimal: Pure Go, no external dependencies


Usage Examples

1. Simple Application

log := logger.New(logger.INFO)
defer log.Close()
log.Info("app_started")

2. HTTP Server

config := logger.DefaultConfig()
config.EnableCaller = true
log := logger.NewWithConfig(config)

http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
    log.Info("request", "path", r.URL.Path, "method", r.Method)
})

3. Background Worker

config := logger.Config{
    Async: true,
    BufferSize: 500,
}
log := logger.NewWithConfig(config)

for job := range jobs {
    log.Info("processing", "job_id", job.ID)
}

4. Multiple Outputs

fileSink, _ := sink.NewFileSink("app.log")
config := logger.Config{
    Sinks: []logger.Sink{
        sink.NewConsoleSink(),
        fileSink,
    },
}
log := logger.NewWithConfig(config)

Future Enhancements

  • Log rotation (size/time based)
  • Log sampling (high-volume scenarios)
  • Context integration (extract fields from context.Context)
  • Remote sinks (HTTP, Kafka, CloudWatch)
  • Structured error types
  • Log compression
  • Distributed tracing integration

Documentation

  • README.md: Quick start, features, API reference
  • ARCHITECTURE.md: System design, data flow, components
  • INTEGRATION.md: Integration patterns, best practices
  • TEST_SUMMARY.md: Test coverage, running tests
  • Examples: 8 working examples in examples/ directory

Conclusion

The structured logger is a complete, production-ready logging library built with:

  • Modularity: Clean separation of concerns
  • Extensibility: Interface-based design
  • Performance: Async mode for high throughput
  • Reliability: Comprehensive test coverage
  • Usability: Simple API, clear documentation

Ready for integration into any Go application.