mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-27 19:46:48 +08:00
feat(router): adding metrics for tracking behavior throughout the router crate (#768)
This commit is contained in:
@ -10,6 +10,7 @@ use crate::{
|
||||
consts,
|
||||
core::errors::{self, RouterResponse, StorageErrorExt},
|
||||
db::StorageInterface,
|
||||
routes::metrics,
|
||||
services::ApplicationResponse,
|
||||
types::{api, storage, transformers::ForeignInto},
|
||||
utils,
|
||||
@ -147,6 +148,8 @@ pub async fn create_api_key(
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed to insert new API key")?;
|
||||
|
||||
metrics::API_KEY_CREATED.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
Ok(ApplicationResponse::Json(
|
||||
(api_key, plaintext_api_key).foreign_into(),
|
||||
))
|
||||
@ -191,6 +194,8 @@ pub async fn revoke_api_key(
|
||||
.await
|
||||
.map_err(|err| err.to_not_found_response(errors::ApiErrorResponse::ApiKeyNotFound))?;
|
||||
|
||||
metrics::API_KEY_REVOKED.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
Ok(ApplicationResponse::Json(api::RevokeApiKeyResponse {
|
||||
key_id: key_id.to_owned(),
|
||||
revoked,
|
||||
|
||||
@ -10,7 +10,7 @@ use crate::{
|
||||
},
|
||||
db::StorageInterface,
|
||||
pii::PeekInterface,
|
||||
routes::AppState,
|
||||
routes::{metrics, AppState},
|
||||
services,
|
||||
types::{
|
||||
api::customers::{self, CustomerRequestExt},
|
||||
@ -222,6 +222,7 @@ pub async fn delete_customer(
|
||||
address_deleted: true,
|
||||
payment_methods_deleted: true,
|
||||
};
|
||||
metrics::CUSTOMER_REDACTED.add(&metrics::CONTEXT, 1, &[]);
|
||||
Ok(services::ApplicationResponse::Json(response))
|
||||
}
|
||||
|
||||
|
||||
@ -6,7 +6,7 @@ use super::payments::helpers;
|
||||
use crate::{
|
||||
core::errors::{self, RouterResponse, StorageErrorExt},
|
||||
db::StorageInterface,
|
||||
routes::AppState,
|
||||
routes::{metrics, AppState},
|
||||
services,
|
||||
types::{
|
||||
self,
|
||||
@ -135,7 +135,14 @@ where
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::MandateNotFound),
|
||||
}?;
|
||||
|
||||
metrics::SUBSEQUENT_MANDATE_PAYMENT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
mandate.connector,
|
||||
)],
|
||||
);
|
||||
resp.payment_method_id = Some(mandate.payment_method_id);
|
||||
}
|
||||
None => {
|
||||
@ -167,6 +174,7 @@ where
|
||||
payment_method_id,
|
||||
mandate_reference,
|
||||
) {
|
||||
let connector = new_mandate_data.connector.clone();
|
||||
logger::debug!("{:?}", new_mandate_data);
|
||||
resp.request
|
||||
.set_mandate_id(api_models::payments::MandateIds {
|
||||
@ -182,6 +190,11 @@ where
|
||||
errors::ApiErrorResponse::DuplicateRefundRequest,
|
||||
)
|
||||
})?;
|
||||
metrics::MANDATE_COUNT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes("connector", connector)],
|
||||
);
|
||||
};
|
||||
} else if resp.request.get_setup_future_usage().is_some() {
|
||||
helpers::call_payment_method(
|
||||
|
||||
@ -19,7 +19,7 @@ use error_stack::{report, ResultExt};
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::scheduler::metrics;
|
||||
use crate::scheduler::metrics as scheduler_metrics;
|
||||
use crate::{
|
||||
configs::settings,
|
||||
core::{
|
||||
@ -29,7 +29,8 @@ use crate::{
|
||||
},
|
||||
db, logger,
|
||||
pii::prelude::*,
|
||||
routes, services,
|
||||
routes::{self, metrics},
|
||||
services,
|
||||
types::{
|
||||
api::{self, PaymentMethodCreateExt},
|
||||
storage::{self, enums},
|
||||
@ -159,14 +160,25 @@ pub async fn add_card_to_locker(
|
||||
customer_id: String,
|
||||
merchant_account: &storage::MerchantAccount,
|
||||
) -> errors::CustomResult<api::PaymentMethodResponse, errors::VaultError> {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
add_card_hs(state, req, card, customer_id, merchant_account).await
|
||||
}
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
add_card(state, req, card, customer_id, merchant_account).await
|
||||
}
|
||||
}
|
||||
metrics::STORED_TO_LOCKER.add(&metrics::CONTEXT, 1, &[]);
|
||||
metrics::request::record_card_operation_time(
|
||||
async {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
add_card_hs(state, req, card, customer_id, merchant_account).await
|
||||
}
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
add_card(state, req, card, customer_id, merchant_account).await
|
||||
}
|
||||
}
|
||||
.map_err(|error| {
|
||||
metrics::CARD_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
error
|
||||
})
|
||||
},
|
||||
&metrics::CARD_ADD_TIME,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn get_card_from_locker(
|
||||
@ -176,22 +188,34 @@ pub async fn get_card_from_locker(
|
||||
card_reference: &str,
|
||||
locker_id: Option<String>,
|
||||
) -> errors::RouterResult<payment_methods::Card> {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
get_card_from_legacy_locker(
|
||||
state,
|
||||
&locker_id.get_required_value("locker_id")?,
|
||||
card_reference,
|
||||
)
|
||||
.await
|
||||
}
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
get_card_from_hs_locker(state, customer_id, merchant_id, card_reference)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while getting card from basilisk_hs")
|
||||
}
|
||||
}
|
||||
metrics::GET_FROM_LOCKER.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
metrics::request::record_card_operation_time(
|
||||
async {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
get_card_from_legacy_locker(
|
||||
state,
|
||||
&locker_id.get_required_value("locker_id")?,
|
||||
card_reference,
|
||||
)
|
||||
.await
|
||||
}
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
get_card_from_hs_locker(state, customer_id, merchant_id, card_reference)
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Failed while getting card from basilisk_hs")
|
||||
}
|
||||
}
|
||||
.map_err(|error| {
|
||||
metrics::CARD_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
error
|
||||
})
|
||||
},
|
||||
&metrics::CARD_GET_TIME,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn delete_card_from_locker(
|
||||
@ -200,14 +224,27 @@ pub async fn delete_card_from_locker(
|
||||
merchant_id: &str,
|
||||
card_reference: &str,
|
||||
) -> errors::RouterResult<payment_methods::DeleteCardResp> {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
delete_card(state, merchant_id, card_reference).await
|
||||
}
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
delete_card_from_hs_locker(state, customer_id, merchant_id, card_reference).await
|
||||
}
|
||||
}
|
||||
metrics::DELETE_FROM_LOCKER.add(&metrics::CONTEXT, 1, &[]);
|
||||
|
||||
metrics::request::record_card_operation_time(
|
||||
async {
|
||||
match state.conf.locker.locker_setup {
|
||||
settings::LockerSetup::LegacyLocker => {
|
||||
delete_card(state, merchant_id, card_reference).await
|
||||
}
|
||||
settings::LockerSetup::BasiliskLocker => {
|
||||
delete_card_from_hs_locker(state, customer_id, merchant_id, card_reference)
|
||||
.await
|
||||
}
|
||||
}
|
||||
.map_err(|error| {
|
||||
metrics::CARD_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
error
|
||||
})
|
||||
},
|
||||
&metrics::CARD_DELETE_TIME,
|
||||
)
|
||||
.await
|
||||
}
|
||||
|
||||
#[instrument(skip_all)]
|
||||
@ -1659,7 +1696,7 @@ impl BasiliskCardSupport {
|
||||
enums::PaymentMethod::Card,
|
||||
)
|
||||
.await?;
|
||||
metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
scheduler_metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
Ok(card)
|
||||
}
|
||||
}
|
||||
|
||||
@ -5,6 +5,8 @@ use josekit::jwe;
|
||||
use masking::PeekInterface;
|
||||
use router_env::{instrument, tracing};
|
||||
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::routes::metrics;
|
||||
use crate::{
|
||||
configs::settings,
|
||||
core::errors::{self, CustomResult, RouterResult},
|
||||
@ -24,7 +26,7 @@ use crate::{
|
||||
#[cfg(feature = "basilisk")]
|
||||
use crate::{
|
||||
db,
|
||||
scheduler::{metrics, process_data, utils as process_tracker_utils},
|
||||
scheduler::{metrics as scheduler_metrics, process_data, utils as process_tracker_utils},
|
||||
types::storage::ProcessTrackerExt,
|
||||
};
|
||||
#[cfg(feature = "basilisk")]
|
||||
@ -367,7 +369,7 @@ impl Vault {
|
||||
|
||||
let lookup_key = create_tokenize(state, value1, Some(value2), lookup_key).await?;
|
||||
add_delete_tokenized_data_task(&*state.store, &lookup_key, pm).await?;
|
||||
metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
scheduler_metrics::TOKENIZED_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
Ok(lookup_key)
|
||||
}
|
||||
|
||||
@ -437,6 +439,7 @@ pub async fn create_tokenize(
|
||||
value2: Option<String>,
|
||||
lookup_key: String,
|
||||
) -> RouterResult<String> {
|
||||
metrics::CREATED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
let payload_to_be_encrypted = api::TokenizePayloadRequest {
|
||||
value1,
|
||||
value2: value2.unwrap_or_default(),
|
||||
@ -499,9 +502,12 @@ pub async fn create_tokenize(
|
||||
)?;
|
||||
Ok(get_response.lookup_key)
|
||||
}
|
||||
Err(err) => Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}")),
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -511,6 +517,7 @@ pub async fn get_tokenized_data(
|
||||
lookup_key: &str,
|
||||
should_get_value2: bool,
|
||||
) -> RouterResult<api::TokenizePayloadRequest> {
|
||||
metrics::GET_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
let payload_to_be_encrypted = api::GetTokenizePayloadRequest {
|
||||
lookup_key: lookup_key.to_string(),
|
||||
get_value2: should_get_value2,
|
||||
@ -566,9 +573,12 @@ pub async fn get_tokenized_data(
|
||||
.attach_printable("Error getting TokenizePayloadRequest from tokenize response")?;
|
||||
Ok(get_response)
|
||||
}
|
||||
Err(err) => Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}")),
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -577,6 +587,7 @@ pub async fn delete_tokenized_data(
|
||||
state: &routes::AppState,
|
||||
lookup_key: &str,
|
||||
) -> RouterResult<String> {
|
||||
metrics::DELETED_TOKENIZED_CARD.add(&metrics::CONTEXT, 1, &[]);
|
||||
let payload_to_be_encrypted = api::DeleteTokenizeByTokenRequest {
|
||||
lookup_key: lookup_key.to_string(),
|
||||
service_name: VAULT_SERVICE_NAME.to_string(),
|
||||
@ -635,9 +646,12 @@ pub async fn delete_tokenized_data(
|
||||
)?;
|
||||
Ok(delete_response)
|
||||
}
|
||||
Err(err) => Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}")),
|
||||
Err(err) => {
|
||||
metrics::TEMP_LOCKER_FAILURES.add(&metrics::CONTEXT, 1, &[]);
|
||||
Err(errors::ApiErrorResponse::InternalServerError)
|
||||
.into_report()
|
||||
.attach_printable(format!("Got 4xx from the basilisk locker: {err:?}"))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -721,14 +735,14 @@ pub async fn start_tokenize_data_workflow(
|
||||
logger::error!("Error: Deleting Card From Locker : {}", resp);
|
||||
retry_delete_tokenize(db, &delete_tokenize_data.pm, tokenize_tracker.to_owned())
|
||||
.await?;
|
||||
metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
scheduler_metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
logger::error!("Err: Deleting Card From Locker : {}", err);
|
||||
retry_delete_tokenize(db, &delete_tokenize_data.pm, tokenize_tracker.to_owned())
|
||||
.await?;
|
||||
metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
scheduler_metrics::RETRIED_DELETE_DATA_COUNT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
||||
@ -8,7 +8,7 @@ use crate::{
|
||||
errors::{self, RouterResult},
|
||||
payments,
|
||||
},
|
||||
routes::AppState,
|
||||
routes::{metrics, AppState},
|
||||
services,
|
||||
types::{self, api as api_types, storage, transformers::ForeignInto},
|
||||
};
|
||||
@ -180,6 +180,13 @@ pub async fn refresh_connector_auth(
|
||||
.await
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not refresh access token")?;
|
||||
|
||||
metrics::ACCESS_TOKEN_CREATION.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.connector_name.to_string(),
|
||||
)],
|
||||
);
|
||||
Ok(access_token_router_data.response)
|
||||
}
|
||||
|
||||
@ -7,8 +7,7 @@ use crate::{
|
||||
mandate,
|
||||
payments::{self, access_token, transformers, PaymentData},
|
||||
},
|
||||
routes::AppState,
|
||||
scheduler::metrics,
|
||||
routes::{metrics, AppState},
|
||||
services,
|
||||
types::{self, api, storage},
|
||||
};
|
||||
|
||||
@ -6,7 +6,7 @@ use crate::{
|
||||
errors::{ConnectorErrorExt, RouterResult},
|
||||
payments::{self, access_token, transformers, PaymentData},
|
||||
},
|
||||
routes::AppState,
|
||||
routes::{metrics, AppState},
|
||||
services,
|
||||
types::{self, api, storage},
|
||||
};
|
||||
@ -43,6 +43,14 @@ impl Feature<api::Void, types::PaymentsCancelData>
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<Self> {
|
||||
metrics::PAYMENT_CANCEL_COUNT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.connector_name.to_string(),
|
||||
)],
|
||||
);
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
|
||||
@ -8,7 +8,8 @@ use crate::{
|
||||
errors::{self, ConnectorErrorExt, RouterResult},
|
||||
payments::{self, access_token, transformers, PaymentData},
|
||||
},
|
||||
routes, services,
|
||||
routes::{self, metrics},
|
||||
services,
|
||||
types::{self, api, storage},
|
||||
utils::OptionExt,
|
||||
};
|
||||
@ -44,6 +45,14 @@ impl Feature<api::Session, types::PaymentsSessionData> for types::PaymentsSessio
|
||||
call_connector_action: payments::CallConnectorAction,
|
||||
_merchant_account: &storage::MerchantAccount,
|
||||
) -> RouterResult<Self> {
|
||||
metrics::SESSION_TOKEN_CREATED.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.connector_name.to_string(),
|
||||
)],
|
||||
);
|
||||
self.decide_flow(
|
||||
state,
|
||||
connector,
|
||||
|
||||
@ -20,8 +20,8 @@ use crate::{
|
||||
payment_methods::{cards, vault},
|
||||
},
|
||||
db::StorageInterface,
|
||||
routes::AppState,
|
||||
scheduler::{metrics, workflows::payment_sync},
|
||||
routes::{metrics, AppState},
|
||||
scheduler::{metrics as scheduler_metrics, workflows::payment_sync},
|
||||
services,
|
||||
types::{
|
||||
api::{self, enums as api_enums, CustomerAcceptanceExt, MandateValidationFieldsExt},
|
||||
@ -483,7 +483,7 @@ where
|
||||
|
||||
match schedule_time {
|
||||
Some(stime) => {
|
||||
metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
||||
scheduler_metrics::TASKS_ADDED_COUNT.add(&metrics::CONTEXT, 1, &[]); // Metrics
|
||||
super::add_process_sync_task(&*state.store, payment_attempt, stime)
|
||||
.await
|
||||
.into_report()
|
||||
@ -663,6 +663,7 @@ pub async fn create_customer_if_not_exist<'a, F: Clone, R>(
|
||||
..storage::CustomerNew::default()
|
||||
};
|
||||
|
||||
metrics::CUSTOMER_CREATED.add(&metrics::CONTEXT, 1, &[]);
|
||||
db.insert_customer(new_customer).await
|
||||
}
|
||||
})
|
||||
|
||||
@ -10,6 +10,7 @@ use crate::{
|
||||
payments::PaymentData,
|
||||
},
|
||||
db::StorageInterface,
|
||||
routes::metrics,
|
||||
services::RedirectForm,
|
||||
types::{
|
||||
self, api,
|
||||
@ -323,6 +324,10 @@ async fn payment_response_update_tracker<F: Clone, T>(
|
||||
.change_context(errors::ApiErrorResponse::InternalServerError)
|
||||
.attach_printable("Could not parse the connector response")?;
|
||||
|
||||
if router_data.status == enums::AttemptStatus::Charged {
|
||||
metrics::SUCCESSFUL_PAYMENT.add(&metrics::CONTEXT, 1, &[]);
|
||||
}
|
||||
|
||||
let payment_attempt_update = storage::PaymentAttemptUpdate::ResponseUpdate {
|
||||
status: router_data.status,
|
||||
connector: Some(router_data.connector),
|
||||
|
||||
@ -11,7 +11,7 @@ use crate::{
|
||||
utils as core_utils,
|
||||
},
|
||||
db, logger,
|
||||
routes::AppState,
|
||||
routes::{metrics, AppState},
|
||||
scheduler::{process_data, utils as process_tracker_utils, workflows::payment_sync},
|
||||
services,
|
||||
types::{
|
||||
@ -98,6 +98,16 @@ pub async fn trigger_refund_to_gateway(
|
||||
.clone()
|
||||
.ok_or(errors::ApiErrorResponse::InternalServerError)?;
|
||||
let connector_id = connector.to_string();
|
||||
|
||||
metrics::REFUND_COUNT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.to_string(),
|
||||
)],
|
||||
);
|
||||
|
||||
let connector: api::ConnectorData = api::ConnectorData::get_connector_by_name(
|
||||
&state.conf.connectors,
|
||||
&connector_id,
|
||||
@ -164,13 +174,25 @@ pub async fn trigger_refund_to_gateway(
|
||||
refund_error_message: Some(err.message),
|
||||
refund_error_code: Some(err.code),
|
||||
},
|
||||
Ok(response) => storage::RefundUpdate::Update {
|
||||
connector_refund_id: response.connector_refund_id,
|
||||
refund_status: response.refund_status,
|
||||
sent_to_gateway: true,
|
||||
refund_error_message: None,
|
||||
refund_arn: "".to_string(),
|
||||
},
|
||||
Ok(response) => {
|
||||
if response.refund_status == storage_models::enums::RefundStatus::Success {
|
||||
metrics::SUCCESSFUL_REFUND.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
connector.connector_name.to_string(),
|
||||
)],
|
||||
)
|
||||
}
|
||||
storage::RefundUpdate::Update {
|
||||
connector_refund_id: response.connector_refund_id,
|
||||
refund_status: response.refund_status,
|
||||
sent_to_gateway: true,
|
||||
refund_error_message: None,
|
||||
refund_arn: "".to_string(),
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
let response = state
|
||||
|
||||
@ -29,7 +29,9 @@ pub async fn merchant_account_create(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<admin::MerchantAccountCreate>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantsAccountCreate;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -60,11 +62,13 @@ pub async fn retrieve_merchant_account(
|
||||
req: HttpRequest,
|
||||
mid: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantsAccountRetrieve;
|
||||
let payload = web::Json(admin::MerchantId {
|
||||
merchant_id: mid.into_inner(),
|
||||
})
|
||||
.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -97,8 +101,10 @@ pub async fn update_merchant_account(
|
||||
mid: web::Path<String>,
|
||||
json_payload: web::Json<admin::MerchantAccountUpdate>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantsAccountUpdate;
|
||||
let merchant_id = mid.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -130,11 +136,13 @@ pub async fn delete_merchant_account(
|
||||
req: HttpRequest,
|
||||
mid: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantsAccountDelete;
|
||||
let payload = web::Json(admin::MerchantId {
|
||||
merchant_id: mid.into_inner(),
|
||||
})
|
||||
.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -166,8 +174,10 @@ pub async fn payment_connector_create(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Json<admin::MerchantConnector>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantConnectorsCreate;
|
||||
let merchant_id = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -202,6 +212,7 @@ pub async fn payment_connector_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<(String, String)>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantConnectorsRetrieve;
|
||||
let (merchant_id, merchant_connector_id) = path.into_inner();
|
||||
let payload = web::Json(admin::MerchantConnectorId {
|
||||
merchant_id,
|
||||
@ -209,6 +220,7 @@ pub async fn payment_connector_retrieve(
|
||||
})
|
||||
.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -244,8 +256,10 @@ pub async fn payment_connector_list(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantConnectorsList;
|
||||
let merchant_id = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
merchant_id,
|
||||
@ -282,8 +296,10 @@ pub async fn payment_connector_update(
|
||||
path: web::Path<(String, String)>,
|
||||
json_payload: web::Json<admin::MerchantConnector>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantConnectorsUpdate;
|
||||
let (merchant_id, merchant_connector_id) = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -320,6 +336,7 @@ pub async fn payment_connector_delete(
|
||||
req: HttpRequest,
|
||||
path: web::Path<(String, String)>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MerchantConnectorsDelete;
|
||||
let (merchant_id, merchant_connector_id) = path.into_inner();
|
||||
let payload = web::Json(admin::MerchantConnectorId {
|
||||
merchant_id,
|
||||
@ -327,6 +344,7 @@ pub async fn payment_connector_delete(
|
||||
})
|
||||
.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -348,9 +366,11 @@ pub async fn merchant_account_toggle_kv(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Json<admin::ToggleKVRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::ConfigKeyUpdate;
|
||||
let payload = json_payload.into_inner();
|
||||
let merchant_id = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
(merchant_id, payload),
|
||||
@ -371,8 +391,10 @@ pub async fn merchant_account_kv_status(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::ConfigKeyFetch;
|
||||
let merchant_id = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
merchant_id,
|
||||
|
||||
@ -32,10 +32,12 @@ pub async fn api_key_create(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Json<api_types::CreateApiKeyRequest>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ApiKeyCreate;
|
||||
let payload = json_payload.into_inner();
|
||||
let merchant_id = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -79,9 +81,11 @@ pub async fn api_key_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<(String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ApiKeyRetrieve;
|
||||
let (_merchant_id, key_id) = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
&key_id,
|
||||
@ -117,10 +121,12 @@ pub async fn api_key_update(
|
||||
path: web::Path<(String, String)>,
|
||||
json_payload: web::Json<api_types::UpdateApiKeyRequest>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ApiKeyUpdate;
|
||||
let (_merchant_id, key_id) = path.into_inner();
|
||||
let payload = json_payload.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
(&key_id, payload),
|
||||
@ -155,9 +161,11 @@ pub async fn api_key_revoke(
|
||||
req: HttpRequest,
|
||||
path: web::Path<(String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ApiKeyRevoke;
|
||||
let (_merchant_id, key_id) = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
&key_id,
|
||||
@ -192,12 +200,14 @@ pub async fn api_key_list(
|
||||
path: web::Path<String>,
|
||||
query: web::Query<api_types::ListApiKeyConstraints>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ApiKeyList;
|
||||
let list_api_key_constraints = query.into_inner();
|
||||
let limit = list_api_key_constraints.limit;
|
||||
let offset = list_api_key_constraints.skip;
|
||||
let merchant_id = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
(limit, offset, merchant_id),
|
||||
|
||||
@ -14,9 +14,11 @@ pub async fn config_key_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ConfigKeyFetch;
|
||||
let key = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
&key,
|
||||
@ -33,11 +35,13 @@ pub async fn config_key_update(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Json<api_types::ConfigUpdate>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::ConfigKeyUpdate;
|
||||
let mut payload = json_payload.into_inner();
|
||||
let key = path.into_inner();
|
||||
payload.key = key;
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
&payload,
|
||||
|
||||
@ -29,7 +29,9 @@ pub async fn customers_create(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<customers::CustomerRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::CustomersCreate;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -60,6 +62,7 @@ pub async fn customers_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::CustomersRetrieve;
|
||||
let payload = web::Json(customers::CustomerId {
|
||||
customer_id: path.into_inner(),
|
||||
})
|
||||
@ -72,6 +75,7 @@ pub async fn customers_retrieve(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -104,9 +108,11 @@ pub async fn customers_update(
|
||||
path: web::Path<String>,
|
||||
mut json_payload: web::Json<customers::CustomerRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::CustomersUpdate;
|
||||
let customer_id = path.into_inner();
|
||||
json_payload.customer_id = customer_id;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -137,11 +143,13 @@ pub async fn customers_delete(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::CustomersCreate;
|
||||
let payload = web::Json(customers::CustomerId {
|
||||
customer_id: path.into_inner(),
|
||||
})
|
||||
.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -157,11 +165,13 @@ pub async fn get_customer_mandates(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::CustomersGetMandates;
|
||||
let customer_id = customers::CustomerId {
|
||||
customer_id: path.into_inner(),
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
customer_id,
|
||||
|
||||
@ -14,8 +14,10 @@ pub async fn ephemeral_key_create(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<customers::CustomerId>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::EphemeralKeyCreate;
|
||||
let payload = json_payload.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -33,8 +35,10 @@ pub async fn ephemeral_key_delete(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::EphemeralKeyDelete;
|
||||
let payload = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
|
||||
@ -32,10 +32,12 @@ pub async fn get_mandate(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MandatesRetrieve;
|
||||
let mandate_id = mandates::MandateId {
|
||||
mandate_id: path.into_inner(),
|
||||
};
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
mandate_id,
|
||||
@ -69,10 +71,12 @@ pub async fn revoke_mandate(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::MandatesRevoke;
|
||||
let mandate_id = mandates::MandateId {
|
||||
mandate_id: path.into_inner(),
|
||||
};
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
mandate_id,
|
||||
|
||||
@ -1,4 +1,4 @@
|
||||
use router_env::{counter_metric, global_meter, metrics_context};
|
||||
use router_env::{counter_metric, global_meter, histogram_metric, metrics_context};
|
||||
|
||||
metrics_context!(CONTEXT);
|
||||
global_meter!(GLOBAL_METER, "ROUTER_API");
|
||||
@ -7,3 +7,66 @@ counter_metric!(HEALTH_METRIC, GLOBAL_METER); // No. of health API hits
|
||||
counter_metric!(KV_MISS, GLOBAL_METER); // No. of KV misses
|
||||
#[cfg(feature = "kms")]
|
||||
counter_metric!(AWS_KMS_FAILURES, GLOBAL_METER); // No. of AWS KMS API failures
|
||||
|
||||
// API Level Metrics
|
||||
counter_metric!(REQUESTS_RECEIVED, GLOBAL_METER);
|
||||
counter_metric!(FAILED_REQUEST, GLOBAL_METER);
|
||||
histogram_metric!(REQUEST_TIME, GLOBAL_METER);
|
||||
|
||||
// Operation Level Metrics
|
||||
counter_metric!(PAYMENT_COUNT, GLOBAL_METER);
|
||||
counter_metric!(SUCCESSFUL_PAYMENT, GLOBAL_METER);
|
||||
|
||||
counter_metric!(REFUND_COUNT, GLOBAL_METER);
|
||||
counter_metric!(SUCCESSFUL_REFUND, GLOBAL_METER);
|
||||
|
||||
counter_metric!(PAYMENT_CANCEL_COUNT, GLOBAL_METER);
|
||||
counter_metric!(SUCCESSFUL_CANCEL, GLOBAL_METER);
|
||||
|
||||
counter_metric!(MANDATE_COUNT, GLOBAL_METER);
|
||||
counter_metric!(SUBSEQUENT_MANDATE_PAYMENT, GLOBAL_METER);
|
||||
|
||||
counter_metric!(RETRY_COUNT, GLOBAL_METER);
|
||||
|
||||
counter_metric!(STORED_TO_LOCKER, GLOBAL_METER);
|
||||
counter_metric!(GET_FROM_LOCKER, GLOBAL_METER);
|
||||
counter_metric!(DELETE_FROM_LOCKER, GLOBAL_METER);
|
||||
|
||||
counter_metric!(CREATED_TOKENIZED_CARD, GLOBAL_METER);
|
||||
counter_metric!(DELETED_TOKENIZED_CARD, GLOBAL_METER);
|
||||
counter_metric!(GET_TOKENIZED_CARD, GLOBAL_METER);
|
||||
|
||||
counter_metric!(CUSTOMER_CREATED, GLOBAL_METER);
|
||||
counter_metric!(CUSTOMER_REDACTED, GLOBAL_METER);
|
||||
|
||||
counter_metric!(API_KEY_CREATED, GLOBAL_METER);
|
||||
counter_metric!(API_KEY_REVOKED, GLOBAL_METER);
|
||||
|
||||
// Flow Specific Metrics
|
||||
|
||||
counter_metric!(ACCESS_TOKEN_CREATION, GLOBAL_METER);
|
||||
histogram_metric!(CONNECTOR_REQUEST_TIME, GLOBAL_METER);
|
||||
counter_metric!(SESSION_TOKEN_CREATED, GLOBAL_METER);
|
||||
|
||||
counter_metric!(CONNECTOR_CALL_COUNT, GLOBAL_METER); // Attributes needed
|
||||
|
||||
counter_metric!(THREE_DS_PAYMENT_COUNT, GLOBAL_METER);
|
||||
counter_metric!(THREE_DS_DOWNGRADE_COUNT, GLOBAL_METER);
|
||||
|
||||
counter_metric!(RESPONSE_DESERIALIZATION_FAILURE, GLOBAL_METER);
|
||||
counter_metric!(CONNECTOR_ERROR_RESPONSE_COUNT, GLOBAL_METER);
|
||||
counter_metric!(REQUEST_TIMEOUT_COUNT, GLOBAL_METER);
|
||||
|
||||
// Connector Level Metric
|
||||
counter_metric!(REQUEST_BUILD_FAILURE, GLOBAL_METER);
|
||||
counter_metric!(UNIMPLEMENTED_FLOW, GLOBAL_METER);
|
||||
|
||||
// Service Level
|
||||
counter_metric!(CARD_LOCKER_FAILURES, GLOBAL_METER);
|
||||
counter_metric!(TEMP_LOCKER_FAILURES, GLOBAL_METER);
|
||||
histogram_metric!(CARD_ADD_TIME, GLOBAL_METER);
|
||||
histogram_metric!(CARD_GET_TIME, GLOBAL_METER);
|
||||
histogram_metric!(CARD_DELETE_TIME, GLOBAL_METER);
|
||||
|
||||
pub mod request;
|
||||
pub mod utils;
|
||||
|
||||
36
crates/router/src/routes/metrics/request.rs
Normal file
36
crates/router/src/routes/metrics/request.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use super::utils as metric_utils;
|
||||
|
||||
pub async fn record_request_time_metric<F, R>(future: F, flow: router_env::Flow) -> R
|
||||
where
|
||||
F: futures::Future<Output = R>,
|
||||
{
|
||||
let key = "request_type";
|
||||
super::REQUESTS_RECEIVED.add(&super::CONTEXT, 1, &[add_attributes(key, flow.to_string())]);
|
||||
let (result, time) = metric_utils::time_future(future).await;
|
||||
super::REQUEST_TIME.record(
|
||||
&super::CONTEXT,
|
||||
time.as_secs_f64(),
|
||||
&[add_attributes(key, flow.to_string())],
|
||||
);
|
||||
result
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub async fn record_card_operation_time<F, R>(
|
||||
future: F,
|
||||
metric: &once_cell::sync::Lazy<router_env::opentelemetry::metrics::Histogram<f64>>,
|
||||
) -> R
|
||||
where
|
||||
F: futures::Future<Output = R>,
|
||||
{
|
||||
let (result, time) = metric_utils::time_future(future).await;
|
||||
metric.record(&super::CONTEXT, time.as_secs_f64(), &[]);
|
||||
result
|
||||
}
|
||||
|
||||
pub fn add_attributes<T: Into<router_env::opentelemetry::Value>>(
|
||||
key: &'static str,
|
||||
value: T,
|
||||
) -> router_env::opentelemetry::KeyValue {
|
||||
router_env::opentelemetry::KeyValue::new(key, value)
|
||||
}
|
||||
12
crates/router/src/routes/metrics/utils.rs
Normal file
12
crates/router/src/routes/metrics/utils.rs
Normal file
@ -0,0 +1,12 @@
|
||||
use std::time;
|
||||
|
||||
#[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)
|
||||
}
|
||||
@ -29,7 +29,9 @@ pub async fn create_payment_method_api(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<payment_methods::PaymentMethodCreate>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::PaymentMethodsCreate;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -71,6 +73,7 @@ pub async fn list_payment_method_api(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Query<payment_methods::PaymentMethodListRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::PaymentMethodsList;
|
||||
let payload = json_payload.into_inner();
|
||||
|
||||
let (auth, _) = match auth::check_client_secret_and_get_auth(req.headers(), &payload) {
|
||||
@ -79,6 +82,7 @@ pub async fn list_payment_method_api(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -119,6 +123,7 @@ pub async fn list_customer_payment_method_api(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Query<payment_methods::PaymentMethodListRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::CustomerPaymentMethodsList;
|
||||
let customer_id = customer_id.into_inner().0;
|
||||
|
||||
let auth_type = match auth::is_ephemeral_auth(req.headers(), &*state.store, &customer_id).await
|
||||
@ -128,6 +133,7 @@ pub async fn list_customer_payment_method_api(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -162,12 +168,14 @@ pub async fn payment_method_retrieve_api(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::PaymentMethodsRetrieve;
|
||||
let payload = web::Json(PaymentMethodId {
|
||||
payment_method_id: path.into_inner(),
|
||||
})
|
||||
.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -202,9 +210,11 @@ pub async fn payment_method_update_api(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Json<payment_methods::PaymentMethodUpdate>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::PaymentMethodsUpdate;
|
||||
let payment_method_id = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -244,10 +254,12 @@ pub async fn payment_method_delete_api(
|
||||
req: HttpRequest,
|
||||
payment_method_id: web::Path<(String,)>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::PaymentMethodsDelete;
|
||||
let pm = PaymentMethodId {
|
||||
payment_method_id: payment_method_id.into_inner().0,
|
||||
};
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
pm,
|
||||
|
||||
@ -34,6 +34,7 @@ pub async fn payments_create(
|
||||
req: actix_web::HttpRequest,
|
||||
json_payload: web::Json<payment_types::PaymentsRequest>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsCreate;
|
||||
let payload = json_payload.into_inner();
|
||||
|
||||
if let Some(api_enums::CaptureMethod::Scheduled) = payload.capture_method {
|
||||
@ -41,6 +42,7 @@ pub async fn payments_create(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -82,13 +84,14 @@ pub async fn payments_start(
|
||||
req: actix_web::HttpRequest,
|
||||
path: web::Path<(String, String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsStart;
|
||||
let (payment_id, merchant_id, attempt_id) = path.into_inner();
|
||||
let payload = payment_types::PaymentsStartRequest {
|
||||
payment_id: payment_id.clone(),
|
||||
merchant_id: merchant_id.clone(),
|
||||
attempt_id: attempt_id.clone(),
|
||||
};
|
||||
api::server_wrap(
|
||||
api::server_wrap(flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -133,6 +136,7 @@ pub async fn payments_retrieve(
|
||||
path: web::Path<String>,
|
||||
json_payload: web::Query<payment_types::PaymentRetrieveBody>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsRetrieve;
|
||||
let payload = payment_types::PaymentsRetrieveRequest {
|
||||
resource_id: payment_types::PaymentIdType::PaymentIntentId(path.to_string()),
|
||||
merchant_id: json_payload.merchant_id.clone(),
|
||||
@ -146,6 +150,7 @@ pub async fn payments_retrieve(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -190,6 +195,7 @@ pub async fn payments_update(
|
||||
json_payload: web::Json<payment_types::PaymentsRequest>,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsUpdate;
|
||||
let mut payload = json_payload.into_inner();
|
||||
|
||||
if let Some(api_enums::CaptureMethod::Scheduled) = payload.capture_method {
|
||||
@ -206,6 +212,7 @@ pub async fn payments_update(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -249,6 +256,7 @@ pub async fn payments_confirm(
|
||||
json_payload: web::Json<payment_types::PaymentsRequest>,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsConfirm;
|
||||
let mut payload = json_payload.into_inner();
|
||||
|
||||
if let Some(api_enums::CaptureMethod::Scheduled) = payload.capture_method {
|
||||
@ -266,6 +274,7 @@ pub async fn payments_confirm(
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -309,12 +318,14 @@ pub async fn payments_capture(
|
||||
json_payload: web::Json<payment_types::PaymentsCaptureRequest>,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsCapture;
|
||||
let capture_payload = payment_types::PaymentsCaptureRequest {
|
||||
payment_id: Some(path.into_inner()),
|
||||
..json_payload.into_inner()
|
||||
};
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
capture_payload,
|
||||
@ -354,9 +365,11 @@ pub async fn payments_connector_session(
|
||||
req: actix_web::HttpRequest,
|
||||
json_payload: web::Json<payment_types::PaymentsSessionRequest>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsSessionToken;
|
||||
let sessions_payload = json_payload.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
sessions_payload,
|
||||
@ -405,6 +418,7 @@ pub async fn payments_redirect_response(
|
||||
req: actix_web::HttpRequest,
|
||||
path: web::Path<(String, String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsRedirect;
|
||||
let (payment_id, merchant_id, connector) = path.into_inner();
|
||||
let param_string = req.query_string();
|
||||
|
||||
@ -417,6 +431,7 @@ pub async fn payments_redirect_response(
|
||||
connector: Some(connector),
|
||||
};
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -439,6 +454,7 @@ pub async fn payments_complete_authorize(
|
||||
json_payload: web::Form<serde_json::Value>,
|
||||
path: web::Path<(String, String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsRedirect;
|
||||
let (payment_id, merchant_id, connector) = path.into_inner();
|
||||
let param_string = req.query_string();
|
||||
|
||||
@ -451,6 +467,7 @@ pub async fn payments_complete_authorize(
|
||||
connector: Some(connector),
|
||||
};
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -492,11 +509,13 @@ pub async fn payments_cancel(
|
||||
json_payload: web::Json<payment_types::PaymentsCancelRequest>,
|
||||
path: web::Path<String>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsCancel;
|
||||
let mut payload = json_payload.into_inner();
|
||||
let payment_id = path.into_inner();
|
||||
payload.payment_id = payment_id;
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
@ -548,8 +567,10 @@ pub async fn payments_list(
|
||||
req: actix_web::HttpRequest,
|
||||
payload: web::Query<payment_types::PaymentListConstraints>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::PaymentsList;
|
||||
let payload = payload.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload,
|
||||
|
||||
@ -7,36 +7,42 @@ use router_env::{instrument, tracing, Flow};
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsCreate))]
|
||||
// #[post("/create")]
|
||||
pub async fn payouts_create() -> impl Responder {
|
||||
let _flow = Flow::PayoutsCreate;
|
||||
http_response("create")
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsRetrieve))]
|
||||
// #[get("/retrieve")]
|
||||
pub async fn payouts_retrieve() -> impl Responder {
|
||||
let _flow = Flow::PayoutsRetrieve;
|
||||
http_response("retrieve")
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsUpdate))]
|
||||
// #[post("/update")]
|
||||
pub async fn payouts_update() -> impl Responder {
|
||||
let _flow = Flow::PayoutsUpdate;
|
||||
http_response("update")
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsReverse))]
|
||||
// #[post("/reverse")]
|
||||
pub async fn payouts_reverse() -> impl Responder {
|
||||
let _flow = Flow::PayoutsReverse;
|
||||
http_response("reverse")
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsCancel))]
|
||||
// #[post("/cancel")]
|
||||
pub async fn payouts_cancel() -> impl Responder {
|
||||
let _flow = Flow::PayoutsCancel;
|
||||
http_response("cancel")
|
||||
}
|
||||
|
||||
#[instrument(skip_all, fields(flow = ?Flow::PayoutsAccounts))]
|
||||
// #[get("/accounts")]
|
||||
pub async fn payouts_accounts() -> impl Responder {
|
||||
let _flow = Flow::PayoutsAccounts;
|
||||
http_response("accounts")
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,9 @@ pub async fn refunds_create(
|
||||
req: HttpRequest,
|
||||
json_payload: web::Json<refunds::RefundRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::RefundsCreate;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -64,9 +66,11 @@ pub async fn refunds_retrieve(
|
||||
req: HttpRequest,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::RefundsRetrieve;
|
||||
let refund_id = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
refund_id,
|
||||
@ -104,8 +108,10 @@ pub async fn refunds_update(
|
||||
json_payload: web::Json<refunds::RefundUpdateRequest>,
|
||||
path: web::Path<String>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::RefundsUpdate;
|
||||
let refund_id = path.into_inner();
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
json_payload.into_inner(),
|
||||
@ -148,7 +154,9 @@ pub async fn refunds_list(
|
||||
req: HttpRequest,
|
||||
payload: web::Query<api_models::refunds::RefundListRequest>,
|
||||
) -> HttpResponse {
|
||||
let flow = Flow::RefundsList;
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
payload.into_inner(),
|
||||
|
||||
@ -15,9 +15,11 @@ pub async fn receive_incoming_webhook<W: api_types::OutgoingWebhookType>(
|
||||
body: web::Bytes,
|
||||
path: web::Path<(String, String)>,
|
||||
) -> impl Responder {
|
||||
let flow = Flow::IncomingWebhookReceive;
|
||||
let (merchant_id, connector_name) = path.into_inner();
|
||||
|
||||
api::server_wrap(
|
||||
flow,
|
||||
state.get_ref(),
|
||||
&req,
|
||||
body,
|
||||
|
||||
@ -26,7 +26,7 @@ use crate::{
|
||||
payments,
|
||||
},
|
||||
logger,
|
||||
routes::{app::AppStateInfo, AppState},
|
||||
routes::{app::AppStateInfo, metrics, AppState},
|
||||
services::authentication as auth,
|
||||
types::{self, api, storage, ErrorResponse},
|
||||
};
|
||||
@ -103,9 +103,17 @@ pub trait ConnectorIntegration<T, Req, Resp>: ConnectorIntegrationAny<T, Req, Re
|
||||
|
||||
fn build_request(
|
||||
&self,
|
||||
_req: &types::RouterData<T, Req, Resp>,
|
||||
req: &types::RouterData<T, Req, Resp>,
|
||||
_connectors: &Connectors,
|
||||
) -> CustomResult<Option<Request>, errors::ConnectorError> {
|
||||
metrics::UNIMPLEMENTED_FLOW.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
req.connector.clone(),
|
||||
)],
|
||||
);
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
@ -179,7 +187,40 @@ where
|
||||
Ok(router_data)
|
||||
}
|
||||
payments::CallConnectorAction::Trigger => {
|
||||
match connector_integration.build_request(req, &state.conf.connectors)? {
|
||||
metrics::CONNECTOR_CALL_COUNT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[
|
||||
metrics::request::add_attributes("connector", req.connector.to_string()),
|
||||
metrics::request::add_attributes(
|
||||
"flow",
|
||||
std::any::type_name::<T>()
|
||||
.split("::")
|
||||
.last()
|
||||
.unwrap_or_default()
|
||||
.to_string(),
|
||||
),
|
||||
],
|
||||
);
|
||||
match connector_integration
|
||||
.build_request(req, &state.conf.connectors)
|
||||
.map_err(|error| {
|
||||
if matches!(
|
||||
error.current_context(),
|
||||
&errors::ConnectorError::RequestEncodingFailed
|
||||
| &errors::ConnectorError::RequestEncodingFailedWithReason(_)
|
||||
) {
|
||||
metrics::RESPONSE_DESERIALIZATION_FAILURE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
req.connector.to_string(),
|
||||
)],
|
||||
)
|
||||
}
|
||||
error
|
||||
})? {
|
||||
Some(request) => {
|
||||
logger::debug!(connector_request=?request);
|
||||
let response = call_connector_api(state, request).await;
|
||||
@ -187,8 +228,32 @@ where
|
||||
match response {
|
||||
Ok(body) => {
|
||||
let response = match body {
|
||||
Ok(body) => connector_integration.handle_response(req, body)?,
|
||||
Ok(body) => connector_integration
|
||||
.handle_response(req, body)
|
||||
.map_err(|error| {
|
||||
if error.current_context()
|
||||
== &errors::ConnectorError::ResponseDeserializationFailed
|
||||
{
|
||||
metrics::RESPONSE_DESERIALIZATION_FAILURE.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
req.connector.to_string(),
|
||||
)],
|
||||
)
|
||||
}
|
||||
error
|
||||
})?,
|
||||
Err(body) => {
|
||||
metrics::CONNECTOR_ERROR_RESPONSE_COUNT.add(
|
||||
&metrics::CONTEXT,
|
||||
1,
|
||||
&[metrics::request::add_attributes(
|
||||
"connector",
|
||||
req.connector.clone(),
|
||||
)],
|
||||
);
|
||||
let error = connector_integration.get_error_response(body)?;
|
||||
router_data.response = Err(error);
|
||||
|
||||
@ -277,7 +342,10 @@ async fn send_request(
|
||||
.send()
|
||||
.await
|
||||
.map_err(|error| match error {
|
||||
error if error.is_timeout() => errors::ApiClientError::RequestTimeoutReceived,
|
||||
error if error.is_timeout() => {
|
||||
metrics::REQUEST_BUILD_FAILURE.add(&metrics::CONTEXT, 1, &[]);
|
||||
errors::ApiClientError::RequestTimeoutReceived
|
||||
}
|
||||
_ => errors::ApiClientError::RequestNotSent(error.to_string()),
|
||||
})
|
||||
.into_report()
|
||||
@ -454,6 +522,7 @@ where
|
||||
fields(request_method, request_url_path)
|
||||
)]
|
||||
pub async fn server_wrap<'a, 'b, A, T, U, Q, F, Fut, E>(
|
||||
flow: router_env::Flow,
|
||||
state: &'b A,
|
||||
request: &'a HttpRequest,
|
||||
payload: T,
|
||||
@ -476,8 +545,12 @@ where
|
||||
|
||||
let start_instant = Instant::now();
|
||||
logger::info!(tag = ?Tag::BeginRequest);
|
||||
|
||||
let res = match server_wrap_util(state, request, payload, func, api_auth).await {
|
||||
let res = match metrics::request::record_request_time_metric(
|
||||
server_wrap_util(state, request, payload, func, api_auth),
|
||||
flow,
|
||||
)
|
||||
.await
|
||||
{
|
||||
Ok(ApplicationResponse::Json(response)) => match serde_json::to_string(&response) {
|
||||
Ok(res) => http_response_json(res),
|
||||
Err(_) => http_response_err(
|
||||
|
||||
@ -138,6 +138,8 @@ pub enum Flow {
|
||||
PayoutsCancel,
|
||||
/// Payouts accounts flow.
|
||||
PayoutsAccounts,
|
||||
/// Payments Redirect flow.
|
||||
PaymentsRedirect,
|
||||
/// Refunds create flow.
|
||||
RefundsCreate,
|
||||
/// Refunds retrieve flow.
|
||||
|
||||
Reference in New Issue
Block a user