Skip to content

Commit 890ee0c

Browse files
authored
Some otel traces and logging adjustments (#2189)
1 parent 90da14a commit 890ee0c

File tree

7 files changed

+25
-13
lines changed

7 files changed

+25
-13
lines changed

.editorconfig

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,9 @@ dotnet_diagnostic.IDE0059.severity = suggestion
240240

241241
dotnet_diagnostic.CA1859.severity = none
242242

243+
# https://learn.microsoft.com/en-us/dotnet/fundamentals/code-analysis/quality-rules/ca1727
244+
dotnet_diagnostic.CA1727.severity = none
245+
243246
dotnet_diagnostic.IDE0305.severity = none
244247

245248
# https://github.com/dotnet/roslyn/issues/60784

src/api/Elastic.Documentation.Api.Core/AskAi/AskAiUsecase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ public async Task<Stream> AskAi(AskAiRequest askAiRequest, Cancel ctx)
3030
};
3131
var inputMessagesJson = JsonSerializer.Serialize(inputMessages, ApiJsonContext.Default.InputMessageArray);
3232
_ = activity?.SetTag("gen_ai.input.messages", inputMessagesJson);
33-
logger.LogInformation("AskAI input message: {InputMessage}", askAiRequest.Message);
33+
logger.LogInformation("AskAI input message: {ask_ai.input.message}", askAiRequest.Message);
3434
logger.LogInformation("Streaming AskAI response");
3535
var rawStream = await askAiGateway.AskAi(askAiRequest, ctx);
3636
// The stream transformer will handle disposing the activity when streaming completes

