From cb8dd13cac81e5f9a05171c2f3a5562243ca02b7 Mon Sep 17 00:00:00 2001 From: Christian Gick Date: Thu, 8 Jan 2026 14:30:38 +0200 Subject: [PATCH] build: Add telemetry compiled output Co-Authored-By: Claude Opus 4.5 --- dist/index.js | 30 ++++++++++++++++++++++++++++++ dist/telemetry.d.ts | 17 +++++++++++++++++ dist/telemetry.js | 30 ++++++++++++++++++++++++++++++ 3 files changed, 77 insertions(+) create mode 100644 dist/telemetry.d.ts create mode 100644 dist/telemetry.js diff --git a/dist/index.js b/dist/index.js index 464567c..cf57ddf 100644 --- a/dist/index.js +++ b/dist/index.js @@ -18,6 +18,7 @@ import { execSync } from "child_process"; import { compressRead } from "./compressors/read.js"; import { compressGrep } from "./compressors/grep.js"; import { compressGlob } from "./compressors/glob.js"; +import { logTelemetry, calculateCompressionRatio } from "./telemetry.js"; // Configuration from environment const COMPRESSION_LEVEL = process.env.COMPRESSION_LEVEL || "medium"; // Compression presets @@ -155,6 +156,15 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { removeComments: !args?.keepComments, }; const result = compressRead(content, path, options); + // Log telemetry + logTelemetry({ + tool: "compressed_read", + inputSize: result.originalLines, + outputSize: result.compressedLines, + compressionRatio: calculateCompressionRatio(result.originalLines, result.compressedLines), + path, + success: true, + }); return { content: [ { @@ -191,6 +201,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { maxMatchesPerFile: args?.maxMatchesPerFile || preset.grep.maxMatchesPerFile, }; const result = compressGrep(output, options); + // Log telemetry + logTelemetry({ + tool: "compressed_grep", + inputSize: result.originalMatches, + outputSize: result.compressedMatches, + compressionRatio: calculateCompressionRatio(result.originalMatches, result.compressedMatches), + path: searchPath, + pattern, + success: true, + }); return { content: [ { @@ -233,6 +253,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => { maxFiles: args?.maxFiles || preset.glob.maxFiles, }; const result = compressGlob(paths, options); + // Log telemetry + logTelemetry({ + tool: "compressed_glob", + inputSize: paths.length, + outputSize: result.compressedCount, + compressionRatio: calculateCompressionRatio(paths.length, result.compressedCount), + path: basePath, + pattern, + success: true, + }); return { content: [ { diff --git a/dist/telemetry.d.ts b/dist/telemetry.d.ts new file mode 100644 index 0000000..0000d78 --- /dev/null +++ b/dist/telemetry.d.ts @@ -0,0 +1,17 @@ +/** + * Telemetry for compressed tools usage tracking + * Logs to ~/.local/share/mcp/compressed-tools.jsonl + */ +export interface TelemetryEvent { + timestamp: string; + tool: "compressed_read" | "compressed_grep" | "compressed_glob"; + inputSize: number; + outputSize: number; + compressionRatio: number; + path?: string; + pattern?: string; + success: boolean; + error?: string; +} +export declare function logTelemetry(event: Omit): void; +export declare function calculateCompressionRatio(original: number, compressed: number): number; diff --git a/dist/telemetry.js b/dist/telemetry.js new file mode 100644 index 0000000..558857c --- /dev/null +++ b/dist/telemetry.js @@ -0,0 +1,30 @@ +/** + * Telemetry for compressed tools usage tracking + * Logs to ~/.local/share/mcp/compressed-tools.jsonl + */ +import { appendFileSync, mkdirSync, existsSync } from "fs"; +import { homedir } from "os"; +import { join } from "path"; +const LOG_DIR = join(homedir(), ".local", "share", "mcp"); +const LOG_FILE = join(LOG_DIR, "compressed-tools.jsonl"); +// Ensure log directory exists +if (!existsSync(LOG_DIR)) { + mkdirSync(LOG_DIR, { recursive: true }); +} +export function logTelemetry(event) { + const entry = { + timestamp: new Date().toISOString(), + ...event, + }; + try { + appendFileSync(LOG_FILE, JSON.stringify(entry) + "\n"); + } + catch { + // Silently fail - telemetry should never break the tool + } +} +export function calculateCompressionRatio(original, compressed) { + if (original === 0) + return 0; + return Math.round((1 - compressed / original) * 100 * 10) / 10; +}