Skip to content

Commit c7675ae

Browse files
CopilotstephentoubJamesNK
authored
Add OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT environment variable support to MEAI telemetry (#6790)
* Initial plan * Implement OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT environment variable support Co-authored-by: stephentoub <[email protected]> * Move ShouldEnableSensitiveDataByDefault to shared TelemetryHelpers class Co-authored-by: JamesNK <[email protected]> * Address feedback --------- Co-authored-by: copilot-swe-agent[bot] <[email protected]> Co-authored-by: stephentoub <[email protected]> Co-authored-by: JamesNK <[email protected]> Co-authored-by: Stephen Toub <[email protected]>
1 parent 4270c00 commit c7675ae

File tree

8 files changed

+28
-11
lines changed

8 files changed

+28
-11
lines changed

src/Libraries/Microsoft.Extensions.AI/ChatCompletion/FunctionInvokingChatClient.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,7 +1128,7 @@ FunctionResultContent CreateFunctionResultContent(FunctionInvocationResult resul
11281128
startingTimestamp = Stopwatch.GetTimestamp();
11291129
if (_logger.IsEnabled(LogLevel.Trace))
11301130
{
1131-
LogInvokingSensitive(context.Function.Name, LoggingHelpers.AsJson(context.Arguments, context.Function.JsonSerializerOptions));
1131+
LogInvokingSensitive(context.Function.Name, TelemetryHelpers.AsJson(context.Arguments, context.Function.JsonSerializerOptions));
11321132
}
11331133
else
11341134
{
@@ -1169,7 +1169,7 @@ FunctionResultContent CreateFunctionResultContent(FunctionInvocationResult resul
11691169

11701170
if (result is not null && _logger.IsEnabled(LogLevel.Trace))
11711171
{
1172-
LogInvocationCompletedSensitive(context.Function.Name, elapsed, LoggingHelpers.AsJson(result, context.Function.JsonSerializerOptions));
1172+
LogInvocationCompletedSensitive(context.Function.Name, elapsed, TelemetryHelpers.AsJson(result, context.Function.JsonSerializerOptions));
11731173
}
11741174
else
11751175
{

src/Libraries/Microsoft.Extensions.AI/ChatCompletion/LoggingChatClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -169,7 +169,7 @@ public override async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseA
169169
}
170170
}
171171

172-
private string AsJson<T>(T value) => LoggingHelpers.AsJson(value, _jsonSerializerOptions);
172+
private string AsJson<T>(T value) => TelemetryHelpers.AsJson(value, _jsonSerializerOptions);
173173

174174
[LoggerMessage(LogLevel.Debug, "{MethodName} invoked.")]
175175
private partial void LogInvoked(string methodName);

src/Libraries/Microsoft.Extensions.AI/ChatCompletion/OpenTelemetryChatClient.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,16 @@ protected override void Dispose(bool disposing)
110110
/// <value>
111111
/// <see langword="true"/> if potentially sensitive information should be included in telemetry;
112112
/// <see langword="false"/> if telemetry shouldn't include raw inputs and outputs.
113-
/// The default value is <see langword="false"/>.
113+
/// The default value is <see langword="false"/>, unless the <c>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT</c>
114+
/// environment variable is set to "true" (case-insensitive).
114115
/// </value>
115116
/// <remarks>
116117
/// By default, telemetry includes metadata, such as token counts, but not raw inputs
117118
/// and outputs, such as message content, function call arguments, and function call results.
119+
/// The default value can be overridden by setting the <c>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT</c>
120+
/// environment variable to "true". Explicitly setting this property will override the environment variable.
118121
/// </remarks>
119-
public bool EnableSensitiveData { get; set; }
122+
public bool EnableSensitiveData { get; set; } = TelemetryHelpers.EnableSensitiveDataDefault;
120123

121124
/// <inheritdoc/>
122125
public override object? GetService(Type serviceType, object? serviceKey = null) =>

src/Libraries/Microsoft.Extensions.AI/Embeddings/OpenTelemetryEmbeddingGenerator.cs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -89,13 +89,16 @@ public OpenTelemetryEmbeddingGenerator(IEmbeddingGenerator<TInput, TEmbedding> i
8989
/// <value>
9090
/// <see langword="true"/> if potentially sensitive information should be included in telemetry;
9191
/// <see langword="false"/> if telemetry shouldn't include raw inputs and outputs.
92-
/// The default value is <see langword="false"/>.
92+
/// The default value is <see langword="false"/>, unless the <c>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT</c>
93+
/// environment variable is set to "true" (case-insensitive).
9394
/// </value>
9495
/// <remarks>
9596
/// By default, telemetry includes metadata, such as token counts, but not raw inputs
9697
/// and outputs or additional options data.
98+
/// The default value can be overridden by setting the <c>OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT</c>
99+
/// environment variable to "true". Explicitly setting this property will override the environment variable.
97100
/// </remarks>
98-
public bool EnableSensitiveData { get; set; }
101+
public bool EnableSensitiveData { get; set; } = TelemetryHelpers.EnableSensitiveDataDefault;
99102

100103
/// <inheritdoc/>
101104
public override object? GetService(Type serviceType, object? serviceKey = null) =>

src/Libraries/Microsoft.Extensions.AI/Image/LoggingImageGenerator.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -102,7 +102,7 @@ public override async Task<ImageGenerationResponse> GenerateAsync(
102102
}
103103
}
104104

105-
private string AsJson<T>(T value) => LoggingHelpers.AsJson(value, _jsonSerializerOptions);
105+
private string AsJson<T>(T value) => TelemetryHelpers.AsJson(value, _jsonSerializerOptions);
106106

107107
[LoggerMessage(LogLevel.Debug, "{MethodName} invoked.")]
108108
private partial void LogInvoked(string methodName);

src/Libraries/Microsoft.Extensions.AI/OpenTelemetryConsts.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,9 @@ internal static class OpenTelemetryConsts
1414
public const string SecondsUnit = "s";
1515
public const string TokensUnit = "token";
1616

17+
/// <summary>Environment variable name for controlling whether sensitive content should be captured in telemetry by default.</summary>
18+
public const string GenAICaptureMessageContentEnvVar = "OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT";
19+
1720
public const string ToolTypeFunction = "function";
1821

1922
public const string TypeText = "text";

src/Libraries/Microsoft.Extensions.AI/SpeechToText/LoggingSpeechToTextClient.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,7 @@ public override async IAsyncEnumerable<SpeechToTextResponseUpdate> GetStreamingT
179179
}
180180
}
181181

182-
private string AsJson<T>(T value) => LoggingHelpers.AsJson(value, _jsonSerializerOptions);
182+
private string AsJson<T>(T value) => TelemetryHelpers.AsJson(value, _jsonSerializerOptions);
183183

184184
[LoggerMessage(LogLevel.Debug, "{MethodName} invoked.")]
185185
private partial void LogInvoked(string methodName);

src/Libraries/Microsoft.Extensions.AI/LoggingHelpers.cs renamed to src/Libraries/Microsoft.Extensions.AI/TelemetryHelpers.cs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,14 +4,22 @@
44
#pragma warning disable CA1031 // Do not catch general exception types
55
#pragma warning disable S108 // Nested blocks of code should not be left empty
66
#pragma warning disable S2486 // Generic exceptions should not be ignored
7+
#pragma warning disable SA1623 // Property summary documentation should match accessors
78

9+
using System;
810
using System.Text.Json;
911

1012
namespace Microsoft.Extensions.AI;
1113

12-
/// <summary>Provides internal helpers for implementing logging.</summary>
13-
internal static class LoggingHelpers
14+
/// <summary>Provides internal helpers for implementing telemetry.</summary>
15+
internal static class TelemetryHelpers
1416
{
17+
/// <summary>Gets a value the OpenTelemetry clients should use for their EnableSensitiveData property's default value.</summary>
18+
/// <remarks>Defaults to false. May be overridden by setting the OTEL_INSTRUMENTATION_GENAI_CAPTURE_MESSAGE_CONTENT environment variable to "true".</remarks>
19+
public static bool EnableSensitiveDataDefault { get; } =
20+
Environment.GetEnvironmentVariable(OpenTelemetryConsts.GenAICaptureMessageContentEnvVar) is string envVar &&
21+
string.Equals(envVar, "true", StringComparison.OrdinalIgnoreCase);
22+
1523
/// <summary>Serializes <paramref name="value"/> as JSON for logging purposes.</summary>
1624
public static string AsJson<T>(T value, JsonSerializerOptions? options)
1725
{

0 commit comments

Comments
 (0)