Skip to main content

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

  1. Logger Initialization: Initialize your logger once and reuse it throughout your application.

  2. Structured Logging: Use structured logging with fields to make logs more searchable and analyzable.

  3. Error Handling: Always include error information when logging errors, but ensure sensitive data is masked.

  4. Performance: Zerolog is designed for high performance. The Censor integration maintains this performance by minimizing allocations.

Next Steps

  1. Learn about Slog Integration
  2. Check out Zap Integration
  3. Review Configuration options
  4. See Examples for more use cases