add(mcp): Add MCP Server name to ToolCallEvent OTel logging (#7829)

Co-authored-by: Shnatu <snatu@google.com>
Co-authored-by: owenofbrien <86964623+owenofbrien@users.noreply.github.com>
Co-authored-by: Abhi <43648792+abhipatel12@users.noreply.github.com>
This commit is contained in:
Shardul Natu
2025-09-18 15:00:11 -07:00
committed by GitHub
parent 22b7d86574
commit bbcc906133
4 changed files with 94 additions and 5 deletions

View File

@@ -477,6 +477,10 @@ export class ClearcutLogger {
gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_CONTENT_LENGTH,
value: JSON.stringify(event.content_length),
},
{
gemini_cli_key: EventMetadataKey.GEMINI_CLI_TOOL_CALL_MCP_SERVER_NAME,
value: JSON.stringify(event.mcp_server_name),
},
];
if (event.metadata) {

View File

@@ -50,6 +50,9 @@ export enum EventMetadataKey {
// Logs whether the session was configured to respect gitignore files.
GEMINI_CLI_START_SESSION_RESPECT_GITIGNORE = 12,
// Logs the output format of the session.
GEMINI_CLI_START_SESSION_OUTPUT_FORMAT = 94,
// ==========================================================================
// User Prompt Event Keys
// ===========================================================================
@@ -64,6 +67,9 @@ export enum EventMetadataKey {
// Logs the function name.
GEMINI_CLI_TOOL_CALL_NAME = 14,
// Logs the MCP server name.
GEMINI_CLI_TOOL_CALL_MCP_SERVER_NAME = 95,
// Logs the user's decision about how to handle the tool call.
GEMINI_CLI_TOOL_CALL_DECISION = 15,

View File

@@ -76,7 +76,11 @@ import * as metrics from './metrics.js';
import { FileOperation } from './metrics.js';
import * as sdk from './sdk.js';
import { vi, describe, beforeEach, it, expect, afterEach } from 'vitest';
import type { GenerateContentResponseUsageMetadata } from '@google/genai';
import type {
CallableTool,
GenerateContentResponseUsageMetadata,
} from '@google/genai';
import { DiscoveredMCPTool } from '../tools/mcp-tool.js';
import * as uiTelemetry from './uiTelemetry.js';
import { makeFakeConfig } from '../test-utils/config.js';
import { ClearcutLogger } from './clearcut-logger/clearcut-logger.js';
@@ -930,6 +934,75 @@ describe('loggers', () => {
'event.timestamp': '2025-01-01T00:00:00.000Z',
});
});
it('should log a tool call with mcp_server_name for MCP tools', () => {
const mockMcpTool = new DiscoveredMCPTool(
{} as CallableTool,
'mock_mcp_server',
'mock_mcp_tool',
'tool description',
{
type: 'object',
properties: {
arg1: { type: 'string' },
arg2: { type: 'number' },
},
required: ['arg1', 'arg2'],
},
);
const call: CompletedToolCall = {
status: 'success',
request: {
name: 'mock_mcp_tool',
args: { arg1: 'value1', arg2: 2 },
callId: 'test-call-id',
isClientInitiated: true,
prompt_id: 'prompt-id',
},
response: {
callId: 'test-call-id',
responseParts: [{ text: 'test-response' }],
resultDisplay: undefined,
error: undefined,
errorType: undefined,
},
tool: mockMcpTool,
invocation: {} as AnyToolInvocation,
durationMs: 100,
};
const event = new ToolCallEvent(call);
logToolCall(mockConfig, event);
expect(mockLogger.emit).toHaveBeenCalledWith({
body: 'Tool call: mock_mcp_tool. Success: true. Duration: 100ms.',
attributes: {
'session.id': 'test-session-id',
'user.email': 'test-user@example.com',
'event.name': EVENT_TOOL_CALL,
'event.timestamp': '2025-01-01T00:00:00.000Z',
function_name: 'mock_mcp_tool',
function_args: JSON.stringify(
{
arg1: 'value1',
arg2: 2,
},
null,
2,
),
duration_ms: 100,
success: true,
prompt_id: 'prompt-id',
tool_type: 'mcp',
mcp_server_name: 'mock_mcp_server',
decision: undefined,
error: undefined,
error_type: undefined,
metadata: undefined,
},
});
});
});
describe('logMalformedJsonResponse', () => {

View File

@@ -137,6 +137,7 @@ export class ToolCallEvent implements BaseTelemetryEvent {
prompt_id: string;
tool_type: 'native' | 'mcp';
content_length?: number;
mcp_server_name?: string;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
metadata?: { [key: string]: any };
@@ -153,11 +154,16 @@ export class ToolCallEvent implements BaseTelemetryEvent {
this.error = call.response.error?.message;
this.error_type = call.response.errorType;
this.prompt_id = call.request.prompt_id;
this.tool_type =
typeof call.tool !== 'undefined' && call.tool instanceof DiscoveredMCPTool
? 'mcp'
: 'native';
this.content_length = call.response.contentLength;
if (
typeof call.tool !== 'undefined' &&
call.tool instanceof DiscoveredMCPTool
) {
this.tool_type = 'mcp';
this.mcp_server_name = call.tool.serverName;
} else {
this.tool_type = 'native';
}
if (
call.status === 'success' &&