Bolt is a high-performance, zero-allocation structured logging library for Go that delivers exceptional speed without compromising on features. Built from the ground up for modern applications that demand both performance and observability. Live benchmarks update automatically.
| Library | Operation | ns/op | Allocations | Performance Advantage |
|---|---|---|---|---|
| Bolt v2.0.0 | Simple Log | 63 | 0 | π Industry Leading |
| Bolt v2.0.0 | Float64 | 62 | 0 | β Zero Allocs |
| Bolt v2.0.0 | New Fields (Int8/16/32) | 60 | 0 | β Zero Allocs |
| Zerolog | Enabled | 175 | 0 | 64% slower |
| Zap | Enabled | 190 | 1 | 67% slower |
| Logrus | Enabled | 2,847 | 23 | 98% slower |
Latest benchmarks on Apple M1 - v2.0.0 Lightning Release with production optimizations
- π₯ Zero Allocations: Achieved through intelligent event pooling, buffer reuse, and custom formatters
- β‘ Ultra-Fast: 63ns/op for simple logs, 62ns for Float64, 60ns for new field types
- ποΈ Structured Logging: Rich, type-safe field support (Int8/16/32/64, Uint, Float64, Bool, Str, etc.)
- π OpenTelemetry Integration: Automatic trace and span ID injection
- π¨ Multiple Outputs: JSON for production, colorized console for development
- π§© Extensible: Custom handlers and formatters
- π¦ Minimal Dependencies: Lightweight core with optional OpenTelemetry
- π‘οΈ Type Safe: Strongly typed field methods prevent runtime errors
- π Security: Input validation, JSON injection prevention, buffer limits
go get github.com/felixgeelhaar/boltpackage main
import (
"os"
"github.com/felixgeelhaar/bolt"
)
func main() {
// Create a JSON logger for production
logger := bolt.New(bolt.NewJSONHandler(os.Stdout))
// Simple logging
logger.Info().Str("service", "api").Int("port", 8080).Msg("Server starting")
// Error logging with context
if err := connectDatabase(); err != nil {
logger.Error().
Err(err).
Str("component", "database").
Msg("Failed to connect to database")
}
}// Context-aware logging with OpenTelemetry
contextLogger := logger.Ctx(ctx) // Automatically includes trace/span IDs
// Structured logging with rich types
logger.Info().
Str("user_id", "12345").
Int("request_size", 1024).
Bool("authenticated", true).
Float64("processing_time", 0.234).
Time("timestamp", time.Now()).
Dur("timeout", 30*time.Second).
Any("metadata", map[string]interface{}{"region": "us-east-1"}).
Msg("Request processed")
// Create loggers with persistent context
userLogger := logger.With().
Str("user_id", "12345").
Str("session_id", "abc-def-ghi").
Logger()
userLogger.Info().Msg("User action logged") // Always includes user_id and session_id// Pretty console output for development
logger := bolt.New(bolt.NewConsoleHandler(os.Stdout))
logger.Info().
Str("env", "development").
Int("workers", 4).
Msg("Application initialized")
// Output: [2024-01-15T10:30:45Z] INFO Application initialized env=development workers=4Bolt achieves zero allocations through several key innovations:
- Event Pooling: Reuses event objects via
sync.Pool - Buffer Management: Pre-allocated buffers with intelligent growth
- Direct Serialization: Numbers and primitives written directly to buffers
- String Interning: Efficient string handling without unnecessary copies
- Fast Number Conversion: Custom integer-to-string functions optimized for common cases
- Allocation-Free RFC3339: Custom timestamp formatting without
time.Format()allocations - Intelligent Buffering: Buffers sized to minimize reallocations for typical log entries
- Branch Prediction: Code structured to optimize for common execution paths
// Automatic format selection based on environment
logger := bolt.New(bolt.NewJSONHandler(os.Stdout))
// Set via environment variables:
// BOLT_LEVEL=info
// BOLT_FORMAT=json (production) or console (development)import (
"context"
"go.opentelemetry.io/otel"
"github.com/felixgeelhaar/bolt"
)
func handleRequest(ctx context.Context) {
// Trace and span IDs automatically included
logger := baseLogger.Ctx(ctx)
logger.Info().
Str("operation", "user.create").
Msg("Processing user creation")
// Logs will include:
// {"level":"info","trace_id":"4bf92f3577b34da6a3ce929d0e0e4736","span_id":"00f067aa0ba902b7","operation":"user.create","message":"Processing user creation"}
}Test Bolt's performance on your system:
# Run Bolt's internal performance tests
go test -bench=. -benchmem
# Run specific benchmarks
go test -bench=BenchmarkZeroAllocation -benchmem
go test -bench=BenchmarkFloat64 -benchmemComparison benchmarks (Bolt vs Zerolog vs Zap vs slog) are maintained in a separate module to avoid adding unnecessary dependencies for users. To run comparison benchmarks:
cd benchmarks
go test -bench=. -benchmem
# Compare specific libraries
go test -bench=BenchmarkBolt -benchmem
go test -bench=BenchmarkZerolog -benchmem
go test -bench=BenchmarkZap -benchmem
go test -bench=BenchmarkSlog -benchmemSee benchmarks/README.md for detailed instructions.
BenchmarkZeroAllocation-8 13,483,334 87 ns/op 0 B/op 0 allocs/op
BenchmarkFloat64Precision-8 18,972,231 62 ns/op 0 B/op 0 allocs/op
BenchmarkNewFieldMethods/Int32-8 20,163,957 60 ns/op 0 B/op 0 allocs/op
BenchmarkConsoleHandler-8 2,427,907 491 ns/op 144 B/op 10 allocs/op
BenchmarkDefaultLogger-8 12,723,752 106 ns/op 168 B/op 0 allocs/op
Note: ConsoleHandler has ~10 allocations due to colorization and formatting. Use JSONHandler for zero-allocation production logging.
Bolt includes multiple security features to protect against common logging vulnerabilities:
// Automatic input validation prevents log injection attacks
logger.Info().
Str("user_input", userProvidedData). // Automatically JSON-escaped
Msg("User data logged safely")
// Built-in size limits prevent resource exhaustion
// - Keys: max 256 characters
// - Values: max 64KB
// - Total buffer: max 1MB per log entry// All operations are thread-safe with atomic operations
var logger = bolt.New(bolt.NewJSONHandler(os.Stdout))
// Safe to use across multiple goroutines
go func() {
logger.SetLevel(bolt.DEBUG) // Thread-safe level changes
}()
go func() {
logger.Info().Msg("Concurrent logging") // Safe concurrent access
}()// Comprehensive error handling with custom error handlers
logger := bolt.New(bolt.NewJSONHandler(os.Stdout)).
SetErrorHandler(func(err error) {
// Custom error handling logic
fmt.Fprintf(os.Stderr, "Logging error: %v\n", err)
})- No eval() or injection vectors: All data is properly escaped during JSON serialization
- Memory safety: Buffer size limits prevent unbounded memory usage
- Structured output: JSON format prevents log format injection
- Controlled serialization: Type-safe field methods prevent data corruption
Extend Bolt with custom output formats:
type CustomHandler struct {
output io.Writer
}
func (h *CustomHandler) Write(e *bolt.Event) error {
// Custom formatting logic
formatted := customFormat(e)
_, err := h.output.Write(formatted)
return err
}
logger := bolt.New(&CustomHandler{output: os.Stdout})Symptom: Logging is slower than expected
# Check if you're in debug mode accidentally
echo $BOLT_LEVEL # Should be 'info' or 'warn' for production
# Run benchmarks to compare
go test -bench=BenchmarkZeroAllocation -benchmemSymptom: Memory usage is high
// Ensure you're calling Msg() to complete log entries
logger.Info().Str("key", "value") // β Event not completed
logger.Info().Str("key", "value").Msg("message") // β
Proper completion
// Check for event leaks in error handling
if err != nil {
// β This leaks events if err is always nil
logger.Error().Err(err).Msg("error occurred")
}
if err != nil {
// β
Proper conditional logging
logger.Error().Err(err).Msg("error occurred")
}Symptom: Race conditions detected
# Run tests with race detector
go test -race ./...
# The library itself is thread-safe, but output destinations may not be
# Use thread-safe output for concurrent scenariosSolution: Use thread-safe outputs
// β bytes.Buffer is not thread-safe
var buf bytes.Buffer
logger := bolt.New(bolt.NewJSONHandler(&buf))
// β
Use thread-safe alternatives
type SafeBuffer struct {
buf bytes.Buffer
mu sync.Mutex
}
func (sb *SafeBuffer) Write(p []byte) (n int, err error) {
sb.mu.Lock()
defer sb.mu.Unlock()
return sb.buf.Write(p)
}Symptom: Logs not appearing
// Check log level configuration
logger := bolt.New(bolt.NewJSONHandler(os.Stdout))
logger.SetLevel(bolt.ERROR) // Will suppress Info/Debug logs
logger.Debug().Msg("Debug message") // Won't appear
logger.Error().Msg("Error message") // Will appearSymptom: Wrong output format
# Check environment variables
echo $BOLT_FORMAT # Should be 'json' or 'console'
echo $BOLT_LEVEL # Should be valid level name
# Override with code if needed
logger := bolt.New(bolt.NewConsoleHandler(os.Stdout)).SetLevel(bolt.DEBUG)Symptom: OpenTelemetry traces not appearing
// Ensure context contains valid span
span := trace.SpanFromContext(ctx)
if !span.SpanContext().IsValid() {
// No active span in context
logger.Info().Msg("No trace context")
}
// Use context-aware logger
ctxLogger := logger.Ctx(ctx)
ctxLogger.Info().Msg("With trace context")# Profile memory usage
go test -bench=BenchmarkZeroAllocation -memprofile=mem.prof
go tool pprof mem.prof
# Profile CPU usage
go test -bench=BenchmarkZeroAllocation -cpuprofile=cpu.prof
go tool pprof cpu.prof
# Check for allocations
go test -bench=. -benchmem | grep allocs- Check the documentation: Review API documentation and examples
- Run diagnostics: Use built-in benchmarks and race detection
- Community support: Open GitHub issues with minimal reproduction cases
- Security issues: Follow responsible disclosure in SECURITY.md
β Perfect for:
- High-throughput APIs (>10k req/sec)
- Microservices with strict latency requirements
- Applications requiring GC-friendly logging
- Production systems where performance is critical
- Containerized/cloud-native deployments
β Not suitable for:
- Real-time systems with <10Β΅s latency requirements - Bolt's 60-300ns overhead may be significant
- Extreme memory constraints (<1MB heap) - Event pool requires ~8-64KB overhead
- Non-Go applications - Bolt is Go-specific
- Legacy log parsers - Requires JSON-compatible log processors
| Scenario | Overhead | Notes |
|---|---|---|
| Simple log (3 fields) | ~63ns | 0 allocations |
| Float64 field | ~62ns | 0 allocations |
| New integer fields | ~60ns | 0 allocations |
| Console handler | ~491ns | 10 allocations (acceptable for dev) |
| HTTP request logging | ~0.01% CPU | Negligible impact |
| High throughput (100k/sec) | <1% CPU | Scales linearly |
Memory Profile:
- Event pool: 8-64KB (steady state)
- Per-event: ~336 bytes (pooled, reused)
- Production API (50k req/sec): ~2-4MB total
See GitHub Pages for live benchmarks and performance analysis.
apiVersion: apps/v1
kind: Deployment
metadata:
name: bolt-app
spec:
template:
spec:
containers:
- name: app
image: myapp:latest
env:
- name: LOG_FORMAT
value: "json"
- name: LOG_LEVEL
value: "info"
- name: OTEL_EXPORTER_OTLP_ENDPOINT
value: "http://otel-collector:4317"π Full example: See examples/kubernetes/
AWS Lambda:
logger := bolt.New(bolt.NewJSONHandler(os.Stdout)).With().
Str("function", os.Getenv("AWS_LAMBDA_FUNCTION_NAME")).
Str("region", os.Getenv("AWS_REGION")).
Logger()Google Cloud Run:
logger := bolt.New(bolt.NewJSONHandler(os.Stdout)).With().
Str("service", os.Getenv("K_SERVICE")).
Str("revision", os.Getenv("K_REVISION")).
Logger()Azure Functions:
logger := bolt.New(bolt.NewJSONHandler(os.Stdout)).With().
Str("function", os.Getenv("WEBSITE_SITE_NAME")).
Logger()π More examples: See examples/ directory for additional cloud platform integrations
Gin:
r.Use(BoltLogger(logger))Echo:
e.Use(BoltLoggerWithTracing(logger))Fiber:
app.Use(BoltLogger(logger))Chi:
r.Use(BoltLogger(logger))π Framework integration: See examples/microservices/ for middleware examples
- Use JSON handler (zero allocations)
- Set appropriate log level (info/warn for production)
- Configure OpenTelemetry for distributed tracing
- Set up log aggregation (Fluentd, Fluent Bit, etc.)
- Enable monitoring (Prometheus, Grafana)
- Configure health checks and metrics endpoints
- Test graceful shutdown and log flushing
- Validate security (no sensitive data in logs)
- Set resource limits (memory, CPU)
- Enable alerting on error rates
π Production examples: See examples/ directory
- π Live Benchmarks - Real-time performance metrics
- ποΈ API Documentation - Complete API reference
- π― Production Examples - REST API, gRPC, Batch processing, K8s
- π Observability - OpenTelemetry, Prometheus integration
- Framework examples: Gin, gRPC
- Cloud deployments: Kubernetes, Batch Processing
- Monitoring setup: Prometheus, OpenTelemetry
- π€ Contributing - How to contribute to Bolt
- π‘οΈ Security Policy - Security vulnerability reporting
- π Code of Conduct - Community standards
We welcome contributions! Please fork the repository and submit pull requests from your fork.
- Fork this repository on GitHub
- Clone your fork:
git clone https://github.com/YOUR_USERNAME/bolt.git cd bolt - Create a feature branch:
git checkout -b feature/your-feature-name
- Make your changes and ensure tests pass:
go test ./... go test -bench=. -benchmem # Optional: Run comparison benchmarks cd benchmarks && go test -bench=. -benchmem
- Submit a pull request from your fork
π Detailed guidelines: See CONTRIBUTING.md for complete contribution workflow, coding standards, and performance requirements.
MIT License - see LICENSE file for details.
Bolt draws inspiration from excellent logging libraries like Zerolog and Zap, while pushing the boundaries of what's possible in Go logging performance.
