Logging is an essential part of application development. Developers use logs to investigate errors, monitor application behavior, troubleshoot production issues, and understand how requests move through a system.
AI applications introduce additional logging challenges. A single request may contain a user prompt, retrieved documents, model responses, tool calls, API responses, and execution metadata. If the application records all this information without proper controls, sensitive data can end up in log files.
For example, a customer might enter an email address, access token, payment detail, or confidential business document into an AI assistant. If the application logs the complete request for debugging, that information may remain in centralized logging systems long after the original request has finished.
The problem becomes more serious when logs are accessible to multiple development teams, external monitoring services, or third-party observability platforms.
Developers need a logging strategy that provides enough information to troubleshoot AI applications without exposing sensitive user data.
Why AI Application Logs Need Special Protection
Traditional applications generally log request metadata, application events, database errors, and execution details.
AI applications may also handle information that is difficult to predict or classify in advance.
Consider a customer support assistant that receives this request:
My account email is [email protected].
My temporary access token is abc123-secret-token.
Please help me understand why my account was locked.
A poorly configured application might log the complete request:
INFO Request received:
{
"email": "[email protected]",
"token": "abc123-secret-token",
"message": "Please help me understand why my account was locked."
}
This creates unnecessary exposure.
The token could be copied into a log aggregation platform, retained in backups, or accessed by someone who does not need permission to view customer credentials.
AI applications can expose sensitive information through several logging points:
User prompts and uploaded documents.
Retrieved RAG content.
Model-generated responses.
Tool arguments and tool results.
API headers and request bodies.
Exception messages.
Debug traces and conversation history.
Protecting only the initial API request is not enough. Sensitive information can appear later in the processing pipeline.
Identify Sensitive Data Before Logging
The first step is to define which information should not appear in application logs.
Common categories include:
Data category | Examples | Logging approach |
|---|
Authentication credentials | API keys, passwords, access tokens | Never log values |
Personal information | Email addresses, phone numbers, addresses | Mask or exclude |
Financial information | Card numbers, bank details | Exclude or tokenize |
Health information | Medical records, patient details | Exclude unless specifically authorized |
Business-confidential data | Contracts, internal reports | Restrict or redact |
Session information | Cookies, session identifiers | Never log raw values |
The exact classification depends on the application, applicable regulations, contractual obligations, and organizational policies.
Not every field needs to be removed. Request IDs, model names, response status codes, execution time, and token counts can often be recorded without storing the actual user content.
The goal is to distinguish operational metadata from sensitive payload data.
Use Structured Logging Instead of Logging Complete Requests
Structured logging records application events as fields rather than combining everything into a large text message.
For example, avoid:
logger.LogInformation(
"AI request received: {Request}",
JsonSerializer.Serialize(request));
This may serialize every property in the request, including fields that should never enter the logs.
Instead, explicitly select the information required for monitoring:
logger.LogInformation(
"AI request received. RequestId: {RequestId}, Model: {Model}, UserId: {UserId}",
requestId,
modelName,
userId);
The second example records useful operational details without logging the prompt, credentials, or uploaded content.
Be careful with identifiers as well. A user ID may still be personal or sensitive information depending on the application. Where possible, use an internal pseudonymous identifier and apply access controls to the resulting logs.
A useful logging rule is to allowlist fields rather than logging an entire object and trying to remove sensitive properties afterward.
Implement Sensitive Data Redaction in C#
For applications built with ASP.NET Core, a logging helper can remove known sensitive values before recording structured data.
The following example demonstrates basic field-level redaction.
using System.Text.Json;
using System.Text.Json.Nodes;
public static class LogSanitizer
{
private static readonly HashSet<string> SensitiveFields =
new(StringComparer.OrdinalIgnoreCase)
{
"password",
"token",
"accessToken",
"apiKey",
"authorization",
"creditCardNumber",
"secret"
};
public static string SanitizeJson(string json)
{
JsonNode? root = JsonNode.Parse(json);
if (root == null)
return "{}";
RedactNode(root);
return root.ToJsonString();
}
private static void RedactNode(JsonNode node)
{
if (node is JsonObject obj)
{
foreach (var property in obj.ToList())
{
if (SensitiveFields.Contains(property.Key))
{
obj[property.Key] = "[REDACTED]";
}
else if (property.Value != null)
{
RedactNode(property.Value);
}
}
}
else if (node is JsonArray array)
{
foreach (var item in array)
{
if (item != null)
{
RedactNode(item);
}
}
}
}
}
Example:
string requestJson = """
{
"userId": "user-101",
"email": "[email protected]",
"accessToken": "abc123-secret-token",
"message": "Help me access my account"
}
""";
string safeJson = LogSanitizer.SanitizeJson(requestJson);
logger.LogInformation(
"Sanitized request: {Request}",
safeJson);
The resulting output will contain the redacted access token.
However, this example is not a complete data protection solution.
Sensitive information can appear in free-text fields such as message, nested document content, headers, and exception messages. Field-name matching cannot identify every possible secret. Production systems should combine allowlisted logging, schema-aware redaction, secret detection, and tests.
Avoid Logging Prompts and Model Responses by Default
AI applications often record prompts and responses to investigate unexpected model behavior.
This can be useful during development, but it creates significant data exposure risks in production.
A safer default is to record metadata instead:
logger.LogInformation(
"AI generation completed. RequestId: {RequestId}, " +
"Model: {Model}, InputTokens: {InputTokens}, " +
"OutputTokens: {OutputTokens}, DurationMs: {DurationMs}",
requestId,
modelName,
inputTokens,
outputTokens,
durationMs);
This gives developers useful operational information without storing the conversation itself.
If prompt or response capture is necessary for a specific debugging or evaluation workflow, use a separate controlled process with:
Explicit data collection rules.
Appropriate user notice or authorization.
Sensitive data redaction.
Restricted access.
Short retention periods.
Auditing of data access.
Do not enable full prompt logging simply because it makes debugging easier.
Protect Tool Calls and External API Responses
AI agents often interact with external services through tools.
For example, an agent may call a customer database, send an email, create a support ticket, or retrieve information from an internal API.
These operations can expose sensitive values through tool arguments and responses.
Consider this example:
logger.LogInformation(
"Executing tool: {ToolName}, Arguments: {Arguments}",
toolName,
JsonSerializer.Serialize(arguments));
If the tool arguments contain an access token or customer information, the complete payload will be recorded.
A safer approach is to log the operation and its outcome:
logger.LogInformation(
"Tool execution started. Tool: {ToolName}, RequestId: {RequestId}",
toolName,
requestId);
logger.LogInformation(
"Tool execution completed. Tool: {ToolName}, Status: {Status}",
toolName,
"Success");
For failures, record a sanitized error category and correlation identifier rather than the entire external API response.
Also check HTTP logging middleware. Some middleware configurations can record request headers or bodies automatically. Ensure that authorization headers, cookies, and sensitive payload fields are excluded.
Use Correlation IDs for Troubleshooting
Developers need a way to connect events belonging to the same AI request without recording the complete conversation.
A correlation ID provides this capability.
For example, a single request may produce these events:
Request received RequestId: req-1001
Documents retrieved RequestId: req-1001
Model execution started RequestId: req-1001
Tool execution started RequestId: req-1001
Response generated RequestId: req-1001
Request completed RequestId: req-1001
The development team can follow the request through the application without storing the user's full prompt or the retrieved documents.
In ASP.NET Core, the request trace identifier can be used as a starting point:
app.Use(async (context, next) =>
{
string requestId = context.TraceIdentifier;
using (logger.BeginScope(
new Dictionary<string, object>
{
["RequestId"] = requestId
}))
{
await next();
}
});
In distributed AI systems, OpenTelemetry trace and span identifiers can provide additional visibility across services.
Avoid placing sensitive information inside trace attributes or span events. Observability data needs the same protection as application logs.
Configure Log Retention and Access Controls
Redacting sensitive data is only one part of log security.
Even sanitized logs should not remain accessible indefinitely.
A production logging strategy should define:
Who can access application logs.
Which environments can generate detailed logs.
How long logs are retained.
Whether logs are encrypted in transit and at rest.
How access to logs is audited.
How exported log data is protected.
Use role-based access control so developers, support teams, security teams, and administrators receive only the permissions required for their responsibilities.
Avoid giving every developer access to production logs by default.
Separate development and production logging configurations. Debug-level logging may be appropriate in a controlled local environment, but production systems should use a carefully reviewed logging policy.
Retention requirements should be based on operational needs and applicable legal or contractual obligations. Longer retention is not automatically better.
Test Logging Behavior Before Production
Logging security should be tested like other application functionality.
Create test cases containing sample credentials, personal information, and confidential content. Execute normal requests and failure scenarios, then inspect the generated logs.
For example:
[Fact]
public void SanitizeJson_ShouldRedactAccessToken()
{
string json = """
{
"userId": "user-101",
"accessToken": "secret-value"
}
""";
string result = LogSanitizer.SanitizeJson(json);
Assert.Contains("[REDACTED]", result);
Assert.DoesNotContain("secret-value", result);
}
This verifies one redaction rule. Additional tests should cover nested objects, arrays, unexpected field names, malformed input, and sensitive information in exception paths.
Also test:
Failed model requests.
Tool execution failures.
Authentication errors.
Document retrieval failures.
HTTP request and response logging.
Background jobs and asynchronous processing.
A common mistake is to test only successful requests. Sensitive information frequently appears in error messages and diagnostic traces.
Common Mistakes to Avoid
Logging complete request objects
Serializing entire request objects can expose fields that were not intended for logging. Select approved fields explicitly.
Relying only on regular expressions
Regular expressions can detect known formats, but they cannot reliably identify every type of sensitive information. Combine pattern matching with structured data controls.
Protecting prompts but ignoring tool responses
Tool arguments, database results, and external API responses can contain the same sensitive information as user prompts.
Keeping production debug logs enabled
Detailed logging increases the amount of information available to anyone who gains access to the logging system. Use controlled logging levels and temporary diagnostic procedures.
Assuming deleted application logs are completely removed
Logs may exist in backups, replicas, exports, or third-party monitoring systems. Define retention and deletion procedures across the entire logging pipeline.
Summary
AI applications process more than ordinary request metadata. Prompts, retrieved documents, model responses, tool arguments, and external API results can all contain sensitive information.
Logging these payloads without proper controls creates unnecessary security and privacy risks.
Developers should use structured logging, allowlist approved fields, redact sensitive values, avoid recording full prompts and responses by default, and protect tool execution logs. Correlation IDs and distributed tracing can provide useful debugging information without exposing complete user conversations.
Log access, encryption, retention, and automated security tests should also be part of the application's production design.
The objective is to make AI applications observable without turning their logging infrastructure into another location where confidential information can be exposed.
Join the conversation! Your thoughts help the community grow.