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"
)
func main() {
// Simple logging
logx.Info("Hello, LogX!")
logx.Warn("This is a warning")
logx.Error("Something went wrong")
// Structured logging with fields
logx.WithFields(logx.Fields{
"user": "john",
"action": "login",
"ip": "192.168.1.1",
}).Info("User logged in")
}package main
import (
"github.com/LowerPlane/logx"
)
func main() {
// Create a new logger
logger := logx.New()
// Set log level
logger.SetLevel(logx.InfoLevel)
// Use console formatter for human-readable output
logger.SetEncoder(logx.ConsoleFormatter{
FullTimestamp: true,
WithColors: false,
})
// Enable caller information
logger.SetReportCaller(true)
logger.Info("Logger configured successfully")
}// Log with structured fields
logx.WithFields(logx.Fields{
"component": "database",
"operation": "connect",
"duration": "150ms",
}).Info("Database connection established")
// Chain multiple field sets
logger := 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 context
ctx := logx.ContextWithTraceSpan(context.Background(), "trace-123", "span-456")
// Logger will automatically extract and include trace/span IDs
logger := 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"
)
func main() {
logger := logx.New()
// Add file rotation hook
rotationHook := logx.NewRotationHook(
"app.log", // filename
10, // max size in MB
5, // max number of backups
30, // 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 DataDog
dataDogHook := logx.NewDataDogHook("your-api-key", "us") // regions: us, eu, us3, us5, ap1, gov
dataDogHook.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 Loggly
logglyHook := logx.NewLogglyHook("your-token", "http") // token and tag
logger.AddHook(logglyHook)
logger.Error("This error will be sent to Loggly")// Send logs to New Relic
newRelicHook := logx.NewNewRelicHook("your-license-key", "us") // regions: us, eu, gov
newRelicHook.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 Atatus
atatusHook := 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 logs
email := logx.NewSecretString("[email protected]")
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 redacted
logx.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 redactor
logx.AddCustomRedactor(func(key string, val interface{}) interface{} {
if key == "ssn" {
return "[MASKED-SSN]"
}
return val
})
// Regex-based redaction
logx.AddRegexRedactor(`(?i)token=[A-Za-z0-9-_]+`)Selectively mask sensitive fields in complex data structures:
userData := map[string]interface{}{
"username": "alice",
"password": "secret123",
"email": "[email protected]",
}
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 setting
logx.EnableRedaction(true) // Enable globally
// Per-logger override (useful for development)
devLogger := logger.WithRedaction(false) // Disable for this logger
devLogger.WithFields(logx.Fields{
"debug_token": "actual_token_value", // Will show actual value
}).Info("Debug info")
// Regular logger still follows global setting
logger.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:
[email protected] - 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"
func init() {
// Enable redaction in production, disable in development
if os.Getenv("ENV") == "production" {
logx.EnableRedaction(true)
} else {
logx.EnableRedaction(false)
}
}// JSON formatter with custom timestamp
logger.SetEncoder(logx.JSONFormatter{
TimestampFormat: "2006-01-02 15:04:05.000",
})
// Console formatter with full timestamps
logger.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 output
logx.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 creation
logger := logx.New()
// Configuration
logger.SetLevel(level Level)
logger.SetEncoder(encoder Encoder)
logger.SetOutput(w io.Writer)
logger.SetReportCaller(enabled bool)
logger.AddHook(hook Hook)
// Logging methods
logger.Trace(msg string)
logger.Debug(msg string)
logger.Info(msg string)
logger.Warn(msg string)
logger.Error(msg string)
logger.Panic(msg string) // Calls panic() after logging
logger.Fatal(msg string) // Calls os.Exit(1) after logging
// Formatted logging
logger.Infof(format string, args ...interface{})
// Structured logging
logger.WithFields(fields Fields) *Logger
logger.WithContext(ctx context.Context) *Logger// Global logger functions (use default logger)
logx.SetLevel(level Level)
logx.SetEncoder(encoder Encoder)
logx.SetOutput(w io.Writer)
logx.SetReportCaller(enabled bool)
logx.AddHook(hook Hook)
logx.Info(msg string)
logx.WithFields(fields Fields) *Logger
logx.WithContext(ctx context.Context) *Loggertype Fields map[string]interface{}
// Usage
fields := logx.Fields{
"user_id": 12345,
"action": "login",
"success": true,
"duration": 150.5,
}fileHook, err := logx.NewFileHook("/var/log/app.log")
if err != nil {
log.Fatal(err)
}
logger.AddHook(fileHook)rotationHook := logx.NewRotationHook(
"/var/log/app.log", // filename
100, // max size in MB
10, // max backups
30, // 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"
func main() {
logrus.SetLevel(logrus.InfoLevel)
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.Info("Application started")
}LogX:
import "github.com/LowerPlane/logx"
func main() {
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 interface
type MyCustomHook struct{}
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 formatter
logrus.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 context
ctx := logx.ContextWithTraceSpan(context.Background(), "trace-123", "span-456")
// Logger automatically extracts trace/span from context
logger := 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 data
password := "[REDACTED]"
logrus.WithFields(logrus.Fields{
"password": password,
}).Info("User login")LogX (automatic protection):
// Secret wrappers ensure data is ALWAYS redacted
password := logx.NewSecretString("actual_password_123")
logx.WithFields(logx.Fields{
"password": password, // Automatically shows as [REDACTED]
}).Info("User login")
// Or use field-based redaction
logx.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 detection
logx.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"
)
func main() {
// Setup
logrus.SetLevel(logrus.InfoLevel)
logrus.SetFormatter(&logrus.JSONFormatter{})
logrus.SetOutput(os.Stdout)
// Basic logging
logrus.Info("Application started")
// Structured logging
logrus.WithFields(logrus.Fields{
"user": "john",
"role": "admin",
}).Info("User authenticated")
// Error logging
logrus.WithFields(logrus.Fields{
"error": "connection timeout",
}).Error("Database error")
}After (LogX with Security):
package main
import (
"github.com/LowerPlane/logx"
"os"
)
func main() {
// 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 security
logx.WithFields(logx.Fields{
"user": "john",
"role": "admin",
"api_key": logx.NewSecretString("sk_live_123"), // Automatically redacted
}).Info("User authenticated")
// Error logging
logx.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.