Skip to content

Commit 54d44be

Browse files
feat(outgoingwebhookevent): adding api for query to fetch outgoing webhook events log (#3310)
Co-authored-by: Sampras Lopes <[email protected]>
1 parent bb09613 commit 54d44be

File tree

12 files changed

+192
-3
lines changed

12 files changed

+192
-3
lines changed

crates/analytics/src/clickhouse.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ use crate::{
2121
filters::ApiEventFilter,
2222
metrics::{latency::LatencyAvg, ApiEventMetricRow},
2323
},
24+
outgoing_webhook_event::events::OutgoingWebhookLogsResult,
2425
sdk_events::events::SdkEventsResult,
2526
types::TableEngine,
2627
};
@@ -120,6 +121,7 @@ impl AnalyticsDataSource for ClickhouseClient {
120121
}
121122
AnalyticsCollection::SdkEvents => TableEngine::BasicTree,
122123
AnalyticsCollection::ApiEvents => TableEngine::BasicTree,
124+
AnalyticsCollection::OutgoingWebhookEvent => TableEngine::BasicTree,
123125
}
124126
}
125127
}
@@ -145,6 +147,10 @@ impl super::sdk_events::events::SdkEventsFilterAnalytics for ClickhouseClient {}
145147
impl super::api_event::events::ApiLogsFilterAnalytics for ClickhouseClient {}
146148
impl super::api_event::filters::ApiEventFilterAnalytics for ClickhouseClient {}
147149
impl super::api_event::metrics::ApiEventMetricAnalytics for ClickhouseClient {}
150+
impl super::outgoing_webhook_event::events::OutgoingWebhookLogsFilterAnalytics
151+
for ClickhouseClient
152+
{
153+
}
148154

149155
#[derive(Debug, serde::Serialize)]
150156
struct CkhQuery {
@@ -302,6 +308,18 @@ impl TryInto<ApiEventFilter> for serde_json::Value {
302308
}
303309
}
304310

311+
impl TryInto<OutgoingWebhookLogsResult> for serde_json::Value {
312+
type Error = Report<ParsingError>;
313+
314+
fn try_into(self) -> Result<OutgoingWebhookLogsResult, Self::Error> {
315+
serde_json::from_value(self)
316+
.into_report()
317+
.change_context(ParsingError::StructParseFailure(
318+
"Failed to parse OutgoingWebhookLogsResult in clickhouse results",
319+
))
320+
}
321+
}
322+
305323
impl ToSql<ClickhouseClient> for PrimitiveDateTime {
306324
fn to_sql(&self, _table_engine: &TableEngine) -> error_stack::Result<String, ParsingError> {
307325
let format =
@@ -326,6 +344,7 @@ impl ToSql<ClickhouseClient> for AnalyticsCollection {
326344
Self::SdkEvents => Ok("sdk_events_dist".to_string()),
327345
Self::ApiEvents => Ok("api_audit_log".to_string()),
328346
Self::PaymentIntent => Ok("payment_intents_dist".to_string()),
347+
Self::OutgoingWebhookEvent => Ok("outgoing_webhook_events_audit".to_string()),
329348
}
330349
}
331350
}

crates/analytics/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ mod query;
77
pub mod refunds;
88

