Skip to content

feat: track json-rpc metrics - #25159

Open
alexghr wants to merge 1 commit into
merge-train/spartanfrom
stack/feat-track-json-rpc-metrics
Open

feat: track json-rpc metrics#25159
alexghr wants to merge 1 commit into
merge-train/spartanfrom
stack/feat-track-json-rpc-metrics

Conversation

@alexghr

@alexghr alexghr commented Aug 10, 2026

Copy link
Copy Markdown
Contributor

Add metrics to the JSON-RPC server.

Fix A-1677.

@alexghr
alexghr enabled auto-merge August 10, 2026 15:48
@alexghr
alexghr force-pushed the stack/feat-track-json-rpc-metrics branch 2 times, most recently from 3580550 to 60b2228 Compare August 10, 2026 16:54
@alexghr
alexghr force-pushed the stack/feat-track-json-rpc-metrics branch from 60b2228 to 10007f1 Compare August 12, 2026 13:46
);
if (apiKeyResolution) {
adminMiddlewares.unshift(getApiKeyAuthMiddleware(apiKeyResolution.apiKeyHash));
adminMiddlewares.splice(1, 0, getApiKeyAuthMiddleware(apiKeyResolution.apiKeyHash));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this because we want the api key auth to run after metrics? If so, let's add it in order in the adminMiddlewares above, this splice(1) seems not very robust. I'm thinking something like:

    const adminMiddlewares = [
      getOtelJsonRpcServerMetricsMiddleware(),
      ...(apiKeyResolution ? [getApiKeyAuthMiddleware()] : []),
      getOtelJsonRpcPropagationMiddleware(),
      getVersioningMiddleware(versions, versioningOpts),
    ];

Comment on lines +49 to +50
...(service === undefined ? {} : { [ATTR_JSONRPC_SERVICE]: service }),
[ATTR_JSONRPC_METHOD]: method,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be a problem in terms of attribute cardinality if we log every request done, even when the service/method doesn't exist? Eg if I start poking an RPC endpoint with aztec_1, aztec_2, etc, can I screw up prometheus?

const method = this.handler[methodName as keyof T];
assert(typeof method === 'function', `Method ${methodName} is not a function`);
const args = await parseWithOptionals(jsonParams, getSchemaParameters(this.schema[methodName]));
const validationTimer = new Timer();

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we set validationSucceeded to false in these branches? Or do we have something else that collects exceptions and flags the request as failed?

@spalladino spalladino left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude also flagged the following, meat-proxying:

Two rejection reasons are unreachable, and real internal errors never appear in the metric — telemetry-client/src/json_rpc_server_metrics.ts:119-146. Handler-thrown errors (including BadRequestError) are caught inside processRequest and mapped to -32701/-32702, which getRejectionReasons ignores. The -32000 and -32600 + status 500 branches only fire for errors thrown outside processRequest, which nothing currently does. So an operator alerting on rejection_reason=internal_error never trips it even while every handler is throwing. Conversely, an uncaught rejection inside a batch item comes out -32600 / HTTP 200 and gets mislabeled invalid_request. Either drop the dead reasons or classify from the codes the server actually emits.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants