mirror of
https://github.com/google-gemini/gemini-cli.git
synced 2026-03-10 14:10:37 -07:00
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:
@@ -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) {
|
||||
|
||||
@@ -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,
|
||||
|
||||
|
||||
@@ -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', () => {
|
||||
|
||||
@@ -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' &&
|
||||
|
||||
Reference in New Issue
Block a user