LogX is a fast, secure, and compliance-ready logging library for Go applications. Built with security-first, compliance-aware, developer-friendly, and performance-optimized principles, LogX is the ideal choice for modern production applications that need to protect sensitive data while maintaining exceptional performance.
LogX is built on four foundational pillars:
- 🛡️ Built-in Sensitive Data Protection: Automatically detects and redacts passwords, API keys, credit cards, SSNs, AWS keys, and more
- 🔒 Secret Wrappers: Type-safe wrappers that guarantee sensitive data is never exposed in logs
- 🎯 Field & Message Redaction: Flexible redaction rules with custom patterns and regex support
- ✅ Compliance-Ready: Pre-configured patterns for PCI-DSS, GDPR, HIPAA, and other regulatory requirements
- 🏛️ Regulatory Standards: Built-in support for PCI-DSS, GDPR, HIPAA, and SOC 2 compliance requirements
- 📝 Audit Trail: Complete logging with trace/span IDs for forensic analysis and compliance auditing
- 🔍 Data Masking: Selective field masking to meet data privacy regulations
- ⚙️ Environment-Based Controls: Different redaction rules for development, staging, and production environments
- 📊 Structured Logging: Intuitive key-value fields and JSON output
- 🔗 Context Integration: Seamless integration with Go context for distributed tracing
- 🪝 Extensible Hooks: Built-in integrations for DataDog, New Relic, Loggly, Atatus, and custom endpoints
- 🎨 Flexible Formatting: Multiple output formats (JSON, Console) with customizable encoders
- 📦 Zero Config: Works out-of-the-box with sensible defaults, configure only what you need
- 🚀 Minimal Allocations: Object pooling and lazy formatting reduce garbage collection pressure
- ⏱️ Low Latency: Optimized for high-throughput, low-latency logging in production systems
- 🔄 Concurrent Safe: Lock-free read paths with optimized concurrent performance
- 📈 Battle-Tested: Benchmarked against popular alternatives (logrus, zerolog)
- 🎯 Multiple Log Levels: TRACE, DEBUG, INFO, WARN, ERROR, PANIC, FATAL
- 🔄 Multiple Output Formats: JSON and human-readable console formats
- 📦 Log Rotation: Integrated with lumberjack for automatic log rotation
- 🔒 Thread-Safe: Safe for concurrent use across goroutines
go get github.com/LowerPlane/logxLogX was designed from the ground up for modern production environments where security, compliance, developer experience, and performance are all critical:
🔐 Security by Default: Unlike other logging libraries, LogX automatically protects your sensitive data. Credit card numbers, API keys, passwords, and other secrets are detected and redacted automatically - no manual configuration required for common patterns.
📋 Compliance Made Easy: Meet regulatory requirements (PCI-DSS, GDPR, HIPAA, SOC 2) out of the box. LogX's built-in redaction patterns are designed to help you avoid accidental data leaks that could result in compliance violations.
👨💻 Developer Experience: Clean, intuitive API that feels natural to Go developers. From simple one-liners to complex structured logging with distributed tracing - LogX scales with your needs without complexity creep.
⚡ Production-Ready Performance: Built for high-throughput systems. LogX uses object pooling, minimal allocations, and concurrent-safe patterns to deliver exceptional performance even under heavy load.
Use LogX when you need:
- To protect sensitive data in logs (PII, credentials, financial information)
- Compliance with data protection regulations
- High-performance logging in production microservices
- Distributed tracing with context propagation
- Integration with observability platforms (DataDog, New Relic, etc.)
package main
import (
"github.com/LowerPlane/logx"
)
funcmain() {
// Simple logginglogx.Info("Hello, LogX!")
logx.Warn("This is a warning")
logx.Error("Something went wrong")
// Structured logging with fieldslogx.WithFields(logx.Fields{
"user": "john",
"action": "login",
"ip": "192.168.1.1",
}).Info("User logged in")
}package main
import (
"github.com/LowerPlane/logx"
)
funcmain() {
// Create a new loggerlogger:=logx.New()
// Set log levellogger.SetLevel(logx.InfoLevel)
// Use console formatter for human-readable outputlogger.SetEncoder(logx.ConsoleFormatter{
FullTimestamp: true,
WithColors: false,
})
// Enable caller informationlogger.SetReportCaller(true)
logger.Info("Logger configured successfully")
}// Log with structured fieldslogx.WithFields(logx.Fields{
"component": "database",
"operation": "connect",
"duration": "150ms",
}).Info("Database connection established")
// Chain multiple field setslogger:=logx.WithFields(logx.Fields{"service": "api"})
logger.WithFields(logx.Fields{"endpoint": "/users"}).Info("Handling request")import (
"context""github.com/LowerPlane/logx"
)
// Add trace/span IDs to contextctx:=logx.ContextWithTraceSpan(context.Background(), "trace-123", "span-456")
// Logger will automatically extract and include trace/span IDslogger:=logx.WithContext(ctx)
logger.Info("Processing request")
// Output: {"level":"INFO","msg":"Processing request","time":"...","fields":{"trace_id":"trace-123","span_id":"span-456"}}import (
"github.com/LowerPlane/logx"
)
funcmain() {
logger:=logx.New()
// Add file rotation hookrotationHook:=logx.NewRotationHook(
"app.log", // filename10, // max size in MB5, // max number of backups30, // max age in days
)
logger.AddHook(rotationHook)
logger.Info("This will be written to app.log with rotation")
}// Send logs to remote endpoint (e.g., Loki, ELK)httpHook:=logx.NewHTTPHook("https://logs.example.com/api/logs")
logger.AddHook(httpHook)
logger.Error("This log will be sent to remote endpoint")// Send logs to DataDogdataDogHook:=logx.NewDataDogHook("your-api-key", "us") // regions: us, eu, us3, us5, ap1, govdataDogHook.Source="my-app"dataDogHook.Service="user-service"dataDogHook.Hostname="server-01"dataDogHook.Tags="env:production,version:1.2.3"logger.AddHook(dataDogHook)
logger.WithFields(logx.Fields{"user_id": 123}).Info("User logged in")// Send logs to LogglylogglyHook:=logx.NewLogglyHook("your-token", "http") // token and taglogger.AddHook(logglyHook)
logger.Error("This error will be sent to Loggly")// Send logs to New RelicnewRelicHook:=logx.NewNewRelicHook("your-license-key", "us") // regions: us, eu, govnewRelicHook.Service="payment-api"newRelicHook.Hostname="api-server-01"logger.AddHook(newRelicHook)
logger.WithFields(logx.Fields{"transaction_id": "txn-123"}).Info("Payment processed")// Send logs to AtatusatatusHook:=logx.NewAtatusHook("your-license-key", "my-app")
logger.AddHook(atatusHook)
logger.WithFields(logx.Fields{"request_id": "req-456"}).Warn("Slow database query")LogX provides comprehensive data protection features to automatically detect and redact sensitive information in your logs.
Always redact sensitive values using secret wrappers:
// These will always appear as [REDACTED] in logsemail:=logx.NewSecretString("user@company.com")
password:=logx.NewSecretString("supersecret123")
logx.WithFields(logx.Fields{
"email": email,
"password": password,
}).Info("User registration")
// Output: {"email":"[REDACTED]","password":"[REDACTED]","msg":"User registration"}Automatically redact sensitive field names:
// Add keys that should always be redactedlogx.AddKeyRedactor("password", "token", "api_key", "credit_card")
logx.WithFields(logx.Fields{
"username": "john",
"password": "secret123", // Will be redacted"api_key": "sk_12345", // Will be redacted
}).Info("User login")Scan and redact sensitive data in log messages:
logx.EnableMessageRedaction(true)
// Built-in patterns automatically detect and redact:logx.Info("Processing credit card 4111-1111-1111-1111") // → "Processing credit card [REDACTED]"logx.Info("User SSN: 123-45-6789") // → "User SSN: [REDACTED]"logx.Info("Login with password=mysecret") // → "Login with [REDACTED]"Create custom redaction rules:
// Custom field redactorlogx.AddCustomRedactor(func(keystring, valinterface{}) interface{} {
ifkey=="ssn" {
return"[MASKED-SSN]"
}
returnval
})
// Regex-based redactionlogx.AddRegexRedactor(`(?i)token=[A-Za-z0-9-_]+`)Selectively mask sensitive fields in complex data structures:
userData:=map[string]interface{}{
"username": "alice",
"password": "secret123",
"email": "alice@example.com",
}
maskedData:=logx.Mask(userData, []string{"password", "email"})
logx.WithFields(logx.Fields{"user": maskedData}).Info("Profile update")
// Output: {"user":{"username":"alice","password":"[REDACTED]","email":"[REDACTED]"}}Enable/disable redaction per logger instance:
// Global settinglogx.EnableRedaction(true) // Enable globally// Per-logger override (useful for development)devLogger:=logger.WithRedaction(false) // Disable for this loggerdevLogger.WithFields(logx.Fields{
"debug_token": "actual_token_value", // Will show actual value
}).Info("Debug info")
// Regular logger still follows global settinglogger.WithFields(logx.Fields{
"token": "secret_token", // Will be redacted
}).Info("Production log")LogX automatically detects and redacts common sensitive data patterns:
- Credit Card Numbers:
4111-1111-1111-1111 - Social Security Numbers:
123-45-6789 - Email Addresses:
user@example.com - API Keys & Tokens:
apikey=sk_12345,Bearer abc123 - AWS Access Keys:
AKIAIOSFODNN7EXAMPLE - Private Key Headers:
-----BEGIN RSA PRIVATE KEY----- - Password Patterns:
password=secret123
Configure redaction based on your environment:
import"os"funcinit() {
// Enable redaction in production, disable in developmentifos.Getenv("ENV") =="production" {
logx.EnableRedaction(true)
} else {
logx.EnableRedaction(false)
}
}// JSON formatter with custom timestamplogger.SetEncoder(logx.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05.000",
})
// Console formatter with full timestampslogger.SetEncoder(logx.ConsoleFormatter{
FullTimestamp: true,
WithColors: true,
})LogX supports the following log levels (in order of severity):
TRACE- Very detailed information, typically only of interest when diagnosing problemsDEBUG- Detailed information, typically only of interest when diagnosing problemsINFO- General information about program executionWARN- Warning messages for potentially harmful situationsERROR- Error events that might still allow the application to continuePANIC- Severe error events that will cause the program to panicFATAL- Very severe error events that will cause the program to exit
logger.SetLevel(logx.DebugLevel) // Only logs DEBUG and above will be outputlogx.Trace("This won't be shown")
logx.Debug("This will be shown")
logx.Info("This will be shown")
logx.Error("This will be shown")LogX is designed for high performance with:
- Object Pooling: Reuses log entry objects to reduce garbage collection
- Lazy Formatting: Messages are only formatted if they meet the log level threshold
- Minimal Allocations: Optimized to reduce memory allocations during logging operations
- Concurrent Safe: Uses read-write mutexes for optimal concurrent performance
Run the included benchmarks to compare performance:
go test -bench=. -benchmemExample results comparing LogX with popular alternatives:
BenchmarkLogxInfo-8 2000000 750 ns/op 120 B/op 3 allocs/op
BenchmarkLogrusInfo-8 1000000 1500 ns/op 280 B/op 8 allocs/op
BenchmarkZerologInfo-8 3000000 550 ns/op 96 B/op 2 allocs/op
// Logger creationlogger:=logx.New()
// Configurationlogger.SetLevel(levelLevel)
logger.SetEncoder(encoderEncoder)
logger.SetOutput(wio.Writer)
logger.SetReportCaller(enabledbool)
logger.AddHook(hookHook)
// Logging methods
logger.Trace(msgstring)
logger.Debug(msgstring)
logger.Info(msgstring)
logger.Warn(msgstring)
logger.Error(msgstring)
logger.Panic(msgstring) // Calls panic() after logging
logger.Fatal(msgstring) // Calls os.Exit(1) after logging// Formatted logginglogger.Infof(formatstring, args...interface{})
// Structured logginglogger.WithFields(fieldsFields) *Logger
logger.WithContext(ctxcontext.Context) *Logger// Global logger functions (use default logger)logx.SetLevel(levelLevel)
logx.SetEncoder(encoderEncoder)
logx.SetOutput(wio.Writer)
logx.SetReportCaller(enabledbool)
logx.AddHook(hookHook)
logx.Info(msgstring)
logx.WithFields(fieldsFields) *Logger
logx.WithContext(ctxcontext.Context) *LoggertypeFieldsmap[string]interface{}
// Usagefields:= logx.Fields{
"user_id": 12345,
"action": "login",
"success": true,
"duration": 150.5,
}fileHook, err:=logx.NewFileHook("/var/log/app.log")
iferr!=nil {
log.Fatal(err)
}
logger.AddHook(fileHook)rotationHook:=logx.NewRotationHook(
"/var/log/app.log", // filename100, // max size in MB10, // max backups30, // max age in days
)
logger.AddHook(rotationHook)httpHook:=logx.NewHTTPHook("https://logs.example.com/api/v1/logs")
logger.AddHook(httpHook)dataDogHook:=logx.NewDataDogHook("your-api-key", "us")
dataDogHook.Source="my-app"dataDogHook.Service="user-service"logger.AddHook(dataDogHook)logglyHook:=logx.NewLogglyHook("your-token", "production")
logger.AddHook(logglyHook)newRelicHook:=logx.NewNewRelicHook("your-license-key", "us")
newRelicHook.Service="api-service"logger.AddHook(newRelicHook)atatusHook:=logx.NewAtatusHook("your-license-key", "my-app")
logger.AddHook(atatusHook)LogX provides a familiar API for logrus users, making migration straightforward. This guide will help you transition your existing logrus-based application to LogX while gaining enhanced security, compliance, and performance benefits.
- 🔐 Built-in Security: Automatic sensitive data redaction (passwords, API keys, credit cards, SSNs)
- 📋 Compliance: Meet PCI-DSS, GDPR, HIPAA requirements out of the box
- ⚡ Better Performance: 2x faster than logrus with fewer allocations (see benchmarks)
- 🔗 Modern Features: Context integration, distributed tracing, and enhanced hook system
- 🛡️ Production-Ready: Security-first design prevents accidental data leaks
Logrus:
import"github.com/sirupsen/logrus"funcmain() {
logrus.SetLevel(logrus.InfoLevel)
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.Info("Application started")
}LogX:
import"github.com/LowerPlane/logx"funcmain() {
logx.SetLevel(logx.InfoLevel)
logx.SetEncoder(logx.JSONFormatter{})
logx.Info("Application started")
}Logrus:
logrus.WithFields(logrus.Fields{
"user_id": 12345,
"action": "login",
}).Info("User logged in")LogX:
logx.WithFields(logx.Fields{
"user_id": 12345,
"action": "login",
}).Info("User logged in")✅ No changes needed - The API is identical!
Logrus:
logger:=logrus.New()
logger.SetLevel(logrus.WarnLevel)
logger.SetFormatter(&logrus.JSONFormatter{})
logger.SetOutput(os.Stderr)LogX:
logger:=logx.New()
logger.SetLevel(logx.WarnLevel)
logger.SetEncoder(logx.JSONFormatter{})
logger.SetOutput(os.Stderr)Key Differences:
SetFormatter()→SetEncoder()(same concept, clearer naming)
| Logrus | LogX | Notes |
|---|---|---|
logrus.TraceLevel | logx.TraceLevel | ✅ Same |
logrus.DebugLevel | logx.DebugLevel | ✅ Same |
logrus.InfoLevel | logx.InfoLevel | ✅ Same |
logrus.WarnLevel | logx.WarnLevel | ✅ Same |
logrus.ErrorLevel | logx.ErrorLevel | ✅ Same |
logrus.FatalLevel | logx.FatalLevel | ✅ Same |
logrus.PanicLevel | logx.PanicLevel | ✅ Same |
Logrus:
import"github.com/sirupsen/logrus"hook:=&MyCustomHook{}
logrus.AddHook(hook)LogX:
import"github.com/LowerPlane/logx"// Built-in hooks (no custom hook needed for common use cases)rotationHook:=logx.NewRotationHook("app.log", 100, 10, 30)
logger.AddHook(rotationHook)
// Or for custom hooks, implement the Hook interfacetypeMyCustomHookstruct{}
func (h*MyCustomHook) Fire(entry*logx.Entry) {
// Your hook logic
}
logger.AddHook(&MyCustomHook{})LogX provides built-in hooks for common scenarios:
- File with Rotation:
NewRotationHook()(replaces logrus file hooks + rotation) - HTTP/Remote:
NewHTTPHook()for Loki, ELK, etc. - DataDog:
NewDataDogHook() - New Relic:
NewNewRelicHook() - Loggly:
NewLogglyHook() - Atatus:
NewAtatusHook()
Logrus:
logrus.SetFormatter(&logrus.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
// Or text formatterlogrus.SetFormatter(&logrus.TextFormatter{
FullTimestamp: true,
})LogX:
logx.SetEncoder(logx.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05",
})
// Or console formatter (equivalent to TextFormatter)logx.SetEncoder(logx.ConsoleFormatter{
FullTimestamp: true,
WithColors: true,
})Logrus doesn't have built-in context support. LogX makes it easy:
LogX:
import"context"// Add trace/span IDs to contextctx:=logx.ContextWithTraceSpan(context.Background(), "trace-123", "span-456")
// Logger automatically extracts trace/span from contextlogger:=logx.WithContext(ctx)
logger.Info("Processing request")
// Output includes: "trace_id":"trace-123", "span_id":"span-456"This is LogX's killer feature - automatic security that logrus doesn't provide:
Logrus (manual redaction required):
// You have to manually redact sensitive datapassword:="[REDACTED]"logrus.WithFields(logrus.Fields{
"password": password,
}).Info("User login")LogX (automatic protection):
// Secret wrappers ensure data is ALWAYS redactedpassword:=logx.NewSecretString("actual_password_123")
logx.WithFields(logx.Fields{
"password": password, // Automatically shows as [REDACTED]
}).Info("User login")
// Or use field-based redactionlogx.AddKeyRedactor("password", "api_key", "credit_card")
logx.WithFields(logx.Fields{
"password": "secret123", // Automatically redacted"username": "john", // Not redacted
}).Info("User login")
// Or enable message redaction for automatic pattern detectionlogx.EnableMessageRedaction(true)
logx.Info("User password is secret123") // → "User password is [REDACTED]"logx.Info("Credit card: 4111-1111-1111-1111") // → "Credit card: [REDACTED]"Before (Logrus):
package main
import (
"github.com/sirupsen/logrus""os"
)
funcmain() {
// Setuplogrus.SetLevel(logrus.InfoLevel)
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetOutput(os.Stdout)
// Basic logginglogrus.Info("Application started")
// Structured logginglogrus.WithFields(logrus.Fields{
"user": "john",
"role": "admin",
}).Info("User authenticated")
// Error logginglogrus.WithFields(logrus.Fields{
"error": "connection timeout",
}).Error("Database error")
}After (LogX with Security):
package main
import (
"github.com/LowerPlane/logx""os"
)
funcmain() {
// Setup (same as logrus)logx.SetLevel(logx.InfoLevel)
logx.SetEncoder(logx.JSONFormatter{})
logx.SetOutput(os.Stdout)
// Enable security features (new!)logx.EnableRedaction(true)
logx.EnableMessageRedaction(true)
// Basic logging (same API)logx.Info("Application started")
// Structured logging with automatic securitylogx.WithFields(logx.Fields{
"user": "john",
"role": "admin",
"api_key": logx.NewSecretString("sk_live_123"), // Automatically redacted
}).Info("User authenticated")
// Error logginglogx.WithFields(logx.Fields{
"error": "connection timeout",
}).Error("Database error")
}- Replace imports:
github.com/sirupsen/logrus→github.com/LowerPlane/logx - Update formatter calls:
SetFormatter()→SetEncoder() - Update formatter types:
JSONFormatter{}→logx.JSONFormatter{} - Update formatter types:
TextFormatter{}→logx.ConsoleFormatter{} - Identify and wrap sensitive fields with
logx.NewSecretString() - Add field redactors for known sensitive keys:
logx.AddKeyRedactor() - Enable message redaction:
logx.EnableMessageRedaction(true) - Replace custom hooks with built-in hooks where possible
- Add context integration for distributed tracing (optional)
- Run tests to verify logging behavior
- Review logs to ensure sensitive data is redacted
Based on included benchmarks:
Operation | Logrus | LogX | Improvement
-------------------|-------------|-------------|------------
Info logging | 1500 ns/op | 750 ns/op | 2x faster
Memory per op | 280 B/op | 120 B/op | 57% less
Allocations per op | 8 allocs/op | 3 allocs/op | 62% fewer
- API is 95% compatible with logrus - most code works unchanged
- Main change:
SetFormatter()→SetEncoder() - Added benefit: Automatic security and compliance features
- Performance: 2x faster with better memory efficiency
- Go 1.19 or later
- lumberjack.v2 - Log rotation
- logrus - Benchmarking only
- zerolog - Benchmarking only
Contributions are welcome! Please feel free to submit a Pull Request.
This project is licensed under the MIT License - see the LICENSE file for details.