Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(analytics): authentication analytics #4429

Merged
merged 23 commits into from May 10, 2024

Conversation

vsrivatsa-juspay
Copy link
Contributor

@vsrivatsa-juspay vsrivatsa-juspay commented Apr 22, 2024

Type of Change

  • Bugfix
  • New feature
  • Enhancement
  • Refactoring
  • Dependency updates
  • Documentation
  • CI/CD

Description

Authentication Analytics - with the following metrics:

  1. AuthenticationAttemptCount
  2. AuthenticationSuccessCount
  3. ChallengeAttemptCount
  4. ChallengeFlowCount
  5. ChallengeSuccessCount
  6. FrictionlessFlowCount
  7. ThreeDsSdkCount

#4252

Additional Changes

  • This PR modifies the API contract
  • This PR modifies the database schema
  • This PR modifies application configuration/environment variables

Motivation and Context

How did you test it?

curl --location 'localhost:8080/analytics/v1/metrics/auth_events' \ --header 'Content-Type: application/json' \ --header 'Accept: application/json' \ --header 'Authorization: Bearer {token}' \ --data '[ { "timeRange": { "startTime": "2024-01-13T18:30:00Z", "endTime": "2024-04-30T18:30:00Z" }, "metrics": [ "three_ds_sdk_count", "authentication_attempt_count", "authentication_success_count", "challenge_flow_count", "frictionless_flow_count", "challenge_attempt_count", "challenge_success_count" ] } ]'

{
    "queryData": [
        {
            "three_ds_sdk_count": 3,
            "authentication_attempt_count": 3,
            "authentication_success_count": 3,
            "challenge_flow_count": 2,
            "frictionless_flow_count": 1,
            "challenge_attempt_count": 2,
            "challenge_success_count": 2,
            "time_bucket": "2024-01-09T00:00:00Z"
        }
    ],
    "metaData": [
        {
            "current_time_range": {
                "start_time": "2024-01-13T18:30:00.000Z",
                "end_time": "2024-04-30T18:30:00.000Z"
            }
        }
    ]
}

Checklist

  • I formatted the code cargo +nightly fmt --all
  • I addressed lints thrown by cargo clippy
  • I reviewed the submitted code
  • I added unit tests for my changes where possible
  • I added a CHANGELOG entry if applicable

@vsrivatsa-juspay vsrivatsa-juspay requested review from a team as code owners April 22, 2024 14:46
@vsrivatsa-juspay vsrivatsa-juspay changed the title feat: authentication analytics feat(analytics): authentication analytics Apr 23, 2024
@vsrivatsa-juspay vsrivatsa-juspay self-assigned this Apr 23, 2024
@vsrivatsa-juspay vsrivatsa-juspay added low-risk label to track PRs which might have less impact on hyperswitch after merge A-Analytics S-waiting-on-review Status: This PR has been implemented and needs to be reviewed labels Apr 23, 2024
@vsrivatsa-juspay vsrivatsa-juspay linked an issue Apr 23, 2024 that may be closed by this pull request
2 tasks
ivor-juspay
ivor-juspay previously approved these changes Apr 24, 2024
Copy link
Member

@lsampras lsampras left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Have some doubts understanding the implementation here

Comment on lines 515 to 516
Self::AuthEvents => Err(error_stack::report!(ParsingError::UnknownError)
.attach_printable("ApiEvents table is not implemented for Sqlx"))?,
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
Self::AuthEvents => Err(error_stack::report!(ParsingError::UnknownError)
.attach_printable("ApiEvents table is not implemented for Sqlx"))?,
Self::AuthEvents => Ok("authentication".to_string()),

can use the authentication table

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Currently the metrics are not from this table, but a combination of 3 clickhouse-only tables

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can you share some example clickhouse sql queries that we expect to run for analytics?

crates/analytics/src/query.rs Outdated Show resolved Hide resolved
Comment on lines 29 to 39
pub struct AuthEventMetricRow {
pub total: Option<bigdecimal::BigDecimal>,
pub count: Option<i64>,
pub time_bucket: Option<String>,
pub payment_method: Option<String>,
pub platform: Option<String>,
pub browser_name: Option<String>,
pub source: Option<String>,
pub component: Option<String>,
pub payment_experience: Option<String>,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is this row backed by?
the fields here seem similar to SDK events?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Forgot to update this

.transpose()
.change_context(AnalyticsError::UnknownError)?
{
logger::info!("Logging Result {:?}", data);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

do we need this logger?

if we do add more context here as to which metric was this data for etc.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removed the logger

Comment on lines 23 to 27
#[derive(Debug, Default)]
pub struct AverageAccumulator {
pub total: u32,
pub count: u32,
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needed?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not needed, right

}

impl AuthEventMetricsAccumulator {
#[allow(dead_code)]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

can we remove this?

granularity: &Option<Granularity>,
time_range: &TimeRange,
pool: &T,
) -> MetricsResult<Vec<(SdkEventMetricsBucketIdentifier, SdkEventMetricRow)>> {
) -> MetricsResult<Vec<(AuthEventMetricsBucketIdentifier, AuthEventMetricRow)>> {
let mut query_builder: QueryBuilder<T> = QueryBuilder::new(AnalyticsCollection::SdkEvents);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are querying the SdkEvents table but deserializing the results to AuthEventMetricRow...
I'd prefer deserializing to SdkEventMetricRow & then having an Into::into implementation to get AuthEventMetricRow...

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since Authentication Analytics currently does not support filters/dimensions, the AuthEventMetricRow would only have time_bucket and count, so we can retain this

pool: &T,
) -> MetricsResult<Vec<(AuthEventMetricsBucketIdentifier, AuthEventMetricRow)>> {
let mut query_builder: QueryBuilder<T> =
QueryBuilder::new(AnalyticsCollection::ConnectorEvents);
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we are querying for connectorevents & deserializing to authevents? 😕

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AuthEventMetricRow would only have time_bucket and count, so we can retain this

.switch()?;

query_builder
.add_filter_clause("category", "USER_EVENT")
.add_filter_clause("visitParamExtractRaw(response, 'transStatus')", "\"Y\"")
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why not extract this out as a separate field in the mv?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The usecase is too specific to authentication analytics.
Since the other filters anyway restrict the data scanned, this should be fine

@@ -360,7 +373,7 @@ impl ToSql<ClickhouseClient> for AnalyticsCollection {
Self::Payment => Ok("payment_attempts".to_string()),
Self::Refund => Ok("refunds".to_string()),
Self::SdkEvents => Ok("sdk_events_audit".to_string()),
Self::ApiEvents => Ok("api_events_audit".to_string()),
Self::ApiEvents | Self::AuthEvents => Ok("api_events_audit".to_string()),
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

😕

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will update this to authentication table in future
😓

@lsampras
Copy link
Member

@vsrivatsa-juspay Is there going to be a new clickhouse table for this?
can you add a script of the clickhouse table creation if exists?

Co-authored-by: Sampras Lopes <lsampras@pm.me>
@vsrivatsa-juspay
Copy link
Contributor Author

@vsrivatsa-juspay Is there going to be a new clickhouse table for this? can you add a script of the clickhouse table creation if exists?

In a future version. Will add the table scripts as well as refactor the queries as well

ivor-juspay
ivor-juspay previously approved these changes May 6, 2024
@@ -512,6 +512,8 @@ impl ToSql<SqlxClient> for AnalyticsCollection {
Self::Refund => Ok("refund".to_string()),
Self::SdkEvents => Err(error_stack::report!(ParsingError::UnknownError)
.attach_printable("SdkEvents table is not implemented for Sqlx"))?,
Self::AuthEvents => Err(error_stack::report!(ParsingError::UnknownError)
.attach_printable("ApiEvents table is not implemented for Sqlx"))?,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

authentication table right ?

@@ -360,7 +373,7 @@ impl ToSql<ClickhouseClient> for AnalyticsCollection {
Self::Payment => Ok("payment_attempts".to_string()),
Self::Refund => Ok("refunds".to_string()),
Self::SdkEvents => Ok("sdk_events_audit".to_string()),
Self::ApiEvents => Ok("api_events_audit".to_string()),
Self::ApiEvents | Self::AuthEvents => Ok("api_events_audit".to_string()),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

api_events_audit is a ID based table , cannot use for time based filtering

If want can use api_events

@Gnanasundari24 Gnanasundari24 added this pull request to the merge queue May 10, 2024
Merged via the queue into main with commit 24d1542 May 10, 2024
11 of 15 checks passed
@Gnanasundari24 Gnanasundari24 deleted the feat/authentication_analytics_2 branch May 10, 2024 10:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
A-Analytics low-risk label to track PRs which might have less impact on hyperswitch after merge S-waiting-on-review Status: This PR has been implemented and needs to be reviewed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

[FEATURE] Authentication Analytics
5 participants