Choose the attachment point
Callbacks do not cover every OpenTelemetry field. Keep sensitive information out of span and event names, attribute keys and instrumentation names. Python user/session metadata and custom attributes also need your own producer-side policy. See the complete TypeScript and Python contracts.
TypeScript: mask email addresses
Install the SDK and setHUE_API_KEY to a Tracing only project key in your server environment. Save this reusable callback as redaction.ts:
trace.ts in a package whose package.json contains "type": "module", then run node trace.ts on Node 24. It makes no model or email-provider calls.
[EMAIL]; user_123, session_456, counts, timing and trace/span IDs remain available. Replacing every address with one marker loses recipient distinctions. If your evaluations need to compare recipients, use stable aliases generated under your application’s policy instead.
Use the same callback with an existing provider
Put the callback on the transport when supplying a transport tocreateHue. Add Hue’s processors to the provider your application already constructs; keep its other processors, resources, sampling and registration. For example, extend the existing bootstrap as follows:
provider, resource and existingProcessor represent your existing setup. If you also export logs, add hueTransport.logRecordProcessor to your existing logger provider. Follow the complete OpenTelemetry setup for lifecycle handling and production safety for fail-open initialization.
Each exporter needs its own policy. A Langfuse mask callback does not automatically scrub Hue’s copy, and Hue’s callback does not scrub Langfuse’s copy. Keep the current instrumentation and provider; see keep Langfuse and add Hue.
Python: mask nested helper content
Installhue-run and set HUE_API_KEY to a Tracing only project key. Save this as trace.py and run python trace.py in that environment:
Hue(redactor=...) to its provider does not apply this callback to those external spans.
Customize the policy
Use the callback to combine text patterns with the fields your application knows are sensitive. Keep it synchronous, fast and free of network calls.- TypeScript:
pathidentifies the exported value, such asattributes.input.valueorattributes.customer.email. Return[REDACTED]for a sensitive string attribute. Helper inputs/outputs are serialized JSON strings:pathdoes not identify their nestedemailfield. For rules on nested fields, explicitly parse known JSON content fields, transform the structure, then serialize it, or sanitize a separate telemetry copy before recording it. If required parsing fails, omit or replace the content rather than returning the original sensitive value. - Python:
fieldidentifies the helper’s content field, not each nested dictionary key. Add key-based rules inside the dictionary branch when you need to replace a field such asemailregardless of its format. The example processes values only; add separate handling if your data uses sensitive dictionary keys.
captureContent: false / capture_content=False, Hue removes recognized content fields instead. That choice does not classify arbitrary attributes; native Langfuse content keys also need explicit handling as described in the OpenTelemetry guide.
Verify before rollout
Run a synthetic request through the application’s actual instrumentation, including nested messages and tool results. Inspect the Hue-bound export or the stored trace: the raw test address should be absent and[EMAIL] present, while opaque user/session IDs, numeric values, trace/span IDs and parent relationships remain intact. Check logs and any running-span placeholders too. With multiple exporters, inspect each destination separately.
Test a callback that throws. TypeScript rejects the affected export record and reports an export issue; Python omits the affected helper content field and counts an instrumentation failure. The original sensitive value must not be sent as a fallback, and application results and errors must remain unchanged. Inspect hue.transport.getReport() / getIssues() or Python’s hue.export_status; log only sanitized counters and status, never original content or callback exceptions.
A successful trace receipt confirms requested spans and field presence, not correct redaction. The examples use strict flush checks for diagnostics; use the production-safe lifecycle in serving applications. Existing stored traces are unaffected; agree retention and deletion separately.