refactor(events): Allow box dyn for event handler (#2629)

Co-authored-by: Nishant Joshi <nishant.joshi@juspay.in>
This commit is contained in:
Sampras Lopes
2023-10-18 18:49:36 +05:30
committed by GitHub
parent 6cf8f0582c
commit 01410bb9f2
5 changed files with 42 additions and 42 deletions

View File

@ -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;
}

View File

@ -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)?,
})
} }
} }

View File

@ -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");
} }
} }

View File

@ -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(),
} }
} }

View File

@ -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,