Skip to content

Commit

Permalink
feat(analytics): three_ds and authentication events in sdkevents (#4251)
Browse files Browse the repository at this point in the history
Co-authored-by: Akash Kamble <127744130+akash-c-k@users.noreply.github.com>
  • Loading branch information
vsrivatsa-edinburgh and akash-c-k committed Apr 2, 2024
1 parent a071463 commit 88b53b0
Show file tree
Hide file tree
Showing 13 changed files with 914 additions and 29 deletions.
2 changes: 2 additions & 0 deletions crates/analytics/src/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -388,6 +388,7 @@ impl_to_sql_for_to_string!(&DisputeDimensions, DisputeDimensions, DisputeStage);
#[derive(Debug)]
pub enum FilterTypes {
Equal,
NotEqual,
EqualBool,
In,
Gte,
Expand All @@ -402,6 +403,7 @@ pub fn filter_type_to_sql(l: &String, op: &FilterTypes, r: &String) -> String {
match op {
FilterTypes::EqualBool => format!("{l} = {r}"),
FilterTypes::Equal => format!("{l} = '{r}'"),
FilterTypes::NotEqual => format!("{l} != '{r}'"),
FilterTypes::In => format!("{l} IN ({r})"),
FilterTypes::Gte => format!("{l} >= '{r}'"),
FilterTypes::Gt => format!("{l} > {r}"),
Expand Down
16 changes: 14 additions & 2 deletions crates/analytics/src/sdk_events/accumulator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,19 @@ use super::metrics::SdkEventMetricRow;
#[derive(Debug, Default)]
pub struct SdkEventMetricsAccumulator {
pub payment_attempts: CountAccumulator,
pub payment_success: CountAccumulator,
pub payment_methods_call_count: CountAccumulator,
pub average_payment_time: AverageAccumulator,
pub sdk_initiated_count: CountAccumulator,
pub sdk_rendered_count: CountAccumulator,
pub payment_method_selected_count: CountAccumulator,
pub payment_data_filled_count: CountAccumulator,
pub three_ds_method_invoked_count: CountAccumulator,
pub three_ds_method_skipped_count: CountAccumulator,
pub three_ds_method_successful_count: CountAccumulator,
pub three_ds_method_unsuccessful_count: CountAccumulator,
pub authentication_unsuccessful_count: CountAccumulator,
pub three_ds_challenge_flow_count: CountAccumulator,
pub three_ds_frictionless_flow_count: CountAccumulator,
}

#[derive(Debug, Default)]
Expand Down Expand Up @@ -86,13 +92,19 @@ impl SdkEventMetricsAccumulator {
pub fn collect(self) -> SdkEventMetricsBucketValue {
SdkEventMetricsBucketValue {
payment_attempts: self.payment_attempts.collect(),
payment_success_count: self.payment_success.collect(),
payment_methods_call_count: self.payment_methods_call_count.collect(),
average_payment_time: self.average_payment_time.collect(),
sdk_initiated_count: self.sdk_initiated_count.collect(),
sdk_rendered_count: self.sdk_rendered_count.collect(),
payment_method_selected_count: self.payment_method_selected_count.collect(),
payment_data_filled_count: self.payment_data_filled_count.collect(),
three_ds_method_invoked_count: self.three_ds_method_invoked_count.collect(),
three_ds_method_skipped_count: self.three_ds_method_skipped_count.collect(),
three_ds_method_successful_count: self.three_ds_method_successful_count.collect(),
three_ds_method_unsuccessful_count: self.three_ds_method_unsuccessful_count.collect(),
authentication_unsuccessful_count: self.authentication_unsuccessful_count.collect(),
three_ds_challenge_flow_count: self.three_ds_challenge_flow_count.collect(),
three_ds_frictionless_flow_count: self.three_ds_frictionless_flow_count.collect(),
}
}
}
24 changes: 21 additions & 3 deletions crates/analytics/src/sdk_events/core.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,9 +88,6 @@ pub async fn get_metrics(
SdkEventMetrics::PaymentAttempts => {
metrics_builder.payment_attempts.add_metrics_bucket(&value)
}
SdkEventMetrics::PaymentSuccessCount => {
metrics_builder.payment_success.add_metrics_bucket(&value)
}
SdkEventMetrics::PaymentMethodsCallCount => metrics_builder
.payment_methods_call_count
.add_metrics_bucket(&value),
Expand All @@ -109,6 +106,27 @@ pub async fn get_metrics(
SdkEventMetrics::AveragePaymentTime => metrics_builder
.average_payment_time
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsMethodInvokedCount => metrics_builder
.three_ds_method_invoked_count
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsMethodSkippedCount => metrics_builder
.three_ds_method_skipped_count
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsMethodSuccessfulCount => metrics_builder
.three_ds_method_successful_count
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsMethodUnsuccessfulCount => metrics_builder
.three_ds_method_unsuccessful_count
.add_metrics_bucket(&value),
SdkEventMetrics::AuthenticationUnsuccessfulCount => metrics_builder
.authentication_unsuccessful_count
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsChallengeFlowCount => metrics_builder
.three_ds_challenge_flow_count
.add_metrics_bucket(&value),
SdkEventMetrics::ThreeDsFrictionlessFlowCount => metrics_builder
.three_ds_frictionless_flow_count
.add_metrics_bucket(&value),
}
}

Expand Down
112 changes: 98 additions & 14 deletions crates/analytics/src/sdk_events/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,23 +11,35 @@ use crate::{
types::{AnalyticsCollection, AnalyticsDataSource, LoadRow, MetricsResult},
};

mod authentication_unsuccessful_count;
mod average_payment_time;
mod payment_attempts;
mod payment_data_filled_count;
mod payment_method_selected_count;
mod payment_methods_call_count;
mod payment_success_count;
mod sdk_initiated_count;
mod sdk_rendered_count;
mod three_ds_challenge_flow_count;
mod three_ds_frictionless_flow_count;
mod three_ds_method_invoked_count;
mod three_ds_method_skipped_count;
mod three_ds_method_successful_count;
mod three_ds_method_unsuccessful_count;

use authentication_unsuccessful_count::AuthenticationUnsuccessfulCount;
use average_payment_time::AveragePaymentTime;
use payment_attempts::PaymentAttempts;
use payment_data_filled_count::PaymentDataFilledCount;
use payment_method_selected_count::PaymentMethodSelectedCount;
use payment_methods_call_count::PaymentMethodsCallCount;
use payment_success_count::PaymentSuccessCount;
use sdk_initiated_count::SdkInitiatedCount;
use sdk_rendered_count::SdkRenderedCount;
use three_ds_challenge_flow_count::ThreeDsChallengeFlowCount;
use three_ds_frictionless_flow_count::ThreeDsFrictionlessFlowCount;
use three_ds_method_invoked_count::ThreeDsMethodInvokedCount;
use three_ds_method_skipped_count::ThreeDsMethodSkippedCount;
use three_ds_method_successful_count::ThreeDsMethodSuccessfulCount;
use three_ds_method_unsuccessful_count::ThreeDsMethodUnsuccessfulCount;

#[derive(Debug, PartialEq, Eq, serde::Deserialize)]
pub struct SdkEventMetricRow {
Expand Down Expand Up @@ -92,18 +104,6 @@ where
)
.await
}
Self::PaymentSuccessCount => {
PaymentSuccessCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::PaymentMethodsCallCount => {
PaymentMethodsCallCount
.load_metrics(
Expand Down Expand Up @@ -176,6 +176,90 @@ where
)
.await
}
Self::ThreeDsMethodSkippedCount => {
ThreeDsMethodSkippedCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::ThreeDsMethodInvokedCount => {
ThreeDsMethodInvokedCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::ThreeDsMethodSuccessfulCount => {
ThreeDsMethodSuccessfulCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::ThreeDsMethodUnsuccessfulCount => {
ThreeDsMethodUnsuccessfulCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::AuthenticationUnsuccessfulCount => {
AuthenticationUnsuccessfulCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::ThreeDsChallengeFlowCount => {
ThreeDsChallengeFlowCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
Self::ThreeDsFrictionlessFlowCount => {
ThreeDsFrictionlessFlowCount
.load_metrics(
dimensions,
publishable_key,
filters,
granularity,
time_range,
pool,
)
.await
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
use api_models::analytics::{
sdk_events::{
SdkEventDimensions, SdkEventFilters, SdkEventMetricsBucketIdentifier, SdkEventNames,
},
Granularity, TimeRange,
};
use common_utils::errors::ReportSwitchExt;
use error_stack::ResultExt;
use time::PrimitiveDateTime;

use super::SdkEventMetricRow;
use crate::{
query::{Aggregate, GroupByClause, QueryBuilder, QueryFilter, ToSql, Window},
types::{AnalyticsCollection, AnalyticsDataSource, MetricsError, MetricsResult},
};

#[derive(Default)]
pub(super) struct AuthenticationUnsuccessfulCount;

#[async_trait::async_trait]
impl<T> super::SdkEventMetric<T> for AuthenticationUnsuccessfulCount
where
T: AnalyticsDataSource + super::SdkEventMetricAnalytics,
PrimitiveDateTime: ToSql<T>,
AnalyticsCollection: ToSql<T>,
Granularity: GroupByClause<T>,
Aggregate<&'static str>: ToSql<T>,
Window<&'static str>: ToSql<T>,
{
async fn load_metrics(
&self,
dimensions: &[SdkEventDimensions],
publishable_key: &str,
filters: &SdkEventFilters,
granularity: &Option<Granularity>,
time_range: &TimeRange,
pool: &T,
) -> MetricsResult<Vec<(SdkEventMetricsBucketIdentifier, SdkEventMetricRow)>> {
let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::SdkEvents);
let dimensions = dimensions.to_vec();

for dim in dimensions.iter() {
query_builder.add_select_column(dim).switch()?;
}

query_builder
.add_select_column(Aggregate::Count {
field: None,
alias: Some("count"),
})
.switch()?;

if let Some(granularity) = granularity.as_ref() {
query_builder
.add_granularity_in_mins(granularity)
.switch()?;
}

filters.set_filter_clause(&mut query_builder).switch()?;

query_builder
.add_filter_clause("merchant_id", publishable_key)
.switch()?;

query_builder
.add_filter_clause("event_name", SdkEventNames::AuthenticationCall)
.switch()?;

query_builder
.add_filter_clause("log_type", "ERROR")
.switch()?;

query_builder
.add_filter_clause("category", "USER_EVENT")
.switch()?;

time_range
.set_filter_clause(&mut query_builder)
.attach_printable("Error filtering time range")
.switch()?;

for dim in dimensions.iter() {
query_builder
.add_group_by_clause(dim)
.attach_printable("Error grouping by dimensions")
.switch()?;
}

if let Some(_granularity) = granularity.as_ref() {
query_builder
.add_group_by_clause("time_bucket")
.attach_printable("Error adding granularity")
.switch()?;
}

query_builder
.execute_query::<SdkEventMetricRow, _>(pool)
.await
.change_context(MetricsError::QueryBuildingError)?
.change_context(MetricsError::QueryExecutionFailure)?
.into_iter()
.map(|i| {
Ok((
SdkEventMetricsBucketIdentifier::new(
i.payment_method.clone(),
i.platform.clone(),
i.browser_name.clone(),
i.source.clone(),
i.component.clone(),
i.payment_experience.clone(),
i.time_bucket.clone(),
),
i,
))
})
.collect::<error_stack::Result<
Vec<(SdkEventMetricsBucketIdentifier, SdkEventMetricRow)>,
crate::query::PostProcessingError,
>>()
.change_context(MetricsError::PostProcessingFailure)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ where
.switch()?;

query_builder
.add_filter_clause("event_name", SdkEventNames::StripeElementsCalled)
.add_filter_clause("event_name", SdkEventNames::OrcaElementsCalled)
.switch()?;

time_range
Expand Down
Loading

0 comments on commit 88b53b0

Please sign in to comment.