Mask Sensitive Trace Data
Protect your sensitive information from traces using the masking feature
Overview
Masking allows you to automatically redact or transform sensitive data in your traces before they're sent to the observatory. Masking is essential for several reasons:
- Security: Prevent exposure of credentials or sensitive business data
- Regulatory Compliance: Meet requirements like GDPR, HIPAA, or CCPA
By default, confident-trace captures the full content of your spans — prompts, completions, tool arguments, retrieved chunks, and anything you set through the update helpers. If that content can contain PII, you have three controls, all configured once in init():
| Control | Python init() | TypeScript init() | What it does |
|---|---|---|---|
| Disable capture | capture_content | captureContent | Turn content capture off entirely — keep timing, status, model, and usage |
| Redact | redact | redact | Run your own masking function over every content value before export |
| Size limit | max_content_bytes | maxContentBytes | Optionally cap the size of each content attribute (disabled by default) |
Configure Masking
To implement masking, define a masking function and pass it to init() as redact. It runs over every content value right before serialization, so nothing sensitive ever leaves your process.
import re
from confident_trace import init, span, shutdown
def masking_function(data):
if isinstance(data, str):
return re.sub(r'\b(?:\d{4}[- ]?){3}\d{4}\b', '[REDACTED CARD]', data)
if isinstance(data, list):
return [masking_function(item) for item in data]
if isinstance(data, dict):
return {k: masking_function(v) for k, v in data.items()}
return data
init(redact=masking_function)
@span(type="agent")
def llm_app(query: str):
return "4242-4242-4242-4242"
try:
llm_app("Test Masking")
finally:
shutdown()import { init, span } from "confident-trace";
const maskingFunction = (data: unknown): unknown => {
if (typeof data === "string")
return data.replace(/\b(?:\d{4}[- ]?){3}\d{4}\b/g, "[REDACTED CARD]");
if (Array.isArray(data)) return data.map(maskingFunction);
if (data && typeof data === "object") {
return Object.fromEntries(Object.entries(data).map(([k, v]) => [k, maskingFunction(v)]));
}
return data;
};
const runtime = init({ redact: maskingFunction });
const llmApp = span({ name: "llm_app", type: "agent" }, (query: string) => {
return "4242-4242-4242-4242";
});
try {
llmApp("Test Masking");
} finally {
await runtime.shutdown();
}Remember to launch your entry point with the Node preload so integration spans are masked too.
The masking function is automatically applied to:
- Span I/O: the captured input and output of every span — function arguments and return values, as well as the messages and completions recorded by integrations
- Update helper fields: anything you set through
update_span()/update_trace(), such asinput,output,retrieval_context, andmetadata
Disable Content Capture
If you'd rather not export prompts and completions at all — for example in a regulated environment where masking isn't enough — turn content capture off. You still get timing, status, span hierarchy, and the model and token usage attributes, so cost tracking and latency monitoring keep working; only the content fields are omitted.
from confident_trace import init
init(capture_content=False)import { init } from "confident-trace";
const runtime = init({ captureContent: false });Size Limits
Content size limits are disabled by default. Unless you configure one,
confident-trace does not cap content attributes.
Set max_content_bytes / maxContentBytes to enable a limit. Values above the
limit are truncated or omitted, and chat message arrays keep a valid, bounded
prefix where possible so the span still renders. Streamed outputs are bounded
the same way and marked as truncated, while token usage keeps being tracked:
from confident_trace import init
init(max_content_bytes=8192)import { init } from "confident-trace";
init({ maxContentBytes: 8192 });Next Steps
With sensitive data masked, control which traces are sent in the first place.
Sample Traces
Send only a percentage of traces to Confident AI to keep volume and cost under control in high-traffic apps.
Drop Traces
Skip tracing entirely for health checks, internal test requests, and other noise you don't want in the Observatory.
Last updated on