1
1
use std:: collections:: HashMap ;
2
2
3
3
use api_models:: analytics:: {
4
- auth_events:: { AuthEventMetrics , AuthEventMetricsBucketIdentifier , MetricsBucketResponse } ,
5
- AnalyticsMetadata , GetAuthEventMetricRequest , MetricsResponse ,
4
+ auth_events:: {
5
+ AuthEventDimensions , AuthEventMetrics , AuthEventMetricsBucketIdentifier ,
6
+ MetricsBucketResponse ,
7
+ } ,
8
+ AuthEventFilterValue , AuthEventFiltersResponse , AuthEventMetricsResponse ,
9
+ AuthEventsAnalyticsMetadata , GetAuthEventFilterRequest , GetAuthEventMetricRequest ,
6
10
} ;
7
- use error_stack:: ResultExt ;
11
+ use error_stack:: { report , ResultExt } ;
8
12
use router_env:: { instrument, tracing} ;
9
13
10
- use super :: AuthEventMetricsAccumulator ;
14
+ use super :: {
15
+ filters:: { get_auth_events_filter_for_dimension, AuthEventFilterRow } ,
16
+ AuthEventMetricsAccumulator ,
17
+ } ;
11
18
use crate :: {
12
19
auth_events:: AuthEventMetricAccumulator ,
13
20
errors:: { AnalyticsError , AnalyticsResult } ,
@@ -19,7 +26,7 @@ pub async fn get_metrics(
19
26
pool : & AnalyticsProvider ,
20
27
merchant_id : & common_utils:: id_type:: MerchantId ,
21
28
req : GetAuthEventMetricRequest ,
22
- ) -> AnalyticsResult < MetricsResponse < MetricsBucketResponse > > {
29
+ ) -> AnalyticsResult < AuthEventMetricsResponse < MetricsBucketResponse > > {
23
30
let mut metrics_accumulator: HashMap <
24
31
AuthEventMetricsBucketIdentifier ,
25
32
AuthEventMetricsAccumulator ,
@@ -34,7 +41,9 @@ pub async fn get_metrics(
34
41
let data = pool
35
42
. get_auth_event_metrics (
36
43
& metric_type,
44
+ & req. group_by_names . clone ( ) ,
37
45
& merchant_id_scoped,
46
+ & req. filters ,
38
47
req. time_series . map ( |t| t. granularity ) ,
39
48
& req. time_range ,
40
49
)
@@ -77,22 +86,94 @@ pub async fn get_metrics(
77
86
AuthEventMetrics :: FrictionlessSuccessCount => metrics_builder
78
87
. frictionless_success_count
79
88
. add_metrics_bucket ( & value) ,
89
+ AuthEventMetrics :: AuthenticationErrorMessage => metrics_builder
90
+ . authentication_error_message
91
+ . add_metrics_bucket ( & value) ,
92
+ AuthEventMetrics :: AuthenticationFunnel => metrics_builder
93
+ . authentication_funnel
94
+ . add_metrics_bucket ( & value) ,
80
95
}
81
96
}
82
97
}
83
98
99
+ let mut total_error_message_count = 0 ;
84
100
let query_data: Vec < MetricsBucketResponse > = metrics_accumulator
85
101
. into_iter ( )
86
- . map ( |( id, val) | MetricsBucketResponse {
87
- values : val. collect ( ) ,
88
- dimensions : id,
102
+ . map ( |( id, val) | {
103
+ let collected_values = val. collect ( ) ;
104
+ if let Some ( count) = collected_values. error_message_count {
105
+ total_error_message_count += count;
106
+ }
107
+ MetricsBucketResponse {
108
+ values : collected_values,
109
+ dimensions : id,
110
+ }
89
111
} )
90
112
. collect ( ) ;
91
-
92
- Ok ( MetricsResponse {
113
+ Ok ( AuthEventMetricsResponse {
93
114
query_data,
94
- meta_data : [ AnalyticsMetadata {
95
- current_time_range : req . time_range ,
115
+ meta_data : [ AuthEventsAnalyticsMetadata {
116
+ total_error_message_count : Some ( total_error_message_count ) ,
96
117
} ] ,
97
118
} )
98
119
}
120
+
121
+ pub async fn get_filters (
122
+ pool : & AnalyticsProvider ,
123
+ req : GetAuthEventFilterRequest ,
124
+ merchant_id : & common_utils:: id_type:: MerchantId ,
125
+ ) -> AnalyticsResult < AuthEventFiltersResponse > {
126
+ let mut res = AuthEventFiltersResponse :: default ( ) ;
127
+ for dim in req. group_by_names {
128
+ let values = match pool {
129
+ AnalyticsProvider :: Sqlx ( _pool) => {
130
+ Err ( report ! ( AnalyticsError :: UnknownError ) )
131
+ }
132
+ AnalyticsProvider :: Clickhouse ( pool) => {
133
+ get_auth_events_filter_for_dimension ( dim, merchant_id, & req. time_range , pool)
134
+ . await
135
+ . map_err ( |e| e. change_context ( AnalyticsError :: UnknownError ) )
136
+ }
137
+ AnalyticsProvider :: CombinedCkh ( sqlx_pool, ckh_pool) | AnalyticsProvider :: CombinedSqlx ( sqlx_pool, ckh_pool) => {
138
+ let ckh_result = get_auth_events_filter_for_dimension (
139
+ dim,
140
+ merchant_id,
141
+ & req. time_range ,
142
+ ckh_pool,
143
+ )
144
+ . await
145
+ . map_err ( |e| e. change_context ( AnalyticsError :: UnknownError ) ) ;
146
+ let sqlx_result = get_auth_events_filter_for_dimension (
147
+ dim,
148
+ merchant_id,
149
+ & req. time_range ,
150
+ sqlx_pool,
151
+ )
152
+ . await
153
+ . map_err ( |e| e. change_context ( AnalyticsError :: UnknownError ) ) ;
154
+ match ( & sqlx_result, & ckh_result) {
155
+ ( Ok ( ref sqlx_res) , Ok ( ref ckh_res) ) if sqlx_res != ckh_res => {
156
+ router_env:: logger:: error!( clickhouse_result=?ckh_res, postgres_result=?sqlx_res, "Mismatch between clickhouse & postgres refunds analytics filters" )
157
+ } ,
158
+ _ => { }
159
+ } ;
160
+ ckh_result
161
+ }
162
+ }
163
+ . change_context ( AnalyticsError :: UnknownError ) ?
164
+ . into_iter ( )
165
+ . filter_map ( |fil : AuthEventFilterRow | match dim {
166
+ AuthEventDimensions :: AuthenticationStatus => fil. authentication_status . map ( |i| i. as_ref ( ) . to_string ( ) ) ,
167
+ AuthEventDimensions :: TransactionStatus => fil. trans_status . map ( |i| i. as_ref ( ) . to_string ( ) ) ,
168
+ AuthEventDimensions :: ErrorMessage => fil. error_message ,
169
+ AuthEventDimensions :: AuthenticationConnector => fil. authentication_connector . map ( |i| i. as_ref ( ) . to_string ( ) ) ,
170
+ AuthEventDimensions :: MessageVersion => fil. message_version ,
171
+ } )
172
+ . collect :: < Vec < String > > ( ) ;
173
+ res. query_data . push ( AuthEventFilterValue {
174
+ dimension : dim,
175
+ values,
176
+ } )
177
+ }
178
+ Ok ( res)
179
+ }
0 commit comments