Skip to content

Commit

Permalink
add requests success rate
Browse files Browse the repository at this point in the history
  • Loading branch information
“Giems” committed Feb 26, 2024
1 parent 4cafaea commit 51a586a
Show file tree
Hide file tree
Showing 6 changed files with 356 additions and 87 deletions.
4 changes: 1 addition & 3 deletions database/migrations/000000000004_request_status.sql
Original file line number Diff line number Diff line change
@@ -1,8 +1,6 @@
CREATE TYPE request_status_enum AS ENUM (
'Pending',
'Completed',
'Failed',
'Rejected',
'TimedOut',
'Unknown'
'TimedOut'
);
63 changes: 0 additions & 63 deletions database/migrations/000000000007_requests_count.sql

This file was deleted.

71 changes: 71 additions & 0 deletions database/migrations/000000000007_requests_stats.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
----------------- Hourly requests stats per app -----------------
--- View
CREATE MATERIALIZED VIEW hourly_requests_stats
WITH (timescaledb.continuous)
AS SELECT
app_id,
time_bucket('1 hour'::interval, creation_timestamp) AS hourly_bucket,
COUNT(*) AS hourly_request_count,
COUNT(*) FILTER (WHERE request_status = 'Completed')::FLOAT / NULLIF(COUNT(*) FILTER (WHERE request_status IN ('Completed', 'Rejected', 'TimedOut')), 0) AS success_rate
FROM requests
GROUP BY app_id, hourly_bucket
WITH NO DATA;

--- Refresh policy
SELECT add_continuous_aggregate_policy('hourly_requests_stats',
start_offset => INTERVAL '3 h',
end_offset => INTERVAL '1 h',
schedule_interval => INTERVAL '1 h');

--- Real time aggregation
ALTER MATERIALIZED VIEW hourly_requests_stats set (timescaledb.materialized_only = false);



----------------- Daily requests stats per app -----------------
--- View
CREATE MATERIALIZED VIEW daily_requests_stats
WITH (timescaledb.continuous)
AS SELECT
app_id,
time_bucket('1 day'::interval, hourly_bucket) AS daily_bucket,
SUM(hourly_request_count)::BIGINT AS daily_request_count,
SUM(hourly_request_count * success_rate)::FLOAT / SUM(hourly_request_count) AS success_rate
FROM hourly_requests_stats
GROUP BY app_id, daily_bucket
WITH NO DATA;

--- Refresh policy
SELECT add_continuous_aggregate_policy('daily_requests_stats',
start_offset => INTERVAL '3 d',
end_offset => INTERVAL '1 h',
schedule_interval => INTERVAL '12 h');

--- Real time aggregation
ALTER MATERIALIZED VIEW daily_requests_stats set (timescaledb.materialized_only = false);



----------------- Monthly requests per app -----------------
--- View
CREATE MATERIALIZED VIEW monthly_requests_stats
WITH (timescaledb.continuous)
AS SELECT
app_id,
time_bucket('1 month'::interval, daily_bucket) AS monthly_bucket,
SUM(daily_request_count)::BIGINT AS monthly_request_count,
SUM(daily_request_count * success_rate)::FLOAT / SUM(daily_request_count) AS success_rate
FROM daily_requests_stats
GROUP BY app_id, monthly_bucket
WITH NO DATA;


--- Refresh policy
SELECT add_continuous_aggregate_policy('monthly_requests_stats',
start_offset => INTERVAL '3 month',
end_offset => INTERVAL '1 h',
schedule_interval => INTERVAL '1 month');

--- Real time aggregation
ALTER MATERIALIZED VIEW monthly_requests_stats set (timescaledb.materialized_only = false);

8 changes: 8 additions & 0 deletions database/src/structs/filter_requests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,14 @@ pub struct AggregatedRequestCount {
pub request_count: i64,
}

#[derive(Debug, sqlx::FromRow)]
pub struct RequestsStats {
pub app_id: String,
pub bucket: DateTime<Utc>,
pub request_count: i64,
pub success_rate: Option<f64>,
}

#[derive(Debug, sqlx::FromRow)]
pub struct SessionsStats {
pub app_id: String,
Expand Down
44 changes: 29 additions & 15 deletions database/src/tables/registered_app/select.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use super::table_struct::{RegisteredApp, REGISTERED_APPS_TABLE_NAME};
use crate::structs::filter_requests::{AggregatedRequestCount, SessionsStats};
use crate::structs::filter_requests::{RequestsStats, SessionsStats};
use crate::structs::time_filters::TimeFilter;
use crate::tables::requests::table_struct::REQUESTS_TABLE_NAME;
use crate::{db::Db, tables::requests::table_struct::Request};
Expand Down Expand Up @@ -37,39 +37,53 @@ impl Db {
.await;
}

pub async fn get_aggregated_requests_by_app_id(
pub async fn get_requests_stats_by_app_id(
&self,
app_id: &str,
filter: TimeFilter,
) -> Result<Vec<AggregatedRequestCount>, Error> {
) -> Result<Vec<RequestsStats>, Error> {
let start_date = filter.to_date();
let bucket_size = filter.bucket_size();

// Correctly selecting the view based on the bucket_size
let (view_name, bucket, request_count) = match bucket_size {
"1 hour" => (
"hourly_requests_per_app",
"hourly_bucket",
"hourly_request_count",
),
"1 day" => (
"daily_requests_per_app",
"daily_bucket",
"daily_request_count",
),
"1 hour" => {
let prefix = "hourly";
(
format!("{}_requests_stats", prefix),
format!("{}_bucket", prefix),
format!("{}_request_count", prefix),
)
}
"1 day" => {
let prefix = "daily";
(
format!("{}_requests_stats", prefix),
format!("{}_bucket", prefix),
format!("{}_request_count", prefix),
)
}
"1 month" => {
let prefix = "monthly";
(
format!("{}_requests_stats", prefix),
format!("{}_bucket", prefix),
format!("{}_request_count", prefix),
)
}
// for now return WorkerCrashed but later create custom error
_ => return Err(Error::WorkerCrashed),
};

let query = format!(
"SELECT app_id, {} as bucket, {} as request_count
"SELECT app_id, {} as bucket, {} as request_count, success_rate
FROM {}
WHERE app_id = $1 AND {} >= $2
ORDER BY {} DESC",
bucket, request_count, view_name, bucket, bucket
);

sqlx::query_as::<_, AggregatedRequestCount>(&query)
sqlx::query_as::<_, RequestsStats>(&query)
.bind(app_id)
.bind(start_date)
.fetch_all(&self.connection_pool)
Expand Down
Loading

0 comments on commit 51a586a

Please sign in to comment.