Redactors
Redactors transform structured log events to remove or mask sensitive data before serialization and sink emission. The Redactors stage executes after Enrichers and before Sinks, preserving the async-first, non-blocking guarantees of the runtime pipeline.
!!! warning “PII in Message Strings Is Not Redacted”
Redactors only process **structured fields** in the log envelope.
PII embedded in the message string will pass through unchanged.
```python
# UNSAFE - email will NOT be redacted
logger.info(f"User {email} logged in")
logger.info("User " + email + " logged in")
# SAFE - email field will be redacted
logger.info("User logged in", email=email)
logger.info("User logged in", user={"email": email})
```
See [PII Showing Despite Redaction](../troubleshooting/pii-showing-despite-redaction.md)
for more details.
Stage Placement and Lifecycle
Runs in the logger worker loop; no new threads or loops are created
Sequential, deterministic application in configured order
Errors are contained; events are not dropped due to redaction errors
Each redactor supports optional async
start/stoplifecycle
Built-in Redactors
Fapilog ships with five built-in redactors. The first three are the core masking layer; the last two provide policy enforcement and size control.
FieldMaskRedactor
Masks selected fields identified by dotted paths across nested dicts and lists.
from fapilog.plugins.redactors.field_mask import FieldMaskRedactor, FieldMaskConfig
redactor = FieldMaskRedactor(
config=FieldMaskConfig(
fields_to_mask=[
"user.password",
"payment.card.number",
"items.value",
],
mask_string="***",
block_on_unredactable=False,
max_depth=16,
max_keys_scanned=1000,
)
)
RegexMaskRedactor
Matches field paths at any nesting level against regex patterns. All patterns are validated at config time to prevent ReDoS (see Regex Pattern Safety).
from fapilog.plugins.redactors.regex_mask import RegexMaskRedactor, RegexMaskConfig
redactor = RegexMaskRedactor(
config=RegexMaskConfig(
patterns=[
r"(?i).*password.*",
r"(?i).*secret.*",
r"(?i).*token.*",
],
mask_string="***",
block_on_unredactable=False,
)
)
UrlCredentialsRedactor
Strips user:password@ credentials from URL-like strings found in any field value. Enabled by default (no preset required).
from fapilog.plugins.redactors.url_credentials import (
UrlCredentialsRedactor,
UrlCredentialsConfig,
)
redactor = UrlCredentialsRedactor(
config=UrlCredentialsConfig(
max_string_length=4096, # Max URL length to scan
)
)
FieldBlockerRedactor
Blocks high-risk field names (e.g., body, payload, raw) by replacing their values entirely. Designed to catch accidental logging of request/response bodies. Enabled by default in the hardened preset.
from fapilog.plugins.redactors.field_blocker import (
FieldBlockerRedactor,
FieldBlockerConfig,
)
redactor = FieldBlockerRedactor(
config=FieldBlockerConfig(
blocked_fields=["body", "request_body", "response_body", "payload"],
allowed_fields=[], # Exemptions from the blocklist
replacement="[REDACTED:HIGH_RISK_FIELD]",
)
)
Builder API shortcut:
logger = LoggerBuilder().with_redaction(block_fields=["body", "payload"]).build()
Each blocked field emits a policy-violation diagnostic. Monitor violations with the fapilog_policy_violations_total metric (see Redaction Metrics).
StringTruncateRedactor
Truncates string values exceeding a configured length and appends a [truncated] marker. Disabled by default (max_string_length=None means no traversal). Useful for preventing oversized log events from body dumps or stack traces.
from fapilog.plugins.redactors.string_truncate import (
StringTruncateRedactor,
StringTruncateConfig,
)
redactor = StringTruncateRedactor(
config=StringTruncateConfig(
max_string_length=1000, # None = disabled (default)
)
)
Builder API shortcut:
logger = LoggerBuilder().with_redaction(max_string_length=1000).build()
Configuration
Core settings include:
core.enable_redactors: enable/disable the stagecore.redactors_order: ordered list of redactor plugin namescore.redaction_max_depth,core.redaction_max_keys_scanned: guardrail plumbing used by redactors
FieldMaskRedactor
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Dotted field paths to mask |
|
|
|
Replacement string |
|
|
|
Drop event if a value can’t be processed |
|
|
|
Per-redactor traversal depth limit |
|
|
|
Per-redactor key scan limit |
|
|
|
|
RegexMaskRedactor
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Regex patterns matched against field paths |
|
|
|
Replacement string |
|
|
|
Drop event if a value can’t be processed |
|
|
|
Bypass ReDoS validation |
UrlCredentialsRedactor
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Max URL length to scan |
FieldBlockerRedactor
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Field names to block (case-insensitive) |
|
|
|
Exemptions from the blocklist |
|
|
|
Replacement string |
|
|
|
Per-redactor traversal depth limit |
|
|
|
Per-redactor key scan limit |
|
|
|
|
StringTruncateRedactor
Setting |
Type |
Default |
Description |
|---|---|---|---|
|
|
|
Max string length; |
|
|
|
Per-redactor traversal depth limit |
|
|
|
Per-redactor key scan limit |
|
|
|
|
Diagnostics and Metrics
Each redactor execution is timed via the shared plugin timer
Failures are recorded in plugin error metrics (when metrics are enabled)
Structured diagnostics are emitted via
core.diagnostics.warnfor guardrail or policy warningsRedaction operational metrics (
fapilog_redacted_fields_total,fapilog_policy_violations_total, etc.) are recorded automatically — see Redaction Metrics
Integration Order
At runtime the effective order is: Enricher → Redactor → Processor → Sink. Redaction occurs pre-serialization. See Redaction Behavior for policy and guardrails.