redact

package module
v2.0.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 3, 2026 License: MIT Imports: 3 Imported by: 0

Documentation

Overview

Package redact provides a LogLayer plugin that replaces sensitive values in metadata and fields before they reach a transport.

Three matching modes:

  • Keys: exact, case-sensitive key/field names. Honors `json` tags when matching struct fields.
  • Patterns: regular expressions matched against string values at any depth.
  • (implicit) struct walking: structs are introspected by default. The metadata's runtime type is preserved (struct in → struct out, map in → map out, slice in → slice out).

Caller's input is never mutated; the plugin clones whatever it touches.

Usage:

log := loglayer.New(loglayer.Config{
    Transport: structured.New(structured.Config{}),
})
log.AddPlugin(redact.New(redact.Config{
    Keys: []string{"password", "apiKey", "ssn"},
}))

See https://go.loglayer.dev for usage guides and the full API reference.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func New

func New(cfg Config) loglayer.Plugin

New constructs a redaction plugin from the config. The returned plugin implements [loglayer.MetadataHook], [loglayer.FieldsHook], and [loglayer.DataHook]. The DataHook re-walks the assembled Data map so the framework-built error subtree (`{"message": err.Error()}` from WithError) is also redacted; without it a Pattern-style redactor would catch secrets in metadata/fields but miss the same secrets rendered by an error's Error() string.

Example

New returns a plugin that replaces values for keys listed in Config.Keys with Censor (default "[REDACTED]") wherever they appear, at any depth. Caller-owned input is never mutated.

tr := lltesting.New(lltesting.Config{})
log := loglayer.New(loglayer.Config{
	Transport:        tr,
	DisableFatalExit: true,
	Plugins: []loglayer.Plugin{
		redact.New(redact.Config{Keys: []string{"password"}}),
	},
})

log.WithMetadata(loglayer.Metadata{
	"user":     "alice",
	"password": "hunter2",
}).Info("login")

line := tr.Library.PopLine()
md := line.Metadata.(loglayer.Metadata)
fmt.Println(md["user"], md["password"])
Output:
alice [REDACTED]

Types

type Config

type Config struct {
	// ID for the plugin. Defaults to "redact". Override when registering
	// multiple redactors at once (e.g. one for PII, one for secrets).
	ID string

	// Keys whose values are replaced with Censor wherever they appear.
	// Matches map keys (string-keyed maps only) and struct field names
	// (json tag preferred, fallback to the Go field name). Walks into
	// nested maps, structs, slices, arrays, and pointers at any depth.
	// Match is exact and case-sensitive.
	Keys []string

	// Patterns are regular expressions matched against string values
	// (not keys) at any depth. A value matching any pattern is replaced
	// with Censor.
	Patterns []*regexp.Regexp

	// Censor is the replacement value. Defaults to "[REDACTED]".
	//
	// For string-typed fields (struct field, map value, slice element),
	// the censor is stringified via fmt.Sprintf if non-string. For
	// interface{} values, the censor is passed through. For other typed
	// fields (int, time.Time, etc.) we can't safely substitute a foreign
	// value; the field is set to its zero value.
	Censor any
}

Config holds redactor configuration.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL