feat: Add telemetry logging to compressed tools

Logs to ~/.local/share/mcp/compressed-tools.jsonl:
- Tool name (compressed_read/grep/glob)
- Input/output sizes
- Compression ratio
- Path and pattern
- Success status

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Christian Gick
2026-01-08 14:13:06 +02:00
parent fdbd3e5723
commit 20e6ea0a47
2 changed files with 79 additions and 0 deletions

View File

@@ -22,6 +22,7 @@ import { execSync } from "child_process";
import { compressRead } from "./compressors/read.js"; import { compressRead } from "./compressors/read.js";
import { compressGrep } from "./compressors/grep.js"; import { compressGrep } from "./compressors/grep.js";
import { compressGlob } from "./compressors/glob.js"; import { compressGlob } from "./compressors/glob.js";
import { logTelemetry, calculateCompressionRatio } from "./telemetry.js";
// Configuration from environment // Configuration from environment
const COMPRESSION_LEVEL = process.env.COMPRESSION_LEVEL || "medium"; const COMPRESSION_LEVEL = process.env.COMPRESSION_LEVEL || "medium";
@@ -177,6 +178,16 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const result = compressRead(content, path, options); 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 { return {
content: [ content: [
{ {
@@ -219,6 +230,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const result = compressGrep(output, options); 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 { return {
content: [ content: [
{ {
@@ -266,6 +288,17 @@ server.setRequestHandler(CallToolRequestSchema, async (request) => {
const result = compressGlob(paths, options); 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 { return {
content: [ content: [
{ {

46
src/telemetry.ts Normal file
View File

@@ -0,0 +1,46 @@
/**
* 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 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 function logTelemetry(event: Omit<TelemetryEvent, "timestamp">): void {
const entry: TelemetryEvent = {
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: number, compressed: number): number {
if (original === 0) return 0;
return Math.round((1 - compressed / original) * 100 * 10) / 10;
}