src/api/Elastic.Documentation.Api.Core/SerializationContext.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ public record OutputMessage(string Role, MessagePart[] Parts, string FinishReaso
2121
[JsonSerializable(typeof(SearchRequest))]
2222
[JsonSerializable(typeof(SearchResponse))]
2323
[JsonSerializable(typeof(InputMessage))]
24-
[JsonSerializable(typeof(OutputMessage))]
24+
[JsonSerializable(typeof(OutputMessage[]))]
2525
[JsonSerializable(typeof(MessagePart))]
2626
[JsonSerializable(typeof(InputMessage[]))]
2727
[JsonSourceGenerationOptions(PropertyNamingPolicy = JsonKnownNamingPolicy.CamelCase)]

src/api/Elastic.Documentation.Api.Infrastructure/Adapters/AskAi/AgentBuilderStreamTransformer.cs

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,18 @@ public class AgentBuilderStreamTransformer(ILogger<AgentBuilderStreamTransformer
1515
{
1616
protected override string GetAgentId() => AgentBuilderAskAiGateway.ModelName;
1717
protected override string GetAgentProvider() => AgentBuilderAskAiGateway.ProviderName;
18-
protected override AskAiEvent? TransformJsonEvent(string? conversationId, string? eventType, JsonElement json)
18+
protected override AskAiEvent? TransformJsonEvent(string? eventType, JsonElement json)
1919
{
2020
var type = eventType ?? "message";
2121
var timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
2222
var id = Guid.NewGuid().ToString();
2323

24+
// Handle error events first - they have a different structure (no "data" wrapper)
25+
if (type == "error")
26+
{
27+
return ParseErrorEvent(id, timestamp, json);
28+
}
29+
2430
// Most Agent Builder events have data nested in a "data" property
2531
if (!json.TryGetProperty("data", out var innerData))
2632
{
@@ -30,8 +36,6 @@ public class AgentBuilderStreamTransformer(ILogger<AgentBuilderStreamTransformer
3036

3137
return type switch
3238
{
33-
"error" =>
34-
ParseErrorEvent(id, timestamp, json),
3539

3640
"conversation_id_set" when innerData.TryGetProperty("conversation_id", out var convId) =>
3741
new AskAiEvent.ConversationStart(id, timestamp, convId.GetString()!),

src/api/Elastic.Documentation.Api.Infrastructure/Adapters/AskAi/LlmGatewayStreamTransformer.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ protected override async Task ProcessStreamAsync(PipeReader reader, PipeWriter w
4747
// Continue with normal stream processing using the actual conversation ID
4848
await base.ProcessStreamAsync(reader, writer, actualConversationId, parentActivity, cancellationToken);
4949
}
50-
protected override AskAiEvent? TransformJsonEvent(string? conversationId, string? eventType, JsonElement json)
50+
protected override AskAiEvent? TransformJsonEvent(string? eventType, JsonElement json)
5151
{
5252
// LLM Gateway format: ["custom", {type: "...", ...}]
5353
if (json.ValueKind != JsonValueKind.Array || json.GetArrayLength() < 2)

src/api/Elastic.Documentation.Api.Infrastructure/Adapters/AskAi/SseParser.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
using System.IO.Pipelines;
77
using System.Runtime.CompilerServices;
88
using System.Text;
9+
using System.Text.Json.Serialization;
910

1011
namespace Elastic.Documentation.Api.Infrastructure.Adapters.AskAi;
1112

@@ -99,3 +100,7 @@ private static bool TryReadLine(ref ReadOnlySequence<byte> buffer, out string li
99100
return true;
100101
}
101102
}
103+
104+
105+
[JsonSerializable(typeof(SseEvent))]
106+
internal sealed partial class SseSerializerContext : JsonSerializerContext;

src/api/Elastic.Documentation.Api.Infrastructure/Adapters/AskAi/StreamTransformerBase.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ protected virtual async Task ProcessStreamAsync(PipeReader reader, PipeWriter wr
140140
var root = doc.RootElement;
141141

142142
// Subclass transforms JsonElement to AskAiEvent
143-
transformedEvent = TransformJsonEvent(conversationId, sseEvent.EventType, root);
143+
transformedEvent = TransformJsonEvent(sseEvent.EventType, root);
144144
}
145145
catch (JsonException ex)
146146
{
@@ -153,6 +153,7 @@ protected virtual async Task ProcessStreamAsync(PipeReader reader, PipeWriter wr
153153
{
154154
Logger.LogWarning("Transformed event is null for transformer {TransformerType}. Skipping event. EventType: {EventType}",
155155
GetType().Name, sseEvent.EventType);
156+
Logger.LogWarning("Original event: {event}", JsonSerializer.Serialize(sseEvent, SseSerializerContext.Default.SseEvent));
156157
continue;
157158
}
158159

@@ -213,7 +214,7 @@ protected virtual async Task ProcessStreamAsync(PipeReader reader, PipeWriter wr
213214
case AskAiEvent.MessageComplete messageComplete:
214215
{
215216
outputMessageParts.Add(new MessagePart("text", messageComplete.FullContent));
216-
Logger.LogInformation("AskAI output message: {OutputMessage}", messageComplete.FullContent);
217+
Logger.LogInformation("AskAI output message: {ask_ai.output.message}", messageComplete.FullContent);
217218
break;
218219
}
219220
case AskAiEvent.ConversationEnd conversationEnd:
@@ -228,22 +229,21 @@ protected virtual async Task ProcessStreamAsync(PipeReader reader, PipeWriter wr
228229
// Set output messages tag once after all events are processed
229230
if (outputMessageParts.Count > 0)
230231
{
231-
var outputMessages = new OutputMessage("assistant", outputMessageParts.ToArray(), "stop");
232-
var outputMessagesJson = JsonSerializer.Serialize(outputMessages, ApiJsonContext.Default.OutputMessage);
232+
var outputMessage = new OutputMessage("assistant", outputMessageParts.ToArray(), "stop");
233+
var outputMessages = new[] { outputMessage };
234+
var outputMessagesJson = JsonSerializer.Serialize(outputMessages, ApiJsonContext.Default.OutputMessageArray);
233235
_ = parentActivity?.SetTag("gen_ai.output.messages", outputMessagesJson);
234-
_ = activity?.SetTag("gen_ai.output.messages", outputMessagesJson);
235236
}
236237
}
237238

238239
/// <summary>
239240
/// Transform a parsed JSON event into an AskAiEvent.
240241
/// Subclasses implement provider-specific transformation logic.
241242
/// </summary>
242-
/// <param name="conversationId">The conversation/thread ID, if available</param>
243243
/// <param name="eventType">The SSE event type (from "event:" field), or null if not present</param>
244244
/// <param name="json">The parsed JSON data from the "data:" field</param>
245245
/// <returns>The transformed AskAiEvent, or null to skip this event</returns>
246-
protected abstract AskAiEvent? TransformJsonEvent(string? conversationId, string? eventType, JsonElement json);
246+
protected abstract AskAiEvent? TransformJsonEvent(string? eventType, JsonElement json);
247247

248248
/// <summary>
249249
/// Write a transformed event to the output stream

0 commit comments

Comments
 (0)