Core Concepts

Auto-Redaction

Automatically scrub PII from wide events before console output and drains. Built-in smart masking for credit cards, emails, IPs, phone numbers, JWTs, and more.

Wide events capture comprehensive context, which makes it easy to accidentally log sensitive data. Auto-redaction scrubs PII from events before console output and before any drain sees the data.

Redaction is enabled by default in production (NODE_ENV === 'production'). In development, it is off so you see full values for debugging. No configuration needed — just deploy.

Opting Out

If you need to disable redaction in production:

export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    redact: false,
  },
})

You can also enable redaction explicitly in development with redact: true.

Smart Masking

Built-in patterns use partial masking instead of flat [REDACTED] — preserving enough context for debugging while protecting the actual data.

PatternExample InputMasked Output
creditCard4111111111111111****1111
emailalice@example.coma***@***.com
ipv4192.168.1.100***.***.***.100
phone+33 6 12 34 56 78+33 ****5678
jwteyJhbGciOiJIUzI1NiIs...eyJ***.***
bearerBearer sk_live_abc123...Bearer ***
ibanFR76 3000 6000 0112 ...189FR76****189
127.0.0.1 and 0.0.0.0 are excluded from IPv4 masking since they are not real client addresses.

Configuration

Custom Paths

Add dot-notation paths to redact specific fields with [REDACTED], on top of the built-in patterns:

evlog: {
  redact: {
    paths: ['user.password', 'headers.authorization'],
  }
}

Path-based redaction replaces the entire value with the replacement string (default [REDACTED]), regardless of content.

Selective Built-ins

Pick only the patterns you need:

evlog: {
  redact: {
    builtins: ['email', 'creditCard'],
  }
}

Custom Patterns

Add your own regex patterns. These use the flat replacement string, not smart masking:

evlog: {
  redact: {
    patterns: [/SECRET_\w+/g, /sk_live_\w+/g],
    replacement: '***',
  }
}

Disable Built-ins

If you only want custom redaction:

evlog: {
  redact: {
    builtins: false,
    paths: ['user.ssn'],
    patterns: [/INTERNAL_\w+/g],
  }
}

Configuration Reference

OptionTypeDefaultDescription
redactboolean | RedactConfigtrue in productionEnabled by default in production. false to disable. Object for fine-grained control
pathsstring[]undefinedDot-notation paths to redact entirely (e.g. user.password)
patternsRegExp[]undefinedCustom regex patterns. Uses flat replacement string
builtinsfalse | string[]All enabledfalse disables built-ins. Array selects specific ones
replacementstring'[REDACTED]'Replacement string for paths and custom patterns. Built-in patterns use smart masking instead

Available built-in names: creditCard, email, ipv4, phone, jwt, bearer, iban.

How It Works

Redaction runs inside the emit pipeline, after the wide event is fully built but before any output:

  1. Path redaction — targeted fields replaced with [REDACTED]
  2. Smart masking — built-in patterns scan all string values recursively with partial masking
  3. Pattern redaction — custom regex patterns scan all string values with flat replacement
  4. Console output — masked event printed to stdout
  5. Drain — masked event sent to external services
Redaction runs after the HTTP response is sent, so it adds zero latency to your API responses.

Production Example

Redaction is already on by default in production. Combine with sampling for a typical setup:

export default defineNuxtConfig({
  modules: ['evlog/nuxt'],
  evlog: {
    env: { service: 'my-app' },
  },
  $production: {
    evlog: {
      sampling: {
        rates: { info: 10, debug: 0 },
        keep: [{ status: 400 }, { duration: 1000 }],
      },
    },
  },
})

Before / After

Without redaction, sensitive data lands in your logs and drains:

{
  "user": { "email": "alice@example.com", "ip": "192.168.1.42" },
  "payment": { "card": "4111111111111111" },
  "auth": "Bearer sk_live_abc123def456"
}

With redact: true:

{
  "user": { "email": "a***@***.com", "ip": "***.***.***.42" },
  "payment": { "card": "****1111" },
  "auth": "Bearer ***"
}

Same debugging context, no PII in your Axiom/Datadog/Sentry.

Next Steps