From 714421c2da4f5d6b9c1c7060fdf5c47ba1c965ca Mon Sep 17 00:00:00 2001 From: Jerop Kipruto Date: Sun, 15 Jun 2025 16:24:53 -0400 Subject: Add file operation telemetry (#1068) Introduces telemetry for file create, read, and update operations. This change adds the `gemini_cli.file.operation.count` metric, recorded by the `read-file`, `read-many-files`, and `write-file` tools. The metric includes the following attributes: - `operation` (string: `create`, `read`, `update`): The type of file operation. - `lines` (optional, Int): Number of lines in the file. - `mimetype` (optional, string): Mimetype of the file. - `extension` (optional, string): File extension of the file. Here is a stacked bar chart of file operations by extension (`js`, `ts`, `md`): ![image](https://github.com/user-attachments/assets/3e8f8ea9-6155-4186-863c-075cc47647c5) Here is a stacked bar chart of file operations by type (`create`, `read`, `update`): ![image](https://github.com/user-attachments/assets/3fcf491d-31d0-4ba8-80e6-7fd2bd9c7c27) #750 cc @allenhutchison as discussed --- packages/core/src/tools/read-file.ts | 18 ++++++++++++++++++ packages/core/src/tools/read-many-files.ts | 17 +++++++++++++++++ packages/core/src/tools/write-file.ts | 26 ++++++++++++++++++++++++++ 3 files changed, 61 insertions(+) (limited to 'packages/core/src/tools') diff --git a/packages/core/src/tools/read-file.ts b/packages/core/src/tools/read-file.ts index 586a7123..5cf49209 100644 --- a/packages/core/src/tools/read-file.ts +++ b/packages/core/src/tools/read-file.ts @@ -10,6 +10,11 @@ import { makeRelative, shortenPath } from '../utils/paths.js'; import { BaseTool, ToolResult } from './tools.js'; import { isWithinRoot, processSingleFileContent } from '../utils/fileUtils.js'; import { Config } from '../config/config.js'; +import { getSpecificMimeType } from '../utils/fileUtils.js'; +import { + recordFileOperationMetric, + FileOperation, +} from '../telemetry/metrics.js'; /** * Parameters for the ReadFile tool @@ -145,6 +150,19 @@ export class ReadFileTool extends BaseTool { }; } + const lines = + typeof result.llmContent === 'string' + ? result.llmContent.split('\n').length + : undefined; + const mimetype = getSpecificMimeType(params.absolute_path); + recordFileOperationMetric( + this.config, + FileOperation.READ, + lines, + mimetype, + path.extname(params.absolute_path), + ); + return { llmContent: result.llmContent, returnDisplay: result.returnDisplay, diff --git a/packages/core/src/tools/read-many-files.ts b/packages/core/src/tools/read-many-files.ts index 107e16b3..62430c10 100644 --- a/packages/core/src/tools/read-many-files.ts +++ b/packages/core/src/tools/read-many-files.ts @@ -14,9 +14,14 @@ import { detectFileType, processSingleFileContent, DEFAULT_ENCODING, + getSpecificMimeType, } from '../utils/fileUtils.js'; import { PartListUnion } from '@google/genai'; import { Config } from '../config/config.js'; +import { + recordFileOperationMetric, + FileOperation, +} from '../telemetry/metrics.js'; /** * Parameters for the ReadManyFilesTool. @@ -420,6 +425,18 @@ Use this tool when the user's query implies needing the content of several files contentParts.push(fileReadResult.llmContent); // This is a Part for image/pdf } processedFilesRelativePaths.push(relativePathForDisplay); + const lines = + typeof fileReadResult.llmContent === 'string' + ? fileReadResult.llmContent.split('\n').length + : undefined; + const mimetype = getSpecificMimeType(filePath); + recordFileOperationMetric( + this.config, + FileOperation.READ, + lines, + mimetype, + path.extname(filePath), + ); } } diff --git a/packages/core/src/tools/write-file.ts b/packages/core/src/tools/write-file.ts index b9e07034..b19b00ac 100644 --- a/packages/core/src/tools/write-file.ts +++ b/packages/core/src/tools/write-file.ts @@ -26,6 +26,11 @@ import { import { GeminiClient } from '../core/client.js'; import { DEFAULT_DIFF_OPTIONS } from './diffOptions.js'; import { ModifiableTool, ModifyContext } from './modifiable-tool.js'; +import { getSpecificMimeType } from '../utils/fileUtils.js'; +import { + recordFileOperationMetric, + FileOperation, +} from '../telemetry/metrics.js'; /** * Parameters for the WriteFile tool @@ -271,6 +276,27 @@ export class WriteFileTool const displayResult: FileDiff = { fileDiff, fileName }; + const lines = fileContent.split('\n').length; + const mimetype = getSpecificMimeType(params.file_path); + const extension = path.extname(params.file_path); // Get extension + if (isNewFile) { + recordFileOperationMetric( + this.config, + FileOperation.CREATE, + lines, + mimetype, + extension, + ); + } else { + recordFileOperationMetric( + this.config, + FileOperation.UPDATE, + lines, + mimetype, + extension, + ); + } + return { llmContent: llmSuccessMessage, returnDisplay: displayResult, -- cgit v1.2.3