Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit25685eb

Browse files
committed
Fix OpenTelemetryChatClient failing on unknown content types
It should fail gracefully by ignoring any content it can't output telemetry for rather than throwing.
1 parent1eb963e commit25685eb

File tree

2 files changed

+96
-5
lines changed

2 files changed

+96
-5
lines changed

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

Lines changed: 25 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
usingSystem.Text.Encodings.Web;
1111
usingSystem.Text.Json;
1212
usingSystem.Text.Json.Serialization;
13+
usingSystem.Text.Json.Serialization.Metadata;
1314
usingSystem.Threading;
1415
usingSystem.Threading.Tasks;
1516
usingMicrosoft.Extensions.Logging;
@@ -216,7 +217,8 @@ public override async IAsyncEnumerable<ChatResponseUpdate> GetStreamingResponseA
216217
}
217218
}
218219

219-
internalstaticstringSerializeChatMessages(IEnumerable<ChatMessage>messages,ChatFinishReason?chatFinishReason=null)
220+
internalstaticstringSerializeChatMessages(
221+
IEnumerable<ChatMessage>messages,ChatFinishReason?chatFinishReason=null,JsonSerializerOptions?customContentSerializerOptions=null)
220222
{
221223
List<object>output=[];
222224

@@ -293,10 +295,28 @@ internal static string SerializeChatMessages(IEnumerable<ChatMessage> messages,
293295
break;
294296

295297
default:
298+
JsonElementelement=_emptyObject;
299+
try
300+
{
301+
JsonTypeInfo?unknownContentTypeInfo=
302+
customContentSerializerOptions?.TryGetTypeInfo(content.GetType(),outJsonTypeInfo?ctsi)istrue?ctsi:
303+
_defaultOptions.TryGetTypeInfo(content.GetType(),outJsonTypeInfo?dtsi)?dtsi:
304+
null;
305+
306+
if(unknownContentTypeInfois notnull)
307+
{
308+
element=JsonSerializer.SerializeToElement(content,unknownContentTypeInfo);
309+
}
310+
}
311+
catch
312+
{
313+
// Ignore the contents of any parts that can't be serialized.
314+
}
315+
296316
m.Parts.Add(newOtelGenericPart
297317
{
298318
Type=content.GetType().FullName!,
299-
Content=content,
319+
Content=element,
300320
});
301321
break;
302322
}
@@ -558,7 +578,7 @@ private void AddInputMessagesTags(IEnumerable<ChatMessage> messages, ChatOptions
558578

559579
_=activity.AddTag(
560580
OpenTelemetryConsts.GenAI.Input.Messages,
561-
SerializeChatMessages(messages));
581+
SerializeChatMessages(messages,customContentSerializerOptions:_jsonSerializerOptions));
562582
}
563583
}
564584

@@ -568,7 +588,7 @@ private void AddOutputMessagesTags(ChatResponse response, Activity? activity)
568588
{
569589
_=activity.AddTag(
570590
OpenTelemetryConsts.GenAI.Output.Messages,
571-
SerializeChatMessages(response.Messages,response.FinishReason));
591+
SerializeChatMessages(response.Messages,response.FinishReason,customContentSerializerOptions:_jsonSerializerOptions));
572592
}
573593
}
574594

@@ -609,6 +629,7 @@ private sealed class OtelFunction
609629
}
610630

611631
privatestaticreadonlyJsonSerializerOptions_defaultOptions=CreateDefaultOptions();
632+
privatestaticreadonlyJsonElement_emptyObject=JsonSerializer.SerializeToElement(newobject(),_defaultOptions.GetTypeInfo(typeof(object)));
612633

613634
privatestaticJsonSerializerOptionsCreateDefaultOptions()
614635
{

‎test/Libraries/Microsoft.Extensions.AI.Tests/ChatCompletion/OpenTelemetryChatClientTests.cs‎

Lines changed: 71 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -329,7 +329,77 @@ async static IAsyncEnumerable<ChatResponseUpdate> CallbackAsync(
329329
Assert.False(tags.ContainsKey("gen_ai.system_instructions"));
330330
Assert.False(tags.ContainsKey("gen_ai.tool.definitions"));
331331
}
332+
}
333+
334+
[Fact]
335+
publicasyncTaskUnknownContentTypes_Ignored()
336+
{
337+
varsourceName=Guid.NewGuid().ToString();
338+
varactivities=newList<Activity>();
339+
usingvartracerProvider=OpenTelemetry.Sdk.CreateTracerProviderBuilder()
340+
.AddSource(sourceName)
341+
.AddInMemoryExporter(activities)
342+
.Build();
343+
344+
usingvarinnerClient=newTestChatClient
345+
{
346+
GetResponseAsyncCallback=async(messages,options,cancellationToken)=>
347+
{
348+
awaitTask.Yield();
349+
returnnewChatResponse(newChatMessage(ChatRole.Assistant,"The blue whale, I think."));
350+
},
351+
};
352+
353+
usingvarchatClient=innerClient
354+
.AsBuilder()
355+
.UseOpenTelemetry(null,sourceName,configure: instance=>
356+
{
357+
instance.EnableSensitiveData=true;
358+
instance.JsonSerializerOptions=TestJsonSerializerContext.Default.Options;
359+
})
360+
.Build();
332361

333-
staticstringReplaceWhitespace(string?input)=>Regex.Replace(input??"",@"\s+"," ").Trim();
362+
List<ChatMessage>messages=
363+
[
364+
new(ChatRole.User,
365+
[
366+
newTextContent("Hello!"),
367+
newNonSerializableAIContent(),
368+
newTextContent("How are you?"),
369+
]),
370+
];
371+
372+
varresponse=awaitchatClient.GetResponseAsync(messages);
373+
Assert.NotNull(response);
374+
375+
varactivity=Assert.Single(activities);
376+
Assert.NotNull(activity);
377+
378+
varinputMessages=activity.Tags.First(kvp=>kvp.Key=="gen_ai.input.messages").Value;
379+
Assert.Equal(ReplaceWhitespace("""
380+
[
381+
{
382+
"role": "user",
383+
"parts": [
384+
{
385+
"type": "text",
386+
"content": "Hello!"
387+
},
388+
{
389+
"type": "Microsoft.Extensions.AI.OpenTelemetryChatClientTests+NonSerializableAIContent",
390+
"content": {}
391+
},
392+
{
393+
"type": "text",
394+
"content": "How are you?"
395+
}
396+
]
397+
}
398+
]
399+
"""),ReplaceWhitespace(inputMessages));
334400
}
401+
402+
privatesealedclassNonSerializableAIContent:AIContent;
403+
404+
privatestaticstringReplaceWhitespace(string?input)=>Regex.Replace(input??"",@"\s+"," ").Trim();
335405
}

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp