Mire - The blazing-fast, zero-allocation logging library for Go that handles 1M+ logs/second with elegance and efficiency.
Say goodbye to allocation overhead and hello to lightning-fast logging! β‘
Features β’ Installation β’ Quick Start β’ Examples β’ Contributing
- π Highlights
- β¨ Features
- π Installation
- β‘ Quick Start
- π Examples
- βοΈ Configuration Options
- π§ Advanced Configuration
- π Performance
- ποΈ Architecture
- π§ͺ Testing
- π€ Contributing
- π License
- π Support
- π Changelog
- Blazing Fast: 1M+ logs/second with zero-allocation design
- Memory Efficient: No GC pressure, direct byte manipulation
- Production Ready: Thread-safe, async logging, rotation, and more
- Developer Friendly: Simple API, rich configuration, multiple formatters
- Zero-Allocation Design: []byte fields eliminate string conversion overhead
- High Throughput: Optimized for 1M+ logs/second
- Object Pooling: Extensive sync.Pool usage for minimal GC impact
- Cache Conscious: Memory hierarchy optimization for predictable performance
- Structured Logging: Rich metadata with fields, tags, and metrics
- Context-Aware: Automatic trace ID, user ID, and request ID extraction
- Multiple Formatters: Text (with colors), JSON, CSV with custom options
- Asynchronous Logging: Non-blocking with configurable workers
- Distributed Tracing: Built-in support for trace_id, span_id
- Log Sampling: Rate limiting for high-volume scenarios
- Hook System: Extensible for custom processing
- Log Rotation: Size and time-based automatic rotation
- Sensitive Data Masking: Automatic masking of configurable fields
- Field Transformers: Custom transformation functions
- Metrics Integration: Built-in monitoring and metrics collection
- Thread Safe: Safe concurrent use across goroutines
- Go 1.25 or later
# Add to your project
go get github.com/Luvion1/mire
# Or add to your go.mod file directly
go mod init your-project
go get github.com/Luvion1/mire# Use a specific version
go get github.com/Luvion1/mire@v1.0.0
# Use the latest version
go get -u github.com/Luvion1/mireMire has only ONE public API - log.Mire(). Simple, strict, zero-allocation.
All logging operations use this single function signature:
log.Mire(ctx context.Context, level Level, msg []byte, keyvals ...[]byte)No other public APIs to remember. No magic. Just log.Mire().
Mire provides one strict zero-allocation API - log.Mire(). This is the only public API you need to know.
package main
import (
"context"
"github.com/Luvion1/mire/log"
)
func main() {
ctx := context.Background()
// Simple logging with []byte - zero allocation!
log.Mire(ctx, log.INFO, []byte("Application started"))
log.Mire(ctx, log.DEBUG, []byte("Debugging request"))
log.Mire(ctx, log.WARN, []byte("Connection slow"))
log.Mire(ctx, log.ERROR, []byte("Request failed"))
// With fields - using []byte key-value pairs!
log.Mire(ctx, log.INFO,
[]byte("User logged in"),
[]byte("user_id"), []byte("12345"),
[]byte("action"), []byte("login"),
[]byte("success"), []byte("true"))
log.Mire(ctx, log.WARN,
[]byte("High latency"),
[]byte("ms"), []byte("250.5"),
[]byte("threshold"), []byte("200"))
log.Mire(ctx, log.ERROR,
[]byte("Database error"),
[]byte("code"), []byte("ERR_TIMEOUT"),
[]byte("retry"), []byte("3"))
// With context for distributed tracing
ctx = context.WithValue(ctx, "trace_id", "trace-123")
log.Mire(ctx, log.INFO,
[]byte("Processing request"),
[]byte("trace_id"), []byte("trace-123"))
// All log levels
log.Mire(ctx, log.TRACE, []byte("Trace message"))
log.Mire(ctx, log.DEBUG, []byte("Debug message"))
log.Mire(ctx, log.INFO, []byte("Info message"))
log.Mire(ctx, log.WARN, []byte("Warning message"))
log.Mire(ctx, log.ERROR, []byte("Error message"))
// FATAL and PANIC will exit the application
// log.Mire(ctx, log.FATAL, []byte("Critical error - exiting"))
// log.Mire(ctx, log.PANIC, []byte("Panic condition - exiting"))
// Clean shutdown
log.MireClose()
}// The one and only public API for logging
func Mire(ctx context.Context, level Level, msg []byte, keyvals ...[]byte)
// Configure the default logger (optional)
func MireConfig(config logger.LoggerConfig)
// Close the logger and flush all buffers
func MireClose()log.TRACE- Detailed debugging informationlog.DEBUG- General debugging informationlog.INFO- Informational messageslog.WARN- Warning messageslog.ERROR- Error messageslog.FATAL- Critical errors (exits application)log.PANIC- Panic conditions (exits application)
For advanced features like custom formatters, log rotation, hooks, etc., use the logger package directly with LogZ:
package main
import (
"context"
"os"
"github.com/Luvion1/mire/core"
"github.com/Luvion1/mire/formatter"
"github.com/Luvion1/mire/logger"
)
func main() {
ctx := context.Background()
// Create a JSON logger to write to a file
file, err := os.OpenFile("app.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
panic(err)
}
jsonLogger := logger.NewLogger(logger.LoggerConfig{
Level: core.DEBUG,
Output: file,
Formatter: &formatter.JSONFormatter{
PrettyPrint: true,
ShowTimestamp: true,
ShowCaller: true,
EnableStackTrace: true,
},
})
defer jsonLogger.Close()
// Zero-allocation logging with fields using LogZ
jsonLogger.LogZ(ctx, core.INFO,
[]byte("Transaction completed"),
[]byte("transaction_id"), []byte("TXN-001"),
[]byte("amount"), []byte("123.45"))
// Or use context-aware methods (LogZC for no fields)
jsonLogger.LogZC(ctx, core.INFO, []byte("Transaction completed"))
}package main
import (
"context"
"github.com/Luvion1/mire/core"
"github.com/Luvion1/mire/formatter"
"github.com/Luvion1/mire/log"
"github.com/Luvion1/mire/logger"
)
func main() {
// Configure custom logger
log.MireConfig(logger.LoggerConfig{
Level: core.DEBUG,
Formatter: &formatter.JSONFormatter{
PrettyPrint: true,
},
})
ctx := context.Background()
// All Mire calls will now use custom logger
log.Mire(ctx, log.INFO,
[]byte("Application started with custom configuration"),
[]byte("config"), []byte("json"))
log.MireClose()
}config := logger.LoggerConfig{
Level: core.INFO, // Minimum log level
Output: os.Stdout, // Output writer
ErrorOutput: os.Stderr, // Error output writer
Formatter: &formatter.TextFormatter{...}, // Formatter to use (TextFormatter, JSONFormatter, or CSVFormatter)
ShowCaller: true, // Show caller info
CallerDepth: logger.DEFAULT_CALLER_DEPTH, // Depth for caller info
ShowGoroutine: true, // Show goroutine ID
ShowPID: true, // Show process ID
ShowTraceInfo: true, // Show trace information
ShowHostname: true, // Show hostname
ShowApplication: true, // Show application name
TimestampFormat: logger.DEFAULT_TIMESTAMP_FORMAT, // Timestamp format
ExitFunc: os.Exit, // Function to call on fatal
EnableStackTrace: true, // Enable stack traces
StackTraceDepth: 32, // Stack trace depth
EnableSampling: false, // Enable sampling
SamplingRate: 1, // Sampling rate (1 = no sampling)
BufferSize: 1000, // Buffer size
FlushInterval: 5 * time.Second, // Flush interval
EnableRotation: false, // Enable log rotation
RotationConfig: &config.RotationConfig{}, // Rotation configuration
ContextExtractor: nil, // Custom context extractor
Hostname: "", // Custom hostname
Application: "my-app", // Application name
Version: "1.0.0", // Application version
Environment: "production", // Environment
MaxFieldWidth: 100, // Maximum field width
EnableMetrics: false, // Enable metrics
MetricsCollector: nil, // Metrics collector
ErrorHandler: nil, // Error handler function
OnFatal: nil, // Fatal handler function
OnPanic: nil, // Panic handler function
Hooks: []hook.Hook{}, // List of hooks
EnableErrorFileHook: true, // Enable error file hook
BatchSize: 100, // Batch size for writes
BatchTimeout: time.Millisecond * 100, // Batch timeout
DisableLocking: false, // Disable internal locking
PreAllocateFields: 8, // Pre-allocate fields map
PreAllocateTags: 10, // Pre-allocate tags slice
MaxMessageSize: 8192, // Maximum message size
AsyncLogging: false, // Enable async logging
LogProcessTimeout: time.Second, // Timeout for processing logs
AsyncLogChannelBufferSize: 1000, // Buffer size for async channel
AsyncWorkerCount: 4, // Number of async workers
ClockInterval: 10 * time.Millisecond, // Clock interval
MaskStringValue: "[MASKED]", // Mask string value
}textFormatter := &formatter.TextFormatter{
EnableColors: true, // Enable ANSI colors
ShowTimestamp: true, // Show timestamp
ShowCaller: true, // Show caller info
ShowGoroutine: false, // Show goroutine ID
ShowPID: false, // Show process ID
ShowTraceInfo: true, // Show trace info
ShowHostname: false, // Show hostname
ShowApplication: false, // Show application name
FullTimestamp: false, // Show full timestamp
TimestampFormat: logger.DEFAULT_TIMESTAMP_FORMAT, // Timestamp format
IndentFields: false, // Indent fields
MaxFieldWidth: 100, // Maximum field width
EnableStackTrace: true, // Enable stack trace
StackTraceDepth: 32, // Stack trace depth
EnableDuration: false, // Show duration
CustomFieldOrder: []string{}, // Custom field order
EnableColorsByLevel: true, // Color by log level
FieldTransformers: map[string]func(interface{}) string{}, // Field transformers
SensitiveFields: []string{"password", "token"}, // Sensitive fields
MaskSensitiveData: true, // Mask sensitive data
MaskStringValue: "[MASKED]", // Mask string value
}csvFormatter := &formatter.CSVFormatter{
IncludeHeader: true, // Include header row in output
FieldOrder: []string{"timestamp", "level", "message"}, // Order of fields in CSV
TimestampFormat: "2006-01-02T15:04:05", // Custom timestamp format
SensitiveFields: []string{"password", "token"}, // List of sensitive field names to mask
MaskSensitiveData: true, // Whether to mask sensitive data
MaskStringValue: "[MASKED]", // String value to use for masking
FieldTransformers: map[string]func(interface{}) string{}, // Functions to transform field values
}jsonFormatter := &formatter.JSONFormatter{
PrettyPrint: false, // Pretty print output
TimestampFormat: "2006-01-02T15:04:05.000Z07:00", // Timestamp format
ShowCaller: true, // Show caller info
ShowGoroutine: false, // Show goroutine ID
ShowPID: false, // Show process ID
ShowTraceInfo: true, // Show trace info
EnableStackTrace: true, // Enable stack trace
EnableDuration: false, // Show duration
FieldKeyMap: map[string]string{}, // Field name remapping
DisableHTMLEscape: false, // Disable HTML escaping
SensitiveFields: []string{"password", "token"}, // Sensitive fields
MaskSensitiveData: true, // Mask sensitive data
MaskStringValue: "[MASKED]", // Mask string value
FieldTransformers: map[string]func(interface{}) interface{}{}, // Transform functions
}The library includes comprehensive tests and benchmarks:
# Run all tests
go test ./...
# Run with coverage
go test -coverprofile=coverage.out ./...
go tool cover -html=coverage.out
# Run benchmarks
go test -bench=. ./...
# Run the example
go run main.go| Operation | Time per op | Allocs per op | Bytes per op |
|---|---|---|---|
| TextFormatter | 1,390ns/op | 2 allocs/op | 72 B/op |
| JSONFormatter | 2,846ns/op | 1 allocs/op | 24 B/op |
| CSVFormatter | 2,990ns/op | 2 allocs/op | 48 B/op |
| CSVFormatter (Batch) | 21.58ns/op | 0 allocs/op | 0 B/op |
| Logger.Info() | 12,617ns/op | 6 allocs/op | 903 B/op |
| LogEntry Pool Get | 10,713ns/op | 3 allocs/op | 670 B/op |
| LogEntry Pool Put | 5,865ns/op | 0 allocs/op | 123 B/op |
The Mire logging library has been tested across various performance aspects including memory allocation, throughput, and component performance. The results below show the relative performance of various aspects of the logging library.
Benchmark Environment:
- CPU: AMD EPYC 7763 64-Core Processor (64 cores)
- Go Version: 1.25.0
- OS: Linux (Ubuntu on GitHub Actions)
- Architecture: amd64
- Runner: GitHub Actions standard runner
| Operation | Time/Op | Bytes/Op | Allocs/Op |
|---|---|---|---|
| Level Bytes Conversion | 0.93ns | 0 B | 0 allocs |
| Caller Info Pool | 14.07ns | 0 B | 0 allocs |
| Buffer Pool | 13.40ns | 0 B | 0 allocs |
| Int to Bytes | 13.50ns | 0 B | 0 allocs |
| LogEntry Format | 325.5ns | 24 B | 1 allocs |
| Log Level | Time/Op | Bytes/Op | Allocs/Op |
|---|---|---|---|
| Trace | 13,469ns | 279 B | 3 allocs |
| Debug | 22,601ns | 768 B | 6 allocs |
| Info | 18,776ns | 697 B | 5 allocs |
| Warn | 16,319ns | 240 B | 3 allocs |
| Error | 53,810ns | 351 B | 3 allocs |
Note: Significant improvement due to zero-allocation design with direct byte slice operations.
| Formatter | Time/Op | Bytes/Op | Allocs/Op |
|---|---|---|---|
| TextFormatter | 408.8ns | 72 B | 2 allocs |
| JSONFormatter | 1168ns | 24 B | 1 allocs |
| JSONFormatter (Pretty) | 1639ns | 72 B | 2 allocs |
| CSVFormatter | 746.0ns | 48 B | 2 allocs |
| CSVFormatter (Batch) | 9.477ns | 0 B | 0 allocs |
Note: All formatters achieve excellent performance with zero-allocation batch operations.
| Configuration | Time/Ops | Allocs/Operation |
|---|---|---|
| No Fields | 11,644ns/op | 4 allocs/op |
| One Field | 16,605ns/op | 12 allocs/op |
| Five Fields | 22,858ns/op | 21 allocs/op |
| Ten Fields | 30,945ns/op | 38 allocs/op |
| Level | Time/Ops | Allocs/Operation |
|---|---|---|
| Trace | 13,469ns/op | 3 allocs/op |
| Debug | 22,601ns/op | 6 allocs/op |
| Info | 18,776ns/op | 5 allocs/op |
| Warn | 16,319ns/op | 3 allocs/op |
| Error | 53,810ns/op | 3 allocs/op |
Note: Performance improved due to zero-allocation design.
| Formatter | Time/Ops | Allocs/Operation |
|---|---|---|
| TextFormatter | 408.8ns/op | 2 allocs/op |
| JSONFormatter | 1168ns/op | 1 allocs/op |
| JSONFormatter (Pretty) | 1639ns/op | 2 allocs/op |
| CSVFormatter | 746.0ns/op | 2 allocs/op |
| CSVFormatter (Batch) | 9.477ns/op | 0 allocs/op |
Note: Formatters achieve better performance with direct []byte manipulation. CSVFormatter batch shows exceptional performance with sub-22ns/op at zero allocations.
- Handles concurrent operations efficiently
- Concurrent formatter operations: ~100.7ns/op with 1 alloc/op
-
Ultra-Low Memory Allocation: The library achieves 1-6 allocations per log operation with []byte fields directly.
-
Enhanced Performance: Operations are faster across all formatters:
- TextFormatter achieves ~1.4ΞΌs/op with 2 allocations
- JSONFormatter shows ~2.8ΞΌs/op for standard operations and ~10.4ΞΌs/op for pretty printing
- CSVFormatter achieves ~3.0ΞΌs/op with sub-22ns/op batch processing at zero allocations
-
Formatter Efficiency: All formatters now handle []byte fields directly, eliminating string conversion overhead.
-
Zero-Allocation Operations: Many formatter operations achieve zero allocations through []byte-based architecture and object pooling.
-
Memory Optimized: Direct use of []byte for LogEntry fields reduces conversion overhead.
-
Improved Architecture: Uses []byte-first design and cache-friendly memory access patterns.
The Mire logging library v0.0.4 is optimized for high-load applications requiring minimal allocations and maximum throughput.
Mire follows a modular architecture with clear separation of concerns:
+------------------+ +---------------------+ +------------------+
| Your App | -> | Logger Core | -> | Formatters |
| (log.Mire()) | | (configuration, | | (Text, JSON, |
+------------------+ | filtering, | | CSV) |
| pooling) | +------------------+
+---------------------+
| Writers |
| (async, buffered, |
| rotating) |
+---------------------+
| Hooks |
| (custom |
| processing) |
+---------------------+
- Logger Core: Manages configuration, filters, and dispatches log entries
- Formatters: Convert log entries to different output formats with zero-allocation design
- Writers: Handle output to various destinations (console, files, networks)
- Object Pools: Reuse objects to minimize allocations and garbage collection
- Hooks: Extensible system for custom log processing
- Clock: Clock for timestamp operations with minimal overhead
package main
import (
"context"
"github.com/Luvion1/mire/core"
"github.com/Luvion1/mire/formatter"
"github.com/Luvion1/mire/log"
"github.com/Luvion1/mire/logger"
"github.com/Luvion1/mire/util"
)
func main() {
// Configure high-performance logger with zero-allocation
log.MireConfig(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
Formatter: &formatter.TextFormatter{
EnableColors: true,
ShowTimestamp: true,
ShowCaller: true,
ShowTraceInfo: true,
},
AsyncMode: true,
WorkerCount: 4,
ChannelSize: 2000,
})
// Context with trace information
ctx := context.Background()
ctx = util.WithTraceID(ctx, "trace-12345")
ctx = util.WithUserID(ctx, "user-67890")
// Zero-allocation logging using Mire API
log.Mire(ctx, log.INFO,
[]byte("Transaction completed"),
[]byte("user_id"), []byte("12345"),
[]byte("action"), []byte("purchase"),
[]byte("amount"), []byte("99.99"))
// Context-aware logging with distributed tracing
log.Mire(ctx, log.INFO,
[]byte("Processing request"))
// Automatically includes trace_id and user_id from context
log.MireClose()
}package main
import (
"os"
"github.com/Luvion1/mire/core"
"github.com/Luvion1/mire/formatter"
"github.com/Luvion1/mire/logger"
)
func main() {
// Create a CSV logger to write to a file
file, err := os.Create("app.csv")
if err != nil {
panic(err)
}
defer file.Close()
csvLogger := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: file,
Formatter: &formatter.CSVFormatter{
IncludeHeader: true, // Include CSV header row
FieldOrder: []string{"timestamp", "level", "message", "user_id", "action"}, // Custom field order
TimestampFormat: "2006-01-02T15:04:05", // Custom timestamp format
SensitiveFields: []string{"password", "token"}, // Fields to mask
MaskSensitiveData: true, // Enable masking
MaskStringValue: "[MASKED]", // Mask value
},
})
defer csvLogger.Close()
// Use LogZ with key-value pairs instead of WithFields
csvLogger.LogZ(context.Background(), core.INFO,
[]byte("User login event"),
[]byte("user_id"), []byte("123"),
[]byte("action"), []byte("login"),
[]byte("status"), []byte("success"))
csvLogger.LogZ(context.Background(), core.INFO,
[]byte("Purchase completed"),
[]byte("user_id"), []byte("456"),
[]byte("action"), []byte("purchase"),
[]byte("amount"), []byte("99.99"))
}asyncLogger := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
AsyncLogging: true,
AsyncWorkerCount: 4,
AsyncLogChannelBufferSize: 1000,
LogProcessTimeout: time.Second,
Formatter: &formatter.TextFormatter{
EnableColors: true,
ShowTimestamp: true,
ShowCaller: true,
},
})
defer asyncLogger.Close()
// This will be processed asynchronously
for i := 0; i < 1000; i++ {
asyncLogger.LogZ(context.Background(), core.INFO,
[]byte("Async log message"),
[]byte("iteration"), []byte(strconv.Itoa(i)))
}func myHandler(w http.ResponseWriter, r *http.Request) {
// Extract tracing information from request context
ctx := r.Context()
ctx = util.WithTraceID(ctx, generateTraceID())
ctx = util.WithRequestID(ctx, generateRequestID())
// Use Mire API for context-aware logging
log.Mire(ctx, log.INFO, []byte("Processing HTTP request"))
// Add user-specific context
ctx = util.WithUserID(ctx, getUserID(r))
// Use Mire API with fields
log.Mire(ctx, log.INFO,
[]byte("Request details"),
[]byte("path"), []byte(r.URL.Path),
[]byte("method"), []byte(r.Method))
}// Implement a custom hook
type CustomHook struct {
endpoint string
}
func (h *CustomHook) Fire(entry *core.LogEntry) error {
// Send log entry to external service
payload, err := json.Marshal(entry)
if err != nil {
return err
}
resp, err := http.Post(h.endpoint, "application/json", bytes.NewBuffer(payload))
if err != nil {
return err
}
defer resp.Body.Close()
return nil
}
func (h *CustomHook) Close() error {
// Cleanup resources
return nil
}
// Use the custom hook
customHook := &CustomHook{endpoint: "https://logs.example.com/api"}
log := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
Hooks: []hook.Hook{customHook},
Formatter: &formatter.TextFormatter{
EnableColors: true,
ShowTimestamp: true,
},
})rotationConfig := &config.RotationConfig{
MaxSize: 100, // 100MB
MaxAge: 30, // 30 days
MaxBackups: 5, // Keep 5 old files
Compress: true, // Compress rotated files
}
logger := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
EnableRotation: true,
RotationConfig: rotationConfig,
Formatter: &formatter.JSONFormatter{
TimestampFormat: "2006-01-02T15:04:05.000Z07:00",
},
})func getLoggerForEnv(env string) *logger.Logger {
baseConfig := logger.LoggerConfig{
Formatter: &formatter.JSONFormatter{
ShowTimestamp: true,
ShowCaller: true,
},
ShowHostname: true,
ShowApplication: true,
Environment: env,
}
switch env {
case "production":
baseConfig.Level = core.INFO
baseConfig.Output = os.Stdout
case "development":
baseConfig.Level = core.DEBUG
baseConfig.Formatter = &formatter.TextFormatter{
EnableColors: true,
ShowTimestamp: true,
ShowCaller: true,
}
case "testing":
baseConfig.Level = core.WARN
baseConfig.Output = io.Discard // Discard logs during testing
}
return logger.New(baseConfig)
}func conditionalLog(ctx context.Context) {
// Extract user role from context and adjust logging behavior
userRole := ctx.Value("role")
if userRole == "admin" {
log.Mire(ctx, log.INFO, []byte("Admin action performed"))
} else {
action := fmt.Sprintf("%v", ctx.Value("action"))
log.Mire(ctx, log.DEBUG,
[]byte("Regular user action"),
[]byte("action"), []byte(action))
}
}import "github.com/Luvion1/mire/metric"
// Create a custom metrics collector
customMetrics := metric.NewDefaultMetricsCollector()
log := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
EnableMetrics: true,
MetricsCollector: customMetrics,
Formatter: &formatter.TextFormatter{
EnableColors: true,
ShowTimestamp: true,
},
})
// Use the logger with Mire API
log.Mire(context.Background(), log.INFO, []byte("Test message"))
// Access metrics
count := customMetrics.GetCounter("log.info")// Define a custom context extractor function
func customContextExtractor(ctx context.Context) map[string]string {
result := make(map[string]string)
// Extract custom values from context
if reqID := ctx.Value("request_id"); reqID != nil {
if idStr, ok := reqID.(string); ok {
result["request_id"] = idStr
}
}
if tenantID := ctx.Value("tenant_id"); tenantID != nil {
if idStr, ok := tenantID.(string); ok {
result["tenant"] = idStr
}
}
return result
}
// Use the custom extractor in logger config
log := logger.New(logger.LoggerConfig{
Level: core.INFO,
Output: os.Stdout,
ContextExtractor: customContextExtractor,
Formatter: &formatter.JSONFormatter{
ShowTimestamp: true,
ShowTraceInfo: true,
},
})We welcome contributions to the Mire project!
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests for new functionality
- Ensure all tests pass
- Submit a pull request
# Clone your fork
git clone https://github.com/YOUR_USERNAME/mire.git
cd mire
# Install dependencies
go mod tidy
# Run tests
go test ./...
# Run benchmarks
go test -bench=. ./...- Follow Go formatting conventions (
go fmt) - Write comprehensive tests for new features
- Document exported functions and types
- Maintain backward compatibility when possible
- Write clear commit messages
This project is licensed under the Apache License 2.0 - see the LICENSE file for details.
Need help? Join our community:
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Major Enhancement: Complete internal redesign with []byte fields to eliminate string conversion overhead
- Performance: Achieved near-zero allocation performance with improved formatter efficiency
- Architecture: Refactored core components for memory hierarchy optimization
- Features: Enhanced context extraction and distributed tracing support
- Bug Fixes: Fixed concurrent metrics counter race conditions and unused import errors
- Testing: Fixed 50+ test errors across all packages, updated for type safety with
map[string][]byte, ensured 100% test coverage and build stability
- Added support for custom context extractors
- Implemented advanced field transformers
- Introduced log sampling for high-volume scenarios
- Added comprehensive test coverage
- Improved documentation and examples
- Added JSON and CSV formatters
- Implemented hook system for custom log processing
- Added log rotation capabilities
- Enhanced asynchronous logging
- Added metrics collection
- Basic text logging with color support
- Context-aware logging with trace IDs
- Structured logging with fields
- Simple configuration options