mirror of
https://github.com/juspay/hyperswitch.git
synced 2025-10-30 09:38:33 +08:00
refactor(events): Allow box dyn for event handler (#2629)
Co-authored-by: Nishant Joshi <nishant.joshi@juspay.in>
This commit is contained in:
@ -4,7 +4,15 @@ pub mod api_logs;
|
|||||||
pub mod event_logger;
|
pub mod event_logger;
|
||||||
|
|
||||||
pub trait EventHandler: Sync + Send + dyn_clone::DynClone {
|
pub trait EventHandler: Sync + Send + dyn_clone::DynClone {
|
||||||
fn log_event<T: Event>(&self, event: T);
|
fn log_event(&self, event: RawEvent);
|
||||||
|
}
|
||||||
|
|
||||||
|
dyn_clone::clone_trait_object!(EventHandler);
|
||||||
|
|
||||||
|
pub struct RawEvent {
|
||||||
|
event_type: EventType,
|
||||||
|
key: String,
|
||||||
|
payload: serde_json::Value,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Serialize)]
|
#[derive(Debug, Serialize)]
|
||||||
@ -15,12 +23,3 @@ pub enum EventType {
|
|||||||
Refund,
|
Refund,
|
||||||
ApiLogs,
|
ApiLogs,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub trait Event
|
|
||||||
where
|
|
||||||
Self: Serialize,
|
|
||||||
{
|
|
||||||
fn event_type() -> EventType;
|
|
||||||
|
|
||||||
fn key(&self) -> String;
|
|
||||||
}
|
|
||||||
|
|||||||
@ -2,7 +2,7 @@ use router_env::{tracing_actix_web::RequestId, types::FlowMetric};
|
|||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use super::Event;
|
use super::{EventType, RawEvent};
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Eq, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct ApiEvent {
|
pub struct ApiEvent {
|
||||||
@ -30,12 +30,14 @@ impl ApiEvent {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Event for ApiEvent {
|
impl TryFrom<ApiEvent> for RawEvent {
|
||||||
fn event_type() -> super::EventType {
|
type Error = serde_json::Error;
|
||||||
super::EventType::ApiLogs
|
|
||||||
}
|
|
||||||
|
|
||||||
fn key(&self) -> String {
|
fn try_from(value: ApiEvent) -> Result<Self, Self::Error> {
|
||||||
self.request_id.to_string()
|
Ok(Self {
|
||||||
|
event_type: EventType::ApiLogs,
|
||||||
|
key: value.request_id.clone(),
|
||||||
|
payload: serde_json::to_value(value)?,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,11 +1,11 @@
|
|||||||
use super::{Event, EventHandler};
|
use super::{EventHandler, RawEvent};
|
||||||
use crate::services::logger;
|
use crate::services::logger;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default)]
|
#[derive(Clone, Debug, Default)]
|
||||||
pub struct EventLogger {}
|
pub struct EventLogger {}
|
||||||
|
|
||||||
impl EventHandler for EventLogger {
|
impl EventHandler for EventLogger {
|
||||||
fn log_event<T: Event>(&self, event: T) {
|
fn log_event(&self, event: RawEvent) {
|
||||||
logger::info!(current = ?serde_json::to_string(&event).unwrap_or(r#"{ "error": "Serialization failed" }"#.to_string()), event_type =? T::event_type(), event_id =? event.key(), log_type = "event");
|
logger::info!(event = ?serde_json::to_string(&event.payload).unwrap_or(r#"{ "error": "Serialization failed" }"#.to_string()), event_type =? event.event_type, event_id =? event.key, log_type = "event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -32,11 +32,11 @@ use crate::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct AppStateBase<E: EventHandler> {
|
pub struct AppState {
|
||||||
pub flow_name: String,
|
pub flow_name: String,
|
||||||
pub store: Box<dyn StorageInterface>,
|
pub store: Box<dyn StorageInterface>,
|
||||||
pub conf: Arc<settings::Settings>,
|
pub conf: Arc<settings::Settings>,
|
||||||
pub event_handler: E,
|
pub event_handler: Box<dyn EventHandler>,
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
pub email_client: Arc<dyn EmailClient>,
|
pub email_client: Arc<dyn EmailClient>,
|
||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
@ -44,8 +44,6 @@ pub struct AppStateBase<E: EventHandler> {
|
|||||||
pub api_client: Box<dyn crate::services::ApiClient>,
|
pub api_client: Box<dyn crate::services::ApiClient>,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type AppState = AppStateBase<EventLogger>;
|
|
||||||
|
|
||||||
impl scheduler::SchedulerAppState for AppState {
|
impl scheduler::SchedulerAppState for AppState {
|
||||||
fn get_db(&self) -> Box<dyn SchedulerInterface> {
|
fn get_db(&self) -> Box<dyn SchedulerInterface> {
|
||||||
self.store.get_scheduler_db()
|
self.store.get_scheduler_db()
|
||||||
@ -53,10 +51,9 @@ impl scheduler::SchedulerAppState for AppState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait AppStateInfo {
|
pub trait AppStateInfo {
|
||||||
type Event: EventHandler;
|
|
||||||
fn conf(&self) -> settings::Settings;
|
fn conf(&self) -> settings::Settings;
|
||||||
fn store(&self) -> Box<dyn StorageInterface>;
|
fn store(&self) -> Box<dyn StorageInterface>;
|
||||||
fn event_handler(&self) -> &Self::Event;
|
fn event_handler(&self) -> Box<dyn EventHandler>;
|
||||||
#[cfg(feature = "email")]
|
#[cfg(feature = "email")]
|
||||||
fn email_client(&self) -> Arc<dyn EmailClient>;
|
fn email_client(&self) -> Arc<dyn EmailClient>;
|
||||||
fn add_request_id(&mut self, request_id: RequestId);
|
fn add_request_id(&mut self, request_id: RequestId);
|
||||||
@ -66,7 +63,6 @@ pub trait AppStateInfo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl AppStateInfo for AppState {
|
impl AppStateInfo for AppState {
|
||||||
type Event = EventLogger;
|
|
||||||
fn conf(&self) -> settings::Settings {
|
fn conf(&self) -> settings::Settings {
|
||||||
self.conf.as_ref().to_owned()
|
self.conf.as_ref().to_owned()
|
||||||
}
|
}
|
||||||
@ -77,8 +73,8 @@ impl AppStateInfo for AppState {
|
|||||||
fn email_client(&self) -> Arc<dyn EmailClient> {
|
fn email_client(&self) -> Arc<dyn EmailClient> {
|
||||||
self.email_client.to_owned()
|
self.email_client.to_owned()
|
||||||
}
|
}
|
||||||
fn event_handler(&self) -> &Self::Event {
|
fn event_handler(&self) -> Box<dyn EventHandler> {
|
||||||
&self.event_handler
|
self.event_handler.to_owned()
|
||||||
}
|
}
|
||||||
fn add_request_id(&mut self, request_id: RequestId) {
|
fn add_request_id(&mut self, request_id: RequestId) {
|
||||||
self.api_client.add_request_id(request_id);
|
self.api_client.add_request_id(request_id);
|
||||||
@ -148,7 +144,7 @@ impl AppState {
|
|||||||
#[cfg(feature = "kms")]
|
#[cfg(feature = "kms")]
|
||||||
kms_secrets: Arc::new(kms_secrets),
|
kms_secrets: Arc::new(kms_secrets),
|
||||||
api_client,
|
api_client,
|
||||||
event_handler: EventLogger::default(),
|
event_handler: Box::<EventLogger>::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -25,6 +25,7 @@ use serde_json::json;
|
|||||||
use tera::{Context, Tera};
|
use tera::{Context, Tera};
|
||||||
|
|
||||||
use self::request::{HeaderExt, RequestBuilderExt};
|
use self::request::{HeaderExt, RequestBuilderExt};
|
||||||
|
use super::authentication::{AuthInfo, AuthenticateAndFetch};
|
||||||
use crate::{
|
use crate::{
|
||||||
configs::settings::{Connectors, Settings},
|
configs::settings::{Connectors, Settings},
|
||||||
consts,
|
consts,
|
||||||
@ -33,14 +34,13 @@ use crate::{
|
|||||||
errors::{self, CustomResult},
|
errors::{self, CustomResult},
|
||||||
payments,
|
payments,
|
||||||
},
|
},
|
||||||
events::{api_logs::ApiEvent, EventHandler},
|
events::api_logs::ApiEvent,
|
||||||
logger,
|
logger,
|
||||||
routes::{
|
routes::{
|
||||||
app::AppStateInfo,
|
app::AppStateInfo,
|
||||||
metrics::{self, request as metrics_request},
|
metrics::{self, request as metrics_request},
|
||||||
AppState,
|
AppState,
|
||||||
},
|
},
|
||||||
services::authentication as auth,
|
|
||||||
types::{
|
types::{
|
||||||
self,
|
self,
|
||||||
api::{self, ConnectorCommon},
|
api::{self, ConnectorCommon},
|
||||||
@ -751,7 +751,7 @@ pub async fn server_wrap_util<'a, 'b, A, U, T, Q, F, Fut, E, OErr>(
|
|||||||
request: &'a HttpRequest,
|
request: &'a HttpRequest,
|
||||||
payload: T,
|
payload: T,
|
||||||
func: F,
|
func: F,
|
||||||
api_auth: &dyn auth::AuthenticateAndFetch<U, A>,
|
api_auth: &dyn AuthenticateAndFetch<U, A>,
|
||||||
lock_action: api_locking::LockAction,
|
lock_action: api_locking::LockAction,
|
||||||
) -> CustomResult<ApplicationResponse<Q>, OErr>
|
) -> CustomResult<ApplicationResponse<Q>, OErr>
|
||||||
where
|
where
|
||||||
@ -761,7 +761,7 @@ where
|
|||||||
Q: Serialize + Debug + 'a,
|
Q: Serialize + Debug + 'a,
|
||||||
T: Debug,
|
T: Debug,
|
||||||
A: AppStateInfo + Clone,
|
A: AppStateInfo + Clone,
|
||||||
U: auth::AuthInfo,
|
U: AuthInfo,
|
||||||
E: ErrorSwitch<OErr> + error_stack::Context,
|
E: ErrorSwitch<OErr> + error_stack::Context,
|
||||||
OErr: ResponseError + error_stack::Context,
|
OErr: ResponseError + error_stack::Context,
|
||||||
errors::ApiErrorResponse: ErrorSwitch<OErr>,
|
errors::ApiErrorResponse: ErrorSwitch<OErr>,
|
||||||
@ -816,12 +816,15 @@ where
|
|||||||
Ok(res) => metrics::request::track_response_status_code(res),
|
Ok(res) => metrics::request::track_response_status_code(res),
|
||||||
Err(err) => err.current_context().status_code().as_u16().into(),
|
Err(err) => err.current_context().status_code().as_u16().into(),
|
||||||
};
|
};
|
||||||
state.event_handler().log_event(ApiEvent::new(
|
let api_event = ApiEvent::new(flow, &request_id, request_duration, status_code);
|
||||||
flow,
|
match api_event.clone().try_into() {
|
||||||
&request_id,
|
Ok(event) => {
|
||||||
request_duration,
|
state.event_handler().log_event(event);
|
||||||
status_code,
|
}
|
||||||
));
|
Err(err) => {
|
||||||
|
logger::error!(error=?err, event=?api_event, "Error Logging API Event");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
metrics::request::status_code_metrics(status_code, flow.to_string(), merchant_id.to_string());
|
metrics::request::status_code_metrics(status_code, flow.to_string(), merchant_id.to_string());
|
||||||
|
|
||||||
@ -838,7 +841,7 @@ pub async fn server_wrap<'a, A, T, U, Q, F, Fut, E>(
|
|||||||
request: &'a HttpRequest,
|
request: &'a HttpRequest,
|
||||||
payload: T,
|
payload: T,
|
||||||
func: F,
|
func: F,
|
||||||
api_auth: &dyn auth::AuthenticateAndFetch<U, A>,
|
api_auth: &dyn AuthenticateAndFetch<U, A>,
|
||||||
lock_action: api_locking::LockAction,
|
lock_action: api_locking::LockAction,
|
||||||
) -> HttpResponse
|
) -> HttpResponse
|
||||||
where
|
where
|
||||||
@ -846,7 +849,7 @@ where
|
|||||||
Fut: Future<Output = CustomResult<ApplicationResponse<Q>, E>>,
|
Fut: Future<Output = CustomResult<ApplicationResponse<Q>, E>>,
|
||||||
Q: Serialize + Debug + 'a,
|
Q: Serialize + Debug + 'a,
|
||||||
T: Debug,
|
T: Debug,
|
||||||
U: auth::AuthInfo,
|
U: AuthInfo,
|
||||||
A: AppStateInfo + Clone,
|
A: AppStateInfo + Clone,
|
||||||
ApplicationResponse<Q>: Debug,
|
ApplicationResponse<Q>: Debug,
|
||||||
E: ErrorSwitch<api_models::errors::types::ApiErrorResponse> + error_stack::Context,
|
E: ErrorSwitch<api_models::errors::types::ApiErrorResponse> + error_stack::Context,
|
||||||
|
|||||||
Reference in New Issue
Block a user