Logs leak. Not because anyone means them to — because an exception handler dumps a request body, a debug line prints a user object, or a third-party library logs a full URL with a token in the query string. By the time you notice, that data has already been shipped to whatever backend ingests your telemetry. If that backend is a SaaS in another jurisdiction, you now have a compliance problem, not just a hygiene one.
The durable fix isn’t “log less” — it’s to mask PII in the pipeline, before telemetry leaves your network. This post covers why PII ends up in logs anyway, the compliance drivers that make the where matter, the redaction patterns that work, and how to verify them without exposing the very data you’re trying to protect.
Why PII lands in logs anyway
“Just don’t log sensitive data” is good advice and a bad control. It fails in practice for structural reasons:
- Errors capture context. The most useful error logs include the request that caused them — headers, body, parameters — which is exactly where PII lives.
- You don’t own all the code. Frameworks, ORMs, and third-party libraries log things you didn’t write and can’t easily silence.
- Well-meaning debugging. Someone adds
log.debug(user)to chase a bug, it ships, and now full user objects flow to production telemetry. - New fields sneak in. A field that was innocent last quarter becomes PII when product adds a phone number to it.
Relying on every developer, in every service, forever, to never log something sensitive is not a strategy. You need a checkpoint that doesn’t depend on discipline.
Compliance drivers: it’s about where, not just whether
Two regulations shape this for a lot of teams:
- GDPR (EU) constrains how personal data is processed and, critically, transferred across borders. Shipping raw personal data to a US-hosted observability SaaS is a cross-border transfer with all the scrutiny that entails.
- Switzerland’s revised FADP (revDSG) carries similar obligations for Swiss organizations, with data-residency expectations that make “our telemetry lives on a US vendor’s servers” an uncomfortable answer.
The common thread: redaction has to happen before the data leaves your network. Masking after it reaches a third party is too late — the raw data already crossed the boundary. That’s the whole argument for doing it in-pipeline, on infrastructure you control:
Because a self-hosted control plane keeps the redaction step on your own infrastructure, the raw values never transit anyone else’s systems — only the masked record does. (This is the same data-sovereignty argument on our Trust page.)
In-pipeline redaction patterns
There are three moves, and most policies combine them.
1. Delete the field. If a field is never useful masked, drop it. Authorization headers, raw request bodies, full cookies — gone before ingest.
2. Mask by pattern. Replace matched substrings — emails, card numbers, national
IDs — with a placeholder, keeping the surrounding log readable. With the OpenTelemetry
Collector’s transform processor (OTTL):
processors:
transform/redact:
log_statements:
- context: log
statements:
- replace_pattern(body, "[\\w.+-]+@[\\w.-]+", "***@***")
- delete_key(attributes, "http.request.header.authorization")
3. Hash for correlation. Sometimes you need to group by a user without storing who they are. Hash the identifier — the same input always yields the same token, so you can still count sessions per user or trace a request across services, but the raw value never lands:
- set(attributes["user.id"], SHA256(attributes["user.id"]))
There’s also a dedicated redaction processor for an allow-list approach — permit a
known-safe set of attributes and block everything else by value pattern — which is a
stronger default posture than trying to enumerate every bad field.
One practical note: redaction is far easier on structured telemetry than on
free-text log bodies. If a value lives in a named attribute (user.email), you can
target it precisely and confidently. If it’s buried in a formatted message string,
you’re back to regex — powerful but brittle, and worth pairing with an allow-list so a
missed pattern fails closed instead of leaking. Emitting structured logs in the first
place makes every redaction rule simpler and safer.

Verifying redaction without exposing the data
Here’s the catch with redaction: how do you confirm a rule works without looking at the raw sensitive data to check? Testing a mask by dumping live traffic to your screen recreates the exact exposure you’re trying to prevent.
The safe pattern is to preview the transform on a captured sample where the rule is already applied — you see the masked before/after, confirm the field is handled, and never surface the raw value in the process. That turns “I think the regex is right” into “I can see it masked” without a compliance footgun.

Redaction as pipeline policy, not per-app code
The deepest reason to redact in the pipeline is where the rule lives. Sanitizing in application code means every service, in every language, reimplements the same masking — and any one of them getting it wrong is a leak. Moving redaction into the pipeline makes it one policy, enforced for all telemetry, regardless of which app emitted it or whether that app remembered to sanitize.
That’s the model LinkMesh is built around: redaction is a processor you add to a pipeline once, it runs on your own infrastructure, and only masked telemetry ever crosses the boundary. You define the policy centrally, apply it fleet-wide, and your developers stop being the last line of defense against a logged credit-card number.
Sensitive data in logs is inevitable; sensitive data leaving your network doesn’t have to be. See Trust for the data-handling model, or stand up a control plane and add a redaction step to your first pipeline at linkmesh.io/install.
This post covers masking patterns for PII in general. If you’re in a regulated, Swiss-adjacent environment, there’s a harder category underneath this one — client-identifying data, which a scanner structurally can’t always find. See PII vs CID: the detection gap in regulated telemetry for why, and what to do about it instead.