feat(otel): client-side redaction of PII and/or secrets#584
Conversation
Fold AWS, Google, JWT, PEM and Stripe key patterns into DEFAULT_TOKEN_PATTERNS and compose DEFAULT_PII_SECRET_PATTERNS from it, with tests covering each secret and the composition invariant. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Use a conditional base (SpanExporter under TYPE_CHECKING, object at runtime) so linters verify the export/shutdown/force_flush overrides while keeping the OpenTelemetry SDK an optional import. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Add a shared _redact_value helper so both policies scan the string elements of list/tuple attribute values instead of passing them through verbatim, preserving the container type and leaving numeric/bool sequences untouched. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
Rewrite test_redaction.py as pytest classes with fixtures and parametrization, and convert the TestTelemetryRedaction class in test_telemetry.py to a plain pytest class (using caplog for log assertions). Optional span attributes/context are narrowed with asserts instead of file-level pyright suppressions. Older telemetry tests are left as-is. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
️✅ There are no secrets present in this pull request anymore.If these secrets were true positive and are still valid, we highly recommend you to revoke them. 🦉 GitGuardian detects secrets in your source code to help developers and security teams secure the modern development process. You are seeing this because you or someone else with access to this repository has authorized GitGuardian to scan your pull request. |
These are all fake/dummy secrets to test redaction |
Switch default_redaction_policy() from the key-oriented AttributeRedactionPolicy to the content-oriented RegexRedactionPolicy, which preserves keys/structure and redacts only matched secret/PII substrings. Update docstrings, README policy table, the example, and adapt the behavioural tests accordingly. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
rbarbadillo
left a comment
There was a problem hiding this comment.
generally lgtm! just a small edge-case to cover
Regression test for the case where a second configure_telemetry call in dedicated mode is ignored because of the early return on an existing auto provider. Currently fails: the provider is not rebuilt so the new redaction setting never takes effect. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
The early return on an existing auto telemetry provider fired before the replace_existing check, so an explicit configure_telemetry call (which always requests replacement) was a no-op: the provider was never rebuilt and a changed redaction setting was silently ignored. Only short-circuit when replace_existing is False, letting the rebuild path shut down the old provider and recreate it with the new settings. Generated by Mistral Vibe. Co-Authored-By: Mistral Vibe <vibe@mistral.ai>
What
Adds a client-side redaction layer for OpenTelemetry spans so PII and secrets never leave the machine. The core primitive is reusable by any OTEL application, and the Mistral SDK installs it automatically when it owns the exporter.
Also add documentation and examples for the observability features of the SDK.
The primitive
RedactingSpanExporterwraps anySpanExporterand redacts each span before delegating the actual export:Redaction covers the whole span surface: attributes, events, links, resource attributes, span name, and status description.
The module requires the optional OpenTelemetry SDK (the
telemetryextra) to run, but not to import — so it stays importable in environments without the extra.Why an exporter wrapper (and not span-creation-time redaction)
Redaction is deliberately placed in a
SpanExporterdecorator, invoked at export time, rather than when spans/attributes are created. In dedicated mode the SDK wires:This has real, concrete benefits:
BatchSpanProcessor(what the SDK installs), export runs on a dedicated background thread, in batches. The regex scanning and span rebuild happen there — not on the threads serving the user'schat/embeddingscalls — so redaction adds no latency to application requests. Cost is amortized across a batch and absorbed by the exporter thread; under extreme load it manifests as export backpressure, never as slower API calls.SpanExporterdecorator with no Mistral coupling, so any OpenTelemetry application can wrap its own exporter — which is exactly what users do inglobal/custom-provider mode.Caveat: the "off the hot path" property depends on an asynchronous processor.
BatchSpanProcessor(installed by the SDK) gives it; aSimpleSpanProcessorwould export — and therefore redact — synchronously on span end.Policies
RegexRedactionPolicy(default,redaction=True)AttributeRedactionPolicyCallbackRedactionPolicy(redaction=<callable>)(key, value) -> value | Nonemasker per attribute; returnNoneto drop the attribute.SDK integration
configure_telemetrygains aredactionargument:True(default) — default (regex) policyFalse— redaction disabledRedactionPolicyinstance (e.g.AttributeRedactionPolicy())(key, value) -> value | NonecallbackRedaction only applies in dedicated provider mode, where the SDK owns the exporter. In
global/custom-provider modes the application owns the export pipeline, so the argument is ignored and a warning is logged — wrap your own exporter withRedactingSpanExporterin that case.Tests
test_redaction.pycovering the policies, span rebuild, and the exporterwrapper.
test_telemetry.pyfor theredactionwiring and theignored-argument warnings.