PII Redaction
Automatically redact personally identifiable information from traces before storage.
Neatlogs provides two layers of PII redaction: client-side masking that runs in your process before data leaves, and server-side redaction powered by a Presidio-based microservice that runs on the backend before data is stored.
Client-Side Masking
Use the mask parameter in neatlogs.init() to redact sensitive data before it's exported from your application:
def redact(span):
attrs = span.get("attributes", {})
for key in list(attrs):
if "email" in key or "phone" in key:
attrs[key] = "***"
return span
neatlogs.init(mask=redact)The mask function receives the full span dict and must return the (possibly modified) dict. It runs on every span before export.
Per-Span Masking
Apply a mask to specific spans only using @span(mask=fn) or with trace(..., mask=fn). Per-span masks take precedence over the global mask:
@neatlogs.span(kind="TOOL", mask=redact_pii)
def lookup_customer(email: str):
...Server-Side Redaction
Server-side redaction runs automatically on the Neatlogs backend using a Presidio-based microservice. It detects and redacts PII entities (names, emails, phone numbers, addresses, etc.) from span payloads before they are stored.
Configuration
Server-side redaction is configured at the team level in the Neatlogs dashboard under Settings > PII Redaction. You can configure:
- Enabled/Disabled — toggle redaction on or off for all projects in the team
- Entity types — which PII types to detect (e.g.,
PERSON,EMAIL_ADDRESS,PHONE_NUMBER) - Operator — how to redact detected entities:
replace— replace with the entity type label (e.g.,John→<PERSON>)mask— mask characters (e.g.,John→****)redact— remove the entity entirely
- Span types — which span kinds to apply redaction to (e.g., only
LLMandTOOLspans)
SDK Overrides
Override the team-level settings per project using neatlogs.init():
# Enable redaction regardless of the dashboard setting
neatlogs.init(pii_enabled=True)
# Only redact PII in LLM and TOOL spans
neatlogs.init(pii_span_types=["LLM", "TOOL"])
# Disable redaction for a dev/test environment
neatlogs.init(pii_enabled=False)When pii_enabled or pii_span_types is not set (default), the team-level dashboard configuration is used.
What Gets Redacted
Server-side redaction covers all user-visible span fields:
| Category | Fields |
|---|---|
| Core I/O | input_value, output_value |
| LLM content | completion_text, intermediate_steps |
| Prompt templates | prompt_template, prompt_template_variables, user_prompt_template, user_prompt_template_variables |
| Tool fields | tool_input, tool_output, tool_parameters, tool_call_function_arguments |
| Retrieval | retrieval_query, retrieval_documents |
| Reranker | reranker_query, reranker_input_documents, reranker_output_documents |
| MCP | mcp_request_argument, mcp_response_value |
Graceful Degradation
If the PII redaction microservice is unavailable or times out, the original data is stored unchanged — ingestion is never blocked. A warning is logged server-side when this occurs.
When to Use Which
| Approach | Use when |
|---|---|
Client-side mask | You need to redact data before it leaves your infrastructure |
| Server-side redaction | You want automatic, team-wide PII detection without modifying application code |
| Both | Defense in depth — mask known fields client-side, let the server catch anything else |