From 6a43b3121887e1fe03b3a40cd67c7393c877554e Mon Sep 17 00:00:00 2001 From: Shardul Natu <43422294+kiranani@users.noreply.github.com> Date: Wed, 26 Nov 2025 20:46:40 -0800 Subject: [PATCH] update(telemetry): OTel API response event with finish reasons (#13849) Co-authored-by: Shnatu --- docs/cli/telemetry.md | 1 + packages/core/src/telemetry/loggers.test.ts | 1 + packages/core/src/telemetry/types.ts | 8 +++++--- 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/docs/cli/telemetry.md b/docs/cli/telemetry.md index 6deaaef838..d93beff3b4 100644 --- a/docs/cli/telemetry.md +++ b/docs/cli/telemetry.md @@ -361,6 +361,7 @@ Captures Gemini API requests, responses, and errors. - `response_text` (string, optional) - `prompt_id` (string) - `auth_type` (string) + - `finish_reasons` (array of strings) - `gemini_cli.api_error`: API request failed. - **Attributes**: diff --git a/packages/core/src/telemetry/loggers.test.ts b/packages/core/src/telemetry/loggers.test.ts index 282c266083..9ae976b7b2 100644 --- a/packages/core/src/telemetry/loggers.test.ts +++ b/packages/core/src/telemetry/loggers.test.ts @@ -409,6 +409,7 @@ describe('loggers', () => { attributes: expect.objectContaining({ 'event.name': EVENT_API_RESPONSE, prompt_id: 'prompt-id-1', + finish_reasons: ['stop'], }), }); diff --git a/packages/core/src/telemetry/types.ts b/packages/core/src/telemetry/types.ts index a7d50fd332..fe218ecee1 100644 --- a/packages/core/src/telemetry/types.ts +++ b/packages/core/src/telemetry/types.ts @@ -31,6 +31,7 @@ import type { AgentTerminateMode } from '../agents/types.js'; import { getCommonAttributes } from './telemetryAttributes.js'; import { SemanticAttributes } from '@opentelemetry/semantic-conventions'; import { safeJsonStringify } from '../utils/safeJsonStringify.js'; +import type { OTelFinishReason } from './semantic.js'; import { toInputMessages, toOutputMessages, @@ -545,6 +546,7 @@ export class ApiResponseEvent implements BaseTelemetryEvent { prompt: GenAIPromptDetails; response: GenAIResponseDetails; usage: GenAIUsageDetails; + finish_reasons: OTelFinishReason[]; constructor( model: string, @@ -573,6 +575,7 @@ export class ApiResponseEvent implements BaseTelemetryEvent { tool_token_count: usage_data?.toolUsePromptTokenCount ?? 0, total_token_count: usage_data?.totalTokenCount ?? 0, }; + this.finish_reasons = toFinishReasons(this.response.candidates); } toLogRecord(config: Config): LogRecord { @@ -591,6 +594,7 @@ export class ApiResponseEvent implements BaseTelemetryEvent { prompt_id: this.prompt.prompt_id, auth_type: this.auth_type, status_code: this.status_code, + finish_reasons: this.finish_reasons, }; if (this.response_text) { attributes['response_text'] = this.response_text; @@ -613,9 +617,7 @@ export class ApiResponseEvent implements BaseTelemetryEvent { 'event.name': EVENT_GEN_AI_OPERATION_DETAILS, 'event.timestamp': this['event.timestamp'], 'gen_ai.response.id': this.response.response_id, - 'gen_ai.response.finish_reasons': toFinishReasons( - this.response.candidates, - ), + 'gen_ai.response.finish_reasons': this.finish_reasons, 'gen_ai.output.messages': JSON.stringify( toOutputMessages(this.response.candidates), ),