Skip to content

Commit e263b34

Browse files
committed
feat: metric for method not found
1 parent 6425abd commit e263b34

File tree

5 files changed

+57
-17
lines changed

5 files changed

+57
-17
lines changed

src/metrics.rs

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,11 @@ pub(crate) const ROUTER_PARSE_ERRORS: &str = "ajj.router.parse_errors";
3333
pub(crate) const ROUTER_PARSE_ERRORS_HELP: &str =
3434
"Number of parse errors encountered by ajj router methods. This implies no response was sent.";
3535

36+
/// Metric for counting method not found errors.
37+
pub(crate) const ROUTER_METHOD_NOT_FOUND: &str = "ajj.router.method_not_found";
38+
pub(crate) const ROUTER_METHOD_NOT_FOUND_HELP: &str =
39+
"Number of times ajj router methods encountered a method not found error. This implies a response was sent.";
40+
3641
static DESCRIBE: LazyLock<()> = LazyLock::new(|| {
3742
metrics::describe_counter!(ROUTER_CALLS, metrics::Unit::Count, ROUTER_CALLS_HELP);
3843
metrics::describe_counter!(ROUTER_ERRORS, metrics::Unit::Count, ROUTER_ERRORS_HELP);
@@ -56,6 +61,11 @@ static DESCRIBE: LazyLock<()> = LazyLock::new(|| {
5661
metrics::Unit::Count,
5762
ROUTER_PARSE_ERRORS_HELP
5863
);
64+
metrics::describe_counter!(
65+
ROUTER_METHOD_NOT_FOUND,
66+
metrics::Unit::Count,
67+
ROUTER_METHOD_NOT_FOUND_HELP
68+
);
5969
});
6070

6171
/// Get or register a counter for calls to a specific service and method.
@@ -168,3 +178,20 @@ pub(crate) fn record_parse_error(service_name: &'static str) {
168178
let counter = parse_errors(service_name);
169179
counter.increment(1);
170180
}
181+
182+
/// Get or register a counter for method not found errors.
183+
pub(crate) fn method_not_found_errors(service_name: &'static str, method: &str) -> Counter {
184+
let _ = &DESCRIBE;
185+
metrics::counter!(ROUTER_METHOD_NOT_FOUND, "service" => service_name.to_string(), "method" => method.to_string())
186+
}
187+
188+
/// Record a method not found error.
189+
pub(crate) fn record_method_not_found(
190+
response_sent: bool,
191+
service_name: &'static str,
192+
method: &str,
193+
) {
194+
let counter = method_not_found_errors(service_name, method);
195+
counter.increment(1);
196+
record_output(response_sent, service_name, method);
197+
}

src/routes/ctx.rs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -464,8 +464,18 @@ impl HandlerArgs {
464464
self.req.id_owned()
465465
}
466466

467+
/// Get the method of the JSON-RPC request.
468+
pub fn method(&self) -> &str {
469+
self.req.method()
470+
}
471+
467472
/// Get the OpenTelemetry span name for this handler invocation.
468473
pub fn otel_span_name(&self) -> String {
469474
format!("{}/{}", self.ctx.service_name(), self.req.method())
470475
}
476+
477+
/// Get the service name for this handler invocation.
478+
pub const fn service_name(&self) -> &'static str {
479+
self.ctx.service_name()
480+
}
471481
}

src/routes/handler.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ pub struct OutputResponsePayload {
440440
_sealed: (),
441441
}
442442

443-
/// Takes nothing, returns ResponsePayload
443+
// Takes nothing, returns ResponsePayload
444444
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload,), S> for F
445445
where
446446
F: FnOnce() -> Fut + Clone + Send + Sync + 'static,
@@ -455,7 +455,7 @@ where
455455
}
456456
}
457457

458-
/// Takes Ctx, returns ResponsePayload
458+
// Takes Ctx, returns ResponsePayload
459459
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx), S> for F
460460
where
461461
F: FnOnce(HandlerCtx) -> Fut + Clone + Send + Sync + 'static,
@@ -470,7 +470,7 @@ where
470470
}
471471
}
472472

473-
/// Takes Params, returns ResponsePayload
473+
// Takes Params, returns ResponsePayload
474474
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, PhantomParams<Input>), S>
475475
for F
476476
where
@@ -487,7 +487,7 @@ where
487487
}
488488
}
489489

490-
/// Takes Params<Params>, returns ResponsePayload
490+
// Takes Params<Params>, returns ResponsePayload
491491
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, Params<Input>), S> for F
492492
where
493493
F: FnOnce(Params<Input>) -> Fut + Clone + Send + Sync + 'static,
@@ -503,7 +503,7 @@ where
503503
}
504504
}
505505

506-
/// Takes State, returns ResponsePayload
506+
// Takes State, returns ResponsePayload
507507
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, PhantomState<S>), S> for F
508508
where
509509
F: FnOnce(S) -> Fut + Clone + Send + Sync + 'static,
@@ -519,7 +519,7 @@ where
519519
}
520520
}
521521

522-
/// Takes State<State>, returns ResponsePayload
522+
// Takes State<State>, returns ResponsePayload
523523
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, State<S>), S> for F
524524
where
525525
F: FnOnce(State<S>) -> Fut + Clone + Send + Sync + 'static,
@@ -535,7 +535,7 @@ where
535535
}
536536
}
537537

538-
/// Takes Ctx, Params, returns ResponsePayload
538+
// Takes Ctx, Params, returns ResponsePayload
539539
impl<F, Fut, Input, Payload, ErrData, S>
540540
Handler<(OutputResponsePayload, HandlerCtx, PhantomParams<Input>), S> for F
541541
where
@@ -552,7 +552,7 @@ where
552552
}
553553
}
554554

555-
/// Takes Ctx, Params<Params>, returns ResponsePayload
555+
// Takes Ctx, Params<Params>, returns ResponsePayload
556556
impl<F, Fut, Input, Payload, ErrData, S>
557557
Handler<(OutputResponsePayload, HandlerCtx, Params<Input>), S> for F
558558
where
@@ -569,7 +569,7 @@ where
569569
}
570570
}
571571

572-
/// Takes Params, State, returns ResponsePayload
572+
// Takes Params, State, returns ResponsePayload
573573
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, Input, S), S> for F
574574
where
575575
F: FnOnce(Input, S) -> Fut + Clone + Send + Sync + 'static,
@@ -586,7 +586,7 @@ where
586586
}
587587
}
588588

589-
/// Takes Ctx, State, returns ResponsePayload
589+
// Takes Ctx, State, returns ResponsePayload
590590
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, PhantomState<S>), S>
591591
for F
592592
where
@@ -603,7 +603,7 @@ where
603603
}
604604
}
605605

606-
/// Takes Ctx, State<State>, returns ResponsePayload
606+
// Takes Ctx, State<State>, returns ResponsePayload
607607
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, State<S>), S> for F
608608
where
609609
F: FnOnce(HandlerCtx, State<S>) -> Fut + Clone + Send + Sync + 'static,
@@ -619,7 +619,7 @@ where
619619
}
620620
}
621621

622-
/// Takes Ctx, Params, State, returns ResponsePayload
622+
// Takes Ctx, Params, State, returns ResponsePayload
623623
impl<F, Fut, Input, Payload, ErrData, S> Handler<(OutputResponsePayload, HandlerCtx, Input, S), S>
624624
for F
625625
where
@@ -637,7 +637,7 @@ where
637637
}
638638
}
639639

640-
/// Takes nothing, returns Result
640+
// Takes nothing, returns Result
641641
impl<F, Fut, Payload, ErrData, S> Handler<(OutputResult,), S> for F
642642
where
643643
F: FnOnce() -> Fut + Clone + Send + Sync + 'static,

src/routes/mod.rs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,8 +52,12 @@ impl Route {
5252
pub(crate) fn default_fallback() -> Self {
5353
Self::new(tower::service_fn(|args: HandlerArgs| async {
5454
let id = args.id_owned();
55+
crate::metrics::record_method_not_found(
56+
id.is_some(),
57+
args.service_name(),
58+
args.method(),
59+
);
5560
drop(args); // no longer needed
56-
5761
Ok(Response::maybe_method_not_found(id.as_deref()))
5862
}))
5963
}

src/types/resp/payload.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ const INTERNAL_ERROR: Cow<'_, str> = Cow::Borrowed("Internal error");
88

99
/// A JSON-RPC 2.0 response payload.
1010
///
11-
/// This enum covers both the success and error cases of a JSON-RPC 2.0
12-
/// response. It is used to represent the `result` and `error` fields of a
13-
/// response object.
11+
/// This is a thin wrapper around a [`Result`] type containing either
12+
/// the successful payload or an error payload.
1413
#[derive(Clone, Debug, PartialEq, Eq)]
1514
#[repr(transparent)]
1615
pub struct ResponsePayload<Payload, ErrData>(pub Result<Payload, ErrorPayload<ErrData>>);

0 commit comments

Comments
 (0)