A lightweight, thread-safe audit logging library for Go that tracks entity changes and events with field-level precision.
- Simple API for entity audit logging (create, update, delete)
- Field-level change tracking with before/after values
- Sensitive data masking for passwords and tokens
- Thread-safe concurrent operations
- Pluggable storage interface (in-memory default)
- Slog integration for automatic audit from standard logs
- Zero dependencies in core package
go get github.com/w0rng/auditlogger := audit.New()
// Log entity creation
logger.Create("order:123", "john.doe", "Order created", map[string]audit.Value{
"status": audit.PlainValue("pending"),
"token": audit.HiddenValue(), // Masked as "***"
})
// Log update
logger.Update("order:123", "admin", "Order approved", map[string]audit.Value{
"status": audit.PlainValue("approved"),
})
// Get change history
changes := logger.Logs("order:123")
for _, change := range changes {
fmt.Printf("%s by %s\n", change.Description, change.Author)
for _, field := range change.Fields {
fmt.Printf(" %s: %v -> %v\n", field.Field, field.From, field.To)
}
}// Default in-memory storage
logger := audit.New()
// With custom storage
logger := audit.New(audit.WithStorage(customStorage))// Create, update, delete
logger.Create(key, author, description, payload)
logger.Update(key, author, description, payload)
logger.Delete(key, author, description, payload)
// Payload with hidden fields
payload := map[string]audit.Value{
"email": audit.PlainValue("user@example.com"),
"password": audit.HiddenValue(), // Shows as "***"
}// All events for entity
events := logger.Events("order:123")
// Filter by fields
statusEvents := logger.Events("order:123", "status", "total")
// Change history with state reconstruction
changes := logger.Logs("order:123")Implement the Storage interface for custom backends (Redis, PostgreSQL, etc.):
type Storage interface {
Store(key string, event Event)
Get(key string) []Event
Has(key string) bool
Clear(key string)
}
// Use it
storage := NewMyStorage()
logger := audit.New(audit.WithStorage(storage))See examples/custom_storage for JSON file storage implementation.
Automatically create audit logs from standard slog logs:
import auditslog "github.com/w0rng/audit/slog"
handler := auditslog.NewHandler(auditLogger, auditslog.HandlerOptions{
KeyExtractor: auditslog.AttrExtractor(auditslog.AttrEntity),
ShouldAudit: func(r slog.Record) bool {
return r.Level >= slog.LevelInfo
},
})
logger := slog.New(handler)
logger.Info("User created",
auditslog.AttrEntity, "user:123",
auditslog.AttrAction, "create",
"email", "user@example.com",
)Available attribute constants: AttrEntity, AttrAction, AttrAuthor, AttrUser.
See examples/slog_integration for complete example.
Run examples to see the library in action:
go run examples/basic/main.go # Basic usage
go run examples/custom_storage/main.go # Custom storage
go run examples/slog_integration/main.go # Slog integrationgo test ./... # Run all tests
go test -race ./... # With race detector
go test -cover ./... # Check coverage
go test -bench=. -benchmem # Run benchmarksMIT License - see LICENSE file for details.