refactor(middleware): add middleware to record metrics for request count and duration#7803
Merged
Gnanasundari24 merged 3 commits intomainfrom Apr 21, 2025
Merged
Conversation
…and request duration
Changed Files
|
SanchithHegde
commented
Apr 12, 2025
Comment on lines
-26
to
-35
| #[inline] | ||
| pub async fn time_future<F, R>(future: F) -> (R, time::Duration) | ||
| where | ||
| F: futures::Future<Output = R>, | ||
| { | ||
| let start = time::Instant::now(); | ||
| let result = future.await; | ||
| let time_spent = start.elapsed(); | ||
| (result, time_spent) | ||
| } |
Member
Author
There was a problem hiding this comment.
Deleted this in favor of the same function defined in the common_utils crate:
hyperswitch/crates/common_utils/src/metrics/utils.rs
Lines 7 to 17 in 2123f63
Comment on lines
-3
to
-12
| #[inline] | ||
| pub async fn time_future<F, R>(future: F) -> (R, time::Duration) | ||
| where | ||
| F: futures::Future<Output = R>, | ||
| { | ||
| let start = time::Instant::now(); | ||
| let result = future.await; | ||
| let time_spent = start.elapsed(); | ||
| (result, time_spent) | ||
| } |
Member
Author
There was a problem hiding this comment.
Deleted this in favor of the same function defined in the common_utils crate:
hyperswitch/crates/common_utils/src/metrics/utils.rs
Lines 7 to 17 in 2123f63
Comment on lines
-4
to
-34
| pub async fn record_request_time_metric<F, R>( | ||
| future: F, | ||
| flow: &impl router_env::types::FlowMetric, | ||
| ) -> R | ||
| where | ||
| F: futures::Future<Output = R>, | ||
| { | ||
| let key = "request_type"; | ||
| super::REQUESTS_RECEIVED.add(1, router_env::metric_attributes!((key, flow.to_string()))); | ||
| let (result, time) = metric_utils::time_future(future).await; | ||
| super::REQUEST_TIME.record( | ||
| time.as_secs_f64(), | ||
| router_env::metric_attributes!((key, flow.to_string())), | ||
| ); | ||
| result | ||
| } | ||
|
|
||
| pub fn status_code_metrics( | ||
| status_code: String, | ||
| flow: String, | ||
| merchant_id: common_utils::id_type::MerchantId, | ||
| ) { | ||
| super::REQUEST_STATUS.add( | ||
| 1, | ||
| router_env::metric_attributes!( | ||
| ("status_code", status_code), | ||
| ("flow", flow), | ||
| ("merchant_id", merchant_id.clone()), | ||
| ), | ||
| ) | ||
| } |
Member
Author
There was a problem hiding this comment.
Removed these two since these were only being called within server_wrap().
jarnura
requested changes
Apr 15, 2025
jarnura
approved these changes
Apr 16, 2025
NishantJoshi00
approved these changes
Apr 16, 2025
su-shivanshmathur
approved these changes
Apr 16, 2025
pixincreate
added a commit
that referenced
this pull request
Apr 21, 2025
…acilitapay-pix-pmt * 'main' of github.com:juspay/hyperswitch: (21 commits) refactor(required_fields): move pm required fields to pm crate (#7539) fix(connector): [noon] address `next_action_url` being `null` for cards in 3ds payment (#7832) refactor(middleware): add middleware to record metrics for request count and duration (#7803) chore(version): 2025.04.18.0 chore(postman): update Postman collection files fix(connector): [globalpay] handle edge case where currency comes as empty upon payment decline (#7812) refactor(cypress-v2): change `Authorization` and `payment_methods_enabled` for v2 cypress tests (#7805) fix(connector): [Cybersource] send type selection indicator for co-batch cards (#7828) feat(payment_method): add logic for setup_future_usage downgrade and add filter based on zero mandate config (#7775) refactor(accounts): move dashboard_metadata table to accounts_schema and point v2 to v1 dashboard_metadata (#7793) chore(analytics): opensearch client creation based on config (#7810) ci(postman): update assertion error message for nmi collection (#7765) feat: add primary key not null query to generic filter function (#7785) chore(version): 2025.04.17.0 chore: change payment method files ownership to `hyperswitch-payment-methods` (#7808) feat(vsaas): modify api key auth to support vsaas cases (#7593) ci(cypress): verify mandate id to be `null` if payment id not `succeeded` (#7749) feat(connector): [chargebee] consumes required fields to support transaction monitoring (#7774) ci(configs): remove vault private key from configs (#7825) chore(version): 2025.04.16.0 ...
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Type of Change
Description
This PR moves the metrics that record incoming request count, status code and duration to the middleware, so that all requests that the server receives would be accounted for. As part of this change, the following two metrics are recorded as part of the middleware rather than within
server_wrap():REQUESTS_RECEIVED: Records the number of requests that the server received. Has request path and HTTP method as attributes.REQUEST_TIME: Records the time it took to respond to the request. Also helps us obtain a count of the number of requests to which the server responded successfully. Has request path, HTTP method and HTTP status code as attributes.Additionally, this PR removes the
REQUEST_STATUSmetric, since it becomes redundant with theREQUEST_TIMEmetric helping us obtain a count of requests that the server responded to, along with tracking the status code. This PR also removes some duplicate code from a couple of places.Motivation and Context
This change is being as part of a bigger change to improve the metrics emitted by the application. This change would help account for all the requests that the server received, record the complete time taken by the server when responding to requests, and possibly help with monitoring the server better.
How did you test it?
Locally, by running the OpenTelemetry Collector, Prometheus and Grafana with our Docker Compose setup.
Using
REQUESTS_RECEIVEDto count the number of requests received by the server:The graph can be obtained by running a query like:
Notice that the metric has
methodandpathas attributes.Using
REQUEST_TIMEto count the number of requests that the server responded to:The graph can be obtained by running a query like:
Notice that the metric has
method,pathandstatus_codeas attributes. We are able to useREQUEST_TIMEto count requests (even though it is a histogram metric) becauseREQUEST_TIME_countis automatically generated which functions like a counter.Ideally, the number recorded by
REQUESTS_RECEIVEDandREQUEST_TIMEshould be the same but in case of application restarts mid-request, the number recorded byREQUEST_TIMEmay be slightly lesser.Using
REQUEST_TIMEto record the request duration:The 99th, 90th and 50th percentile values can be plotted:
The graph can be obtained by running a query like:
This would provide us the 99th percentile values. The 90th and 50th percentile values can be obtained by replacing
0.99in the above query with0.9and0.5, respectively.The same data can be plotted as a heatmap:
The heatmap can be obtained by running a query like:
Checklist
cargo +nightly fmt --allcargo clippy