Skip to content

Commit 416517f

Browse files
chore: refactor report queries, add event rate limit
Signed-off-by: Henry <mail@henrygressmann.de>
1 parent 8916087 commit 416517f

11 files changed

Lines changed: 475 additions & 245 deletions

File tree

Cargo.lock

Lines changed: 151 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,10 @@ path="src/lib.rs"
1414
name="liwan"
1515
path="src/main.rs"
1616

17+
[[bench]]
18+
name="reports"
19+
harness=false
20+
1721
[dependencies]
1822
# async/concurrency
1923
arc-swap="1.9"
@@ -80,7 +84,7 @@ url="2.5"
8084
ua-parser="0.2"
8185
rust-embed={version="8.11", features=["mime-guess"]}
8286
reqwest={version="0.13", default-features=false, features=["json", "stream", "charset", "rustls"]}
83-
ipnet="2.11"
87+
ipnet="2.12"
8488

8589
# database
8690
duckdb={version="1.10501", features=["chrono", "bundled", "r2d2"]}
@@ -96,6 +100,7 @@ figment={version="*", features=["test"]}
96100
cookie={version="*", default-features=false}
97101
tower={version="*", features=["util"]}
98102
axum-test={version="20"}
103+
criterion={version="0.5", default-features=false}
99104

100105
[features]
101106
default=["geoip"]

benches/reports.rs

Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
use chrono::{Days, Utc};
2+
use criterion::{BenchmarkId, Criterion, criterion_group, criterion_main};
3+
use liwan::app::Liwan;
4+
use liwan::app::reports::{self, DateRange, Dimension, Metric};
5+
use liwan::config::Config;
6+
use std::time::Duration;
7+
8+
fn configure_group(group: &mut criterion::BenchmarkGroup<'_, criterion::measurement::WallTime>) {
9+
group.warm_up_time(Duration::from_secs(2));
10+
group.measurement_time(Duration::from_secs(5));
11+
group.sample_size(20);
12+
}
13+
14+
fn benchmark_reports(c: &mut Criterion) {
15+
let config = Config::load(None).expect("failed to load config");
16+
let app = Liwan::try_new(config).expect("failed to initialize app");
17+
18+
let project = app
19+
.projects
20+
.all()
21+
.expect("failed to load projects")
22+
.into_iter()
23+
.next()
24+
.expect("no projects found; seed the database first");
25+
26+
let entities = app.projects.entity_ids(&project.id).expect("failed to resolve entities for benchmark project");
27+
assert!(!entities.is_empty(), "project has no entities; seed the database first");
28+
29+
let range = DateRange {
30+
start: Utc::now().checked_sub_days(Days::new(365)).expect("failed to build range start"),
31+
end: Utc::now(),
32+
};
33+
34+
let conn = app.events_conn().expect("failed to get events connection");
35+
36+
{
37+
let mut group = c.benchmark_group("report_meta");
38+
configure_group(&mut group);
39+
group.bench_function("earliest_timestamp", |b| {
40+
b.iter(|| reports::earliest_timestamp(&conn, &entities).expect("earliest_timestamp failed"));
41+
});
42+
group.bench_function("online_users", |b| {
43+
b.iter(|| reports::online_users(&conn, &entities).expect("online_users failed"));
44+
});
45+
group.finish();
46+
}
47+
48+
{
49+
let mut group = c.benchmark_group("overall_report");
50+
configure_group(&mut group);
51+
for metric in [Metric::Views, Metric::UniqueVisitors, Metric::BounceRate, Metric::AvgTimeOnSite] {
52+
group.bench_with_input(BenchmarkId::new("metric", format!("{metric:?}")), &metric, |b, metric| {
53+
b.iter(|| {
54+
reports::overall_report(&conn, &entities, "pageview", &range, 365, &[], metric)
55+
.expect("overall_report failed")
56+
});
57+
});
58+
}
59+
group.finish();
60+
}
61+
62+
{
63+
let mut group = c.benchmark_group("overall_stats");
64+
configure_group(&mut group);
65+
group.bench_function("all_metrics", |b| {
66+
b.iter(|| reports::overall_stats(&conn, &entities, "pageview", &range, &[]).expect("overall_stats failed"));
67+
});
68+
group.finish();
69+
}
70+
71+
{
72+
let mut group = c.benchmark_group("dimension_report");
73+
configure_group(&mut group);
74+
let dimension = Dimension::Url;
75+
for metric in [Metric::Views, Metric::UniqueVisitors, Metric::BounceRate, Metric::AvgTimeOnSite] {
76+
group.bench_with_input(
77+
BenchmarkId::new("dim_metric", format!("{dimension:?}/{metric:?}")),
78+
&metric,
79+
|b, metric| {
80+
b.iter(|| {
81+
reports::dimension_report(&conn, &entities, "pageview", &range, &dimension, &[], metric)
82+
.expect("dimension_report failed")
83+
});
84+
},
85+
);
86+
}
87+
group.finish();
88+
}
89+
}
90+
91+
criterion_group!(benches, benchmark_reports);
92+
criterion_main!(benches);

0 commit comments

Comments
 (0)