mirror of
https://github.com/Kaelio/ktx.git
synced 2026-06-16 08:25:14 +02:00
feat(telemetry): collect PostHog $exception error reports in CLI and daemon (#262)
* feat(telemetry): add node exception reporter * feat(telemetry): report node cli exceptions * feat(telemetry): add daemon exception reporter * feat(telemetry): report daemon exceptions * docs(telemetry): document error reports * fix(telemetry): pass redaction snapshots from node call sites * test(telemetry): verify prepared node exception payload * fix(telemetry): close daemon exception lifecycle gaps * test(telemetry): verify prepared daemon exception payload * test(telemetry): close error collection acceptance gaps * test(telemetry): close posthog exception acceptance gaps
This commit is contained in:
parent
c3d8cedb0b
commit
fb7b94b60e
36 changed files with 2870 additions and 140 deletions
|
|
@ -3,7 +3,13 @@ import type { ToolAnnotations } from '@modelcontextprotocol/sdk/types.js';
|
|||
import { z } from 'zod';
|
||||
import type { KtxCliIo } from '../../cli-runtime.js';
|
||||
import type { MemoryAgentInput } from '../../context/memory/types.js';
|
||||
import { emitTelemetryEvent, mcpTelemetrySampleRate, shouldEmitMcpTelemetry } from '../../telemetry/index.js';
|
||||
import {
|
||||
emitTelemetryEvent,
|
||||
mcpTelemetrySampleRate,
|
||||
reportException,
|
||||
shouldEmitMcpTelemetry,
|
||||
} from '../../telemetry/index.js';
|
||||
import { collectTelemetryRedactionSecrets } from '../../telemetry/redaction-secrets.js';
|
||||
import { scrubErrorClass } from '../../telemetry/scrubber.js';
|
||||
import type {
|
||||
KtxMcpClientInfo,
|
||||
|
|
@ -518,11 +524,26 @@ function registerParsedTool<TSchema extends z.ZodType>(
|
|||
},
|
||||
schema: TSchema,
|
||||
handler: (input: z.infer<TSchema>, context?: KtxMcpToolHandlerContext) => Promise<KtxMcpToolResult>,
|
||||
telemetry?: { projectDir?: string; io?: KtxCliIo },
|
||||
): void {
|
||||
server.registerTool(name, config, async (input, context) => {
|
||||
try {
|
||||
return await handler(schema.parse(input), context);
|
||||
} catch (error) {
|
||||
if (telemetry?.io) {
|
||||
await reportException({
|
||||
error,
|
||||
context: { source: `mcp:${name}`, handled: true, fatal: false },
|
||||
projectDir: telemetry.projectDir,
|
||||
io: telemetry.io,
|
||||
redactionSecrets: await collectTelemetryRedactionSecrets({
|
||||
projectDir: telemetry.projectDir,
|
||||
includeLlm: true,
|
||||
includeEmbeddings: true,
|
||||
env: process.env,
|
||||
}),
|
||||
});
|
||||
}
|
||||
return jsonErrorToolResult(formatToolError(error));
|
||||
}
|
||||
});
|
||||
|
|
@ -571,6 +592,20 @@ function instrumentMcpServer(
|
|||
}
|
||||
return result;
|
||||
} catch (error) {
|
||||
if (telemetry.io) {
|
||||
await reportException({
|
||||
error,
|
||||
context: { source: `mcp:${name}`, handled: true, fatal: false },
|
||||
projectDir: telemetry.projectDir,
|
||||
io: telemetry.io,
|
||||
redactionSecrets: await collectTelemetryRedactionSecrets({
|
||||
projectDir: telemetry.projectDir,
|
||||
includeLlm: true,
|
||||
includeEmbeddings: true,
|
||||
env: process.env,
|
||||
}),
|
||||
});
|
||||
}
|
||||
if (telemetry.io && telemetry.projectDir && shouldEmitMcpTelemetry()) {
|
||||
const errorClass = scrubErrorClass(error);
|
||||
await emitTelemetryEvent({
|
||||
|
|
@ -596,6 +631,7 @@ function instrumentMcpServer(
|
|||
|
||||
export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void {
|
||||
const { ports, userContext } = deps;
|
||||
const toolTelemetry = { projectDir: deps.projectDir, io: deps.io };
|
||||
const server = instrumentMcpServer(deps.server, {
|
||||
projectDir: deps.projectDir,
|
||||
io: deps.io,
|
||||
|
|
@ -616,6 +652,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
},
|
||||
connectionListSchema,
|
||||
async () => jsonToolResult({ connections: await connections.list() }),
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -640,6 +677,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
limit: input.limit,
|
||||
}),
|
||||
),
|
||||
toolTelemetry,
|
||||
);
|
||||
|
||||
registerParsedTool(
|
||||
|
|
@ -657,6 +695,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
const page = await knowledge.read({ userId: userContext.userId, key: input.key });
|
||||
return page ? jsonToolResult(page) : jsonErrorToolResult(`Wiki page "${input.key}" was not found.`);
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -679,6 +718,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
? jsonToolResult(source)
|
||||
: jsonErrorToolResult(`Semantic-layer source "${input.sourceName}" was not found.`);
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
|
||||
registerParsedTool(
|
||||
|
|
@ -711,6 +751,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
);
|
||||
return jsonToolResult(projectSlQueryResult(result, input.include));
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -728,6 +769,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
},
|
||||
entityDetailsSchema,
|
||||
async (input) => jsonToolResult(await entityDetails.read(input)),
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -745,6 +787,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
},
|
||||
dictionarySearchSchema,
|
||||
async (input) => jsonToolResult(await dictionarySearch.search(input)),
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -762,6 +805,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
},
|
||||
discoverDataSchema,
|
||||
async (input) => jsonToolResult({ refs: await discover.search(input) }),
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -791,6 +835,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
),
|
||||
);
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
|
||||
|
|
@ -818,6 +863,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
};
|
||||
return jsonToolResult(await memoryIngest.ingest(ingestInput));
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
|
||||
registerParsedTool(
|
||||
|
|
@ -835,6 +881,7 @@ export function registerKtxContextTools(deps: RegisterKtxContextToolsDeps): void
|
|||
const status = await memoryIngest.status(input.runId);
|
||||
return status ? jsonToolResult(status) : jsonErrorToolResult(`Memory ingest run "${input.runId}" was not found.`);
|
||||
},
|
||||
toolTelemetry,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue