Logging LLM applications without creating a privacy problem
How to log prompts, completions, and tool calls well enough for incident response, while keeping personal data and secrets out of long-lived storage.
- Published
- Reading time
- 3 min read

Key takeaways
- Split LLM logs by purpose: a long-lived audit log of metadata and decisions, and a short-lived debug log of redacted content.
- Redact personal data and secrets before content reaches any log sink, not in a downstream pipeline.
- Never store credentials or full retrieved documents in logs; log document identifiers instead.
- Correlation IDs, model versions, and authorization decisions make LLM incidents reconstructable.
On this page
When an LLM feature misbehaves, the first thing anyone asks for is the prompt. What did the user send, what did the retrieval step add, what did the model return, and which tools did it call? Without those records, investigating a bad answer or a suspected injection is guesswork.
The same records are a privacy liability. Users paste in names, account numbers, medical details, and occasionally credentials. Retrieval pulls internal documents into the context. Store all of it indefinitely in a general-purpose logging platform and you have built a sensitive data store that nobody designed, reviewed, or scoped.
The way out is to stop treating "the logs" as one thing.
Separate logs by purpose
Most LLM logging serves two distinct purposes with different requirements.
| Audit log | Debug log | |
|---|---|---|
| Question it answers | What happened, and was it allowed? | Why did the model produce this output? |
| Content | Metadata, decisions, hashes | Full redacted prompt and completion |
| Retention | Long, set by your security policy | Short, often days to weeks |
| Access | Security and incident response | The owning engineering team |
The audit log records events: who made a request, which model and version answered, which tools were proposed, what the authorization decision was, and a hash of the prompt and completion. It is small, low-sensitivity, and kept for as long as your incident response process needs.
The debug log holds the content itself, after redaction. It is the higher-risk store, so it gets short retention and narrow access.
Redact at the edge
Redaction should happen before content reaches any log sink, not in a downstream pipeline. Once raw text has been written to a shared logging platform, it has usually been replicated, indexed, and backed up.
A pragmatic redaction step combines pattern matching for well-structured values with your existing data classification where you have it:
import re
PATTERNS = {
"EMAIL": re.compile(r"[\w.+-]+@[\w-]+\.[\w.-]+"),
"PAN": re.compile(r"\b(?:\d[ -]?){13,19}\b"),
"SECRET": re.compile(r"\b(?:sk|pk|api)[_-][A-Za-z0-9]{16,}\b"),
}
def redact(text: str) -> str:
for label, pattern in PATTERNS.items():
text = pattern.sub(f"[{label}]", text)
return text
Pattern-based redaction will miss things, especially free-text personal details. That is acceptable as long as you design for it: short retention and restricted access on the debug log are what protect you from the misses.
Decide what never gets logged
Some content should not be stored even in redacted form. Make the list explicit and enforce it in code.
- Credentials and session tokens passed through tool calls or headers.
- Full retrieved documents. Log document identifiers and versions instead; the source system already holds the content under its own access controls.
- Special-category data in regulated workflows, where your privacy team has decided the risk outweighs the debugging value.
Make the records useful for incident response
When something goes wrong, responders need to reconstruct a session quickly. A few fields make that possible:
- A correlation ID that ties together the user request, retrieval calls, model calls, and tool calls.
- Model and prompt template versions, so you can tell whether behaviour changed because of a deploy.
- Authorization decisions for every tool call, including denials. A spike in denied calls is often the first visible sign of an injection attempt; see why authorization is the real control.
- The principal, taken from the authenticated session rather than from anything the model produced.
Write it down
Logging choices are governance decisions. Record the retention periods, redaction approach, and access rules alongside each system in your AI model inventory, so reviewers can see them and so they change deliberately rather than by drift.
None of this requires specialised tooling. It requires deciding, before the first incident, which questions your logs must answer and which data they must never hold.