99
pub mod api_event;
10+
pub mod outgoing_webhook_event;
1011
pub mod sdk_events;
1112
mod sqlx;
1213
mod types;
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
mod core;
2+
pub mod events;
3+
4+
pub trait OutgoingWebhookEventAnalytics: events::OutgoingWebhookLogsFilterAnalytics {}
5+
6+
pub use self::core::outgoing_webhook_events_core;
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
use api_models::analytics::outgoing_webhook_event::OutgoingWebhookLogsRequest;
2+
use common_utils::errors::ReportSwitchExt;
3+
use error_stack::{IntoReport, ResultExt};
4+
5+
use super::events::{get_outgoing_webhook_event, OutgoingWebhookLogsResult};
6+
use crate::{errors::AnalyticsResult, types::FiltersError, AnalyticsProvider};
7+
8+
pub async fn outgoing_webhook_events_core(
9+
pool: &AnalyticsProvider,
10+
req: OutgoingWebhookLogsRequest,
11+
merchant_id: String,
12+
) -> AnalyticsResult<Vec<OutgoingWebhookLogsResult>> {
13+
let data = match pool {
14+
AnalyticsProvider::Sqlx(_) => Err(FiltersError::NotImplemented(
15+
"Outgoing Webhook Events Logs not implemented for SQLX",
16+
))
17+
.into_report()
18+
.attach_printable("SQL Analytics is not implemented for Outgoing Webhook Events"),
19+
AnalyticsProvider::Clickhouse(ckh_pool)
20+
| AnalyticsProvider::CombinedSqlx(_, ckh_pool)
21+
| AnalyticsProvider::CombinedCkh(_, ckh_pool) => {
22+
get_outgoing_webhook_event(&merchant_id, req, ckh_pool).await
23+
}
24+
}
25+
.switch()?;
26+
Ok(data)
27+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
use api_models::analytics::{outgoing_webhook_event::OutgoingWebhookLogsRequest, Granularity};
2+
use common_utils::errors::ReportSwitchExt;
3+
use error_stack::ResultExt;
4+
use time::PrimitiveDateTime;
5+
6+
use crate::{
7+
query::{Aggregate, GroupByClause, QueryBuilder, ToSql, Window},
8+
types::{AnalyticsCollection, AnalyticsDataSource, FiltersError, FiltersResult, LoadRow},
9+
};
10+
pub trait OutgoingWebhookLogsFilterAnalytics: LoadRow<OutgoingWebhookLogsResult> {}
11+
12+
pub async fn get_outgoing_webhook_event<T>(
13+
merchant_id: &String,
14+
query_param: OutgoingWebhookLogsRequest,
15+
pool: &T,
16+
) -> FiltersResult<Vec<OutgoingWebhookLogsResult>>
17+
where
18+
T: AnalyticsDataSource + OutgoingWebhookLogsFilterAnalytics,
19+
PrimitiveDateTime: ToSql<T>,
20+
AnalyticsCollection: ToSql<T>,
21+
Granularity: GroupByClause<T>,
22+
Aggregate<&'static str>: ToSql<T>,
23+
Window<&'static str>: ToSql<T>,
24+
{
25+
let mut query_builder: QueryBuilder<T> =
26+
QueryBuilder::new(AnalyticsCollection::OutgoingWebhookEvent);
27+
query_builder.add_select_column("*").switch()?;
28+
29+
query_builder
30+
.add_filter_clause("merchant_id", merchant_id)
31+
.switch()?;
32+
query_builder
33+
.add_filter_clause("payment_id", query_param.payment_id)
34+
.switch()?;
35+
36+
if let Some(event_id) = query_param.event_id {
37+
query_builder
38+
.add_filter_clause("event_id", &event_id)
39+
.switch()?;
40+
}
41+
if let Some(refund_id) = query_param.refund_id {
42+
query_builder
43+
.add_filter_clause("refund_id", &refund_id)
44+
.switch()?;
45+
}
46+
if let Some(dispute_id) = query_param.dispute_id {
47+
query_builder
48+
.add_filter_clause("dispute_id", &dispute_id)
49+
.switch()?;
50+
}
51+
if let Some(mandate_id) = query_param.mandate_id {
52+
query_builder
53+
.add_filter_clause("mandate_id", &mandate_id)
54+
.switch()?;
55+
}
56+
if let Some(payment_method_id) = query_param.payment_method_id {
57+
query_builder
58+
.add_filter_clause("payment_method_id", &payment_method_id)
59+
.switch()?;
60+
}
61+
if let Some(attempt_id) = query_param.attempt_id {
62+
query_builder
63+
.add_filter_clause("attempt_id", &attempt_id)
64+
.switch()?;
65+
}
66+
//TODO!: update the execute_query function to return reports instead of plain errors...
67+
query_builder
68+
.execute_query::<OutgoingWebhookLogsResult, _>(pool)
69+
.await
70+
.change_context(FiltersError::QueryBuildingError)?
71+
.change_context(FiltersError::QueryExecutionFailure)
72+
}
73+
#[derive(Debug, serde::Serialize, serde::Deserialize)]
74+
pub struct OutgoingWebhookLogsResult {
75+
pub merchant_id: String,
76+
pub event_id: String,
77+
pub event_type: String,
78+
pub outgoing_webhook_event_type: String,
79+
pub payment_id: String,
80+
pub refund_id: Option<String>,
81+
pub attempt_id: Option<String>,
82+
pub dispute_id: Option<String>,
83+
pub payment_method_id: Option<String>,
84+
pub mandate_id: Option<String>,
85+
pub content: Option<String>,
86+
pub is_error: bool,
87+
pub error: Option<String>,
88+
#[serde(with = "common_utils::custom_serde::iso8601")]
89+
pub created_at: PrimitiveDateTime,
90+
}

crates/analytics/src/sqlx.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -429,6 +429,8 @@ impl ToSql<SqlxClient> for AnalyticsCollection {
429429
Self::ApiEvents => Err(error_stack::report!(ParsingError::UnknownError)
430430
.attach_printable("ApiEvents table is not implemented for Sqlx"))?,
431431
Self::PaymentIntent => Ok("payment_intent".to_string()),
432+
Self::OutgoingWebhookEvent => Err(error_stack::report!(ParsingError::UnknownError)
433+
.attach_printable("OutgoingWebhookEvents table is not implemented for Sqlx"))?,
432434
}
433435
}
434436
}

crates/analytics/src/types.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@ pub enum AnalyticsCollection {
2626
SdkEvents,
2727
ApiEvents,
2828
PaymentIntent,
29+
OutgoingWebhookEvent,
2930
}
3031

3132
#[allow(dead_code)]

crates/api_models/src/analytics.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use self::{
1212
pub use crate::payments::TimeRange;
1313

1414
pub mod api_event;
15+
pub mod outgoing_webhook_event;
1516
pub mod payments;
1617
pub mod refunds;
1718
pub mod sdk_events;
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#[derive(Clone, Debug, serde::Deserialize, serde::Serialize)]
2+
pub struct OutgoingWebhookLogsRequest {
3+
pub payment_id: String,
4+
pub event_id: Option<String>,
5+
pub refund_id: Option<String>,
6+
pub dispute_id: Option<String>,
7+
pub mandate_id: Option<String>,
8+
pub payment_method_id: Option<String>,
9+
pub attempt_id: Option<String>,
10+
}

crates/api_models/src/events.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,9 @@ use common_utils::{
1717

1818
use crate::{
1919
admin::*,
20-
analytics::{api_event::*, sdk_events::*, *},
20+
analytics::{
21+
api_event::*, outgoing_webhook_event::OutgoingWebhookLogsRequest, sdk_events::*, *,
22+
},
2123
api_keys::*,
2224
cards_info::*,
2325
disputes::*,
@@ -89,7 +91,8 @@ impl_misc_api_event_type!(
8991
ApiLogsRequest,
9092
GetApiEventMetricRequest,
9193
SdkEventsRequest,
92-
ReportRequest
94+
ReportRequest,
95+
OutgoingWebhookLogsRequest
9396
);
9497

9598
#[cfg(feature = "stripe")]

0 commit comments

Comments
 (0)