From 10d8159464b3bfd89c8be582a015aee406039213 Mon Sep 17 00:00:00 2001 From: Georgios Andrianakis Date: Wed, 18 Dec 2024 09:58:36 +0200 Subject: [PATCH] Be more defensive in setting metadata for observability events Without this change it was possible in some of the ITs, depending on the mock response from the server, to have NPEs being thrown. These NPEs didn't affect the response, but they did clutter up the logs --- .../listeners/MetricsChatModelListener.java | 19 +++++++++++-------- .../listeners/SpanChatModelListener.java | 5 ++++- 2 files changed, 15 insertions(+), 9 deletions(-) diff --git a/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/MetricsChatModelListener.java b/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/MetricsChatModelListener.java index ee3df4e9b..094f4215f 100644 --- a/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/MetricsChatModelListener.java +++ b/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/MetricsChatModelListener.java @@ -16,7 +16,6 @@ import io.micrometer.core.instrument.Counter; import io.micrometer.core.instrument.Meter; import io.micrometer.core.instrument.Metrics; -import io.micrometer.core.instrument.Tag; import io.micrometer.core.instrument.Tags; import io.micrometer.core.instrument.Timer; import io.quarkiverse.langchain4j.cost.Cost; @@ -78,9 +77,10 @@ public void onResponse(ChatModelResponseContext responseContext) { ChatModelRequest request = responseContext.request(); ChatModelResponse response = responseContext.response(); - Tags tags = Tags.of( - Tag.of("gen_ai.request.model", request.model()), - Tag.of("gen_ai.response.model", response.model())); + Tags tags = Tags.of("gen_ai.request.model", request.model()); + if (response.model() != null) { + tags = tags.and("gen_ai.response.model", response.model()); + } if (ContextLocals.duplicatedContextActive()) { String aiServiceClassName = ContextLocals.get(AiServiceConstants.AI_SERVICE_CLASS_NAME); if (aiServiceClassName != null) { @@ -112,10 +112,13 @@ public void onError(ChatModelErrorContext errorContext) { return; } - Tags tags = Tags.of( - Tag.of("gen_ai.request.model", errorContext.request().model()), - Tag.of("gen_ai.response.model", errorContext.partialResponse().model()), - Tag.of("error.type", aiMessage.text())); + Tags tags = Tags.of("gen_ai.request.model", errorContext.request().model()); + if (errorContext.partialResponse().model() != null) { + tags = tags.and("gen_ai.response.model", errorContext.partialResponse().model()); + } + if (aiMessage.text() != null) { + tags = tags.and("error.type", aiMessage.text()); + } duration.withTags(tags).record(endTime - startTime, TimeUnit.NANOSECONDS); } diff --git a/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/SpanChatModelListener.java b/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/SpanChatModelListener.java index a6668084f..5dade6b6d 100644 --- a/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/SpanChatModelListener.java +++ b/core/runtime/src/main/java/io/quarkiverse/langchain4j/runtime/listeners/SpanChatModelListener.java @@ -61,7 +61,10 @@ public void onResponse(ChatModelResponseContext responseContext) { Span span = (Span) attributes.get(OTEL_SPAN_KEY_NAME); if (span != null) { ChatModelResponse response = responseContext.response(); - span.setAttribute("gen_ai.response.id", response.id()).setAttribute("gen_ai.response.model", response.model()); + span.setAttribute("gen_ai.response.id", response.id()); + if (response.model() != null) { + span.setAttribute("gen_ai.response.model", response.model()); + } if (response.finishReason() != null) { span.setAttribute("gen_ai.response.finish_reasons", response.finishReason().toString()); }