agentsclimarketplace

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

Install
npx -y skills add kjuhwa/skills-hub --skill latency-bucket-tool-invocation-metric

Assembled 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 a success = false flag. Set success = true right before returning the result.
  • In finally, compute latency = 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 void so 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.
  • success must 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 void on 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.

Keep looking

Skills are one crate of 326,852. Ordering is by how many stacks a row turns up in, so the top of any crate is what has actually been picked rather than what has the most stars.