Mask PII
Sensitive fields — credit-card numbers, email addresses, phone numbers, internal IDs — slip into logs constantly. Once they reach an observability backend they’re indexed, retained, and eventually queried by people who shouldn’t see them.
LinkMesh-managed collectors run the OpenTelemetry transform processor
with OTTL expressions, so masking happens on the host, before any
data leaves your network. There is no “trust the backend to redact it
later” step.
What you’ll do
- Add a Transform step to a pipeline with one or more OTTL
replace_patternstatements. - Verify with the dry-run panel that the patterns get rewritten.
- Save + attach the pipeline to a route on the collector that handles sensitive logs.
1. Add the Transform step
Open the pipeline you want to add redaction to (or create a fresh one — see Build your first pipeline for the chain-editor walkthrough). Click + Add Processor.
For the common case, pick the canned PII Redaction template — it
ships with three replace_pattern statements covering emails, phone
numbers, and credit-card patterns. For project-specific PII (internal
IDs, IBANs, custom tokens), pick Transform (custom) and write your
own statements:
replace_pattern(body, "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}", "<email>")replace_pattern(body, "[0-9]{4}[ -]?[0-9]{4}[ -]?[0-9]{4}[ -]?[0-9]{4}", "<card>")replace_pattern(body, "INT-[A-Z0-9]{8}", "<internal-id>")Each statement scans body (the log record’s message) and rewrites
every match to a placeholder.
2. Dry-run against a sample
Open the dry-run panel and paste a sample event containing the PII you want to mask:
{ "resourceLogs": [{ "scopeLogs": [{ "logRecords": [{ "body": { "stringValue": "POST /api/v2/cart/checkout user=jdoe@example.com card=4242 4242 4242 4242" } }] }] }]}Click Run. The Final Output panel shows the body rewritten:
user=<email> and card=<card> replacing the originals.
3. Verify on a live collector
Save the pipeline and attach it via a route on a collector that’s actually handling sensitive traffic.
The fastest verification path: add a debug exporter alongside your
real destination for a minute, watch journalctl -u alloy -f (or
-u otelcol-contrib -f), and confirm the body field on outbound records
contains the placeholders rather than the raw values. Remove the debug
exporter once you’ve seen one redacted record — it’s noisy at sustained
traffic.
How the generated config looks
For operators editing collector config directly (or auditing what the UI pushed), the underlying OTel YAML is:
processors: transform/pii_mask: log_statements: - context: log statements: - replace_pattern(body, "[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,}", "<email>") - replace_pattern(body, "[0-9]{4}[ -]?[0-9]{4}[ -]?[0-9]{4}[ -]?[0-9]{4}", "<card>")
service: pipelines: logs: processors: [transform/pii_mask, batch]The order in processors: matters: transform/pii_mask runs before
batch so unredacted values are gone before records are buffered for
export.
Related
- Pipeline — the reusable processor chain this recipe modifies
- Route — wires the pipeline to a specific source-destination pair on a collector
- Drop noisy logs — the Filter sibling of this Transform recipe
- Trust on linkmesh.io — the broader rationale for redacting at the collector edge rather than the backend