Zerolog Integration
This guide shows you how to integrate Censor with the Zerolog logging framework.
Installation
Install the required packages:
go get -u github.com/rs/zerolog
go get -u github.com/vpakhuchyi/censor
Basic Usage
Here's a simple example of using Censor with Zerolog:
package main
import (
"os"
"github.com/rs/zerolog"
"github.com/vpakhuchyi/censor"
"github.com/vpakhuchyi/censor/logger/zerolog"
)
func main() {
// Create a Censor instance.
c := censor.New()
// Create a Zerolog logger with Censor handler.
logger := zerolog.New(os.Stdout).With().Logger()
logger = censorlog.WithCensor(logger, c)
// Define a struct with sensitive data.
type User struct {
ID string `json:"id" censor:"display"`
Email string `json:"email"`
Password string `json:"password"`
}
// Create a user.
user := User{
ID: "123",
Email: "user@example.com",
Password: "secret123",
}
// Log the user data (safely).
logger.Info().Interface("user", user).Msg("user login")
// Output: {"level":"info","user":{"id":"123","email":"[CENSORED]","password":"[CENSORED]"},"message":"user login"}
}
Configuration Options
Custom Mask Value
// Create a Censor instance with custom mask value.
c := censor.New(censor.WithMaskValue("[REDACTED]"))
// Create a logger with the Censor instance.
logger := zerolog.New(os.Stdout).With().Logger()
logger = censorlog.WithCensor(logger, c)
// Log data.
logger.Info().Interface("user", user).Msg("user login")
// Output: {"level":"info","user":{"id":"123","email":"[REDACTED]","password":"[REDACTED]"},"message":"user login"}
Exclude Patterns
// Create a Censor instance with exclude patterns.
c := censor.New(
censor.WithExcludePatterns([]string{
`\d{4}-\d{4}-\d{4}-\d{4}`, // Credit card numbers.
`\d{3}-\d{2}-\d{4}`, // SSN.
}),
)
// Create a logger with the Censor instance.
logger := zerolog.New(os.Stdout).With().Logger()
logger = censorlog.WithCensor(logger, c)
// Log data with patterns that match exclude patterns.
type Payment struct {
CardNumber string `json:"card_number"`
SSN string `json:"ssn"`
}
payment := Payment{
CardNumber: "4111-1111-1111-1111",
SSN: "123-45-6789",
}
logger.Info().Interface("payment", payment).Msg("payment processed")
// Output: {"level":"info","payment":{"card_number":"4111-1111-1111-1111","ssn":"123-45-6789"},"message":"payment processed"}
Advanced Usage
Custom Field Processors
// Create a Censor instance with custom field processor.
c := censor.New(
censor.WithFieldProcessor("email", func(value interface{}) interface{} {
if email, ok := value.(string); ok {
// Mask email but show domain.
parts := strings.Split(email, "@")
if len(parts) == 2 {
return "***@" + parts[1]
}
}
return "[CENSORED]"
}),
)
// Create a logger with the Censor instance.
logger := zerolog.New(os.Stdout).With().Logger()
logger = censorlog.WithCensor(logger, c)
// Log data.
logger.Info().Interface("user", user).Msg("user login")
// Output: {"level":"info","user":{"id":"123","email":"***@example.com","password":"[CENSORED]"},"message":"user login"}
Field Name Mapping
// Create a Censor instance with field name mapping.
c := censor.New(
censor.WithFieldNameMapper(func(name string) string {
return strings.ToUpper(name)
}),
)
// Create a logger with the Censor instance.
logger := zerolog.New(os.Stdout).With().Logger()
logger = censorlog.WithCensor(logger, c)
// Log data.
logger.Info().Interface("user", user).Msg("user login")
// Output: {"level":"info","user":{"ID":"123","EMAIL":"[CENSORED]","PASSWORD":"[CENSORED]"},"message":"user login"}
Complete Example
Here's a complete example showing various Zerolog integration features:
package main
import (
"os"
"time"
"github.com/rs/zerolog"
"github.com/vpakhuchyi/censor"
"github.com/vpakhuchyi/censor/logger/zerolog"
)
func main() {
// Create a Censor instance with custom configuration.
c := censor.New(
censor.WithMaskValue("[REDACTED]"),
censor.WithExcludePatterns([]string{
`\d{4}-\d{4}-\d{4}-\d{4}`,
}),
)
// Create a Zerolog logger with Censor handler.
logger := zerolog.New(os.Stdout).
With().
Timestamp().
Logger()
logger = censorlog.WithCensor(logger, c)
// Define a struct with sensitive data.
type User struct {
ID string `json:"id" censor:"display"`
Email string `json:"email"`
Password string `json:"password"`
APIKey string `json:"api_key"`
LastLogin time.Time `json:"last_login"`
CreditCard string `json:"credit_card"`
}
// Create a user.
user := User{
ID: "123",
Email: "user@example.com",
Password: "secret123",
APIKey: "sk_live_123456789",
LastLogin: time.Now(),
CreditCard: "4111-1111-1111-1111",
}
// Log user actions.
logger.Info().
Interface("user", user).
Str("action", "login").
Msg("user logged in")
// Log errors safely.
if err := processPayment(user); err != nil {
logger.Error().
Err(err).
Interface("user", user).
Msg("payment processing failed")
}
}
func processPayment(user User) error {
// Simulate payment processing.
return nil
}
Best Practices
-
Logger Initialization: Initialize your logger once and reuse it throughout your application.
-
Structured Logging: Use structured logging with fields to make logs more searchable and analyzable.
-
Error Handling: Always include error information when logging errors, but ensure sensitive data is masked.
-
Performance: Zerolog is designed for high performance. The Censor integration maintains this performance by minimizing allocations.
Next Steps
- Learn about Slog Integration
- Check out Zap Integration
- Review Configuration options
- See Examples for more use cases