Latency bucket tool invocation metric
Skill kjuhwa/skills-hub/skills/mcp/latency-bucket-tool-invocation-metric
Wrap every MCP tool handler in a try/finally that records `{toolName, sanitized params, success, bucketized latency}` so you get a per-tool success/duration histogram without raising cardinality.From its SKILL.md
npx -y skills add kjuhwa/skills-hub --skill latency-bucket-tool-invocation-metricAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
2.9 KB, 550 tokens by cl100k_base, as published. Nobody here has run it
Latency-Bucketed Tool Invocation Metric
When to use
- You want per-tool success/latency visibility but can't afford to emit a tag with the raw millisecond count (too high-cardinality for a log pipeline).
- You already run tool handlers through a central dispatcher so you can wrap them once.
How it works
- In the dispatcher, record
startTime = Date.now()before calling the handler and asuccess = falseflag. Setsuccess = trueright before returning the result. - In
finally, computelatency = Date.now() - startTime, bucketize to a coarse exponential scale (e.g.<10ms, 10-100ms, 100-500ms, 500-2000ms, 2000-10000ms, >10000ms→ emit as the upper bound or a named bucket), and ship to the metrics sink:{tool_name, success, latency_ms: bucketized(ms), tool_params: sanitize(params, schema)}. - Guard with
voidso failure to log never blocks the tool response:void clearcutLogger?.logToolInvocation({...}).
Example
server.registerTool(tool.name, {...}, async params => {
const guard = await toolMutex.acquire();
const startTime = Date.now();
let success = false;
try {
const result = await runHandler(tool, params);
success = true;
return result;
} catch (err) {
return {content:[{type:'text', text: err.message}], isError: true};
} finally {
void clearcutLogger?.logToolInvocation({
toolName: tool.name,
params,
schema: tool.schema,
success,
latencyMs: bucketizeLatency(Date.now() - startTime),
});
guard.dispose();
}
});
Gotchas
- Bucketize before sending, not in the analytics pipeline. Raw ms in the emitted event is what blows cardinality budgets.
successmust flip to true after the handler resolves but before response formatting — if you flip after "everything including IO" you'll miss edge cases where serialization fails.- Use
voidon the logging call so no awaited Promise failure can prevent tool results from reaching the client. - Sanitize params (lengths, counts, enums — see the param-sanitize pattern) rather than logging raw values.
{tool: 'navigate', params: {url: 'https://example.com/...'}}leaks user data. - Emit a single event per invocation. Don't emit start+end; the extra noise isn't worth the storage.
What ships with it
Read from the repository
Just SKILL.md. No reference files, no scripts.