Zap Handler
The Zap handler provides integration with the go.uber.org/zap logging library, allowing you to automatically mask sensitive data in your logs.
Overview
The Zap handler is a configurable logging handler that applies censoring to log entries and fields, overriding the original values before passing them to the core. It's designed to work with both sugared and unsugared Zap loggers, though with some limitations.
Basic Usage
Here's a simple example of how to use the Zap handler:
package main
import (
censorlog "github.com/vpakhuchyi/censor/handlers/zap"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
type User struct {
Name string `censor:"display"`
Email string
}
func main() {
// Create a user with sensitive data.
u := User{
Name: "John Doe",
Email: "example@gmail.com",
}
// Create a Zap logger with the Censor handler.
o := zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return censorlog.NewHandler(core)
})
l, err := zap.NewProduction(o)
if err != nil {
// Handle error.
}
// Log the user data - sensitive fields will be automatically masked.
l.Info("user", zap.Any("payload", u))
// Output: {"level":"info",...,"msg":"user","payload":"{Name: John Doe, Email: [CENSORED]}"}
}
Understanding Logger Components
When working with the Zap logger, we can identify three main components:
- msg: The main log message (e.g., "user" in the example above)
- key: The field name (e.g., "payload" in the example above)
- value: The actual data being logged (e.g., the User struct in the example above)
By default, Censor processes only the "value" component to minimize overhead, as "msg" and "key" typically contain static strings or field names rather than sensitive data. This design choice helps maintain performance while still protecting sensitive information.
Configuration Options
The Zap handler provides the following configuration option:
WithCensor(censor *censor.Processor)
: Sets a custom Censor processor instance for the Zap handler. If not provided, a default Censor processor is used.
Example with custom configuration:
// Create a custom Censor instance.
c := censor.New()
// Create a Zap logger with custom Censor configuration.
o := zap.WrapCore(func(core zapcore.Core) zapcore.Core {
return censorlog.NewHandler(core, censorlog.WithCensor(c))
})
l, err := zap.NewProduction(o)
if err != nil {
// Handle error.
}
Supported Logger Methods
Unsugared Logger Methods
The handler fully supports the following unsugared logger methods:
// Basic logging methods.
Info(msg string, fields ...zap.Field)
Debug(msg string, fields ...zap.Field)
Warn(msg string, fields ...zap.Field)
Error(msg string, fields ...zap.Field)
Panic(msg string, fields ...zap.Field)
Fatal(msg string, fields ...zap.Field)
// With context methods.
With(fields ...zap.Field).Info(msg string, fields ...zap.Field)
With(fields ...zap.Field).Debug(msg string, fields ...zap.Field)
With(fields ...zap.Field).Warn(msg string, fields ...zap.Field)
With(fields ...zap.Field).Error(msg string, fields ...zap.Field)
With(fields ...zap.Field).Panic(msg string, fields ...zap.Field)
With(fields ...zap.Field).Fatal(msg string, fields ...zap.Field)
Sugared Logger Methods
The handler also supports the following sugared logger methods:
// Basic logging methods.
Infow(msg string, keysAndValues ...interface{})
Debugw(msg string, keysAndValues ...interface{})
Warnw(msg string, keysAndValues ...interface{})
Errorw(msg string, keysAndValues ...interface{})
Panicw(msg string, keysAndValues ...interface{})
Fatalw(msg string, keysAndValues ...interface{})
// With context methods.
With(args ...interface{}).Infow(msg string, keysAndValues ...interface{})
With(args ...interface{}).Debugw(msg string, keysAndValues ...interface{})
With(args ...interface{}).Warnw(msg string, keysAndValues ...interface{})
With(args ...interface{}).Errorw(msg string, keysAndValues ...interface{})
With(args ...interface{}).Panicw(msg string, keysAndValues ...interface{})
With(args ...interface{}).Fatalw(msg string, keysAndValues ...interface{})
Important Notes
-
Method Support: Only the methods listed above are fully supported. Other methods that use
fmt.Sprint
-like functions to concatenate arguments are not supported, as they pass data to the Censor handler as single formatted strings, preventing individual value processing. -
Performance Considerations: The handler is optimized to minimize overhead by only processing the "value" component of log entries. This design choice helps maintain performance while still protecting sensitive information.
-
Compatibility: While the handler works seamlessly with the unsugared logger, its compatibility with the sugared logger is more limited. It's recommended to use the unsugared logger for the most reliable results.
Next Steps
- Learn about Type Support options
- See Configuration for customization options
- Check out Examples for real-world usage