Skip to content

Commit f0596c2

Browse files
committed
feat(fortuna): add prometheus metrics for history query latency
1 parent a334a22 commit f0596c2

File tree

6 files changed

+131
-26
lines changed

6 files changed

+131
-26
lines changed

apps/fortuna/Cargo.lock

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

apps/fortuna/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ ethabi = "18.0.0"
1919
ethers = { version = "2.0.14", features = ["ws"] }
2020
futures = { version = "0.3.28" }
2121
hex = "0.4.3"
22-
prometheus-client = { version = "0.21.2" }
22+
prometheus-client = { version = "0.23.1" }
2323
pythnet-sdk = { path = "../../pythnet/pythnet_sdk", features = ["strum"] }
2424
rand = "0.8.5"
2525
reqwest = { version = "0.11.22", features = ["json", "blocking"] }

apps/fortuna/src/api.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ pub struct ApiState {
6161

6262
/// Prometheus metrics
6363
pub metrics: Arc<ApiMetrics>,
64+
65+
pub explorer_metrics: Arc<ExplorerMetrics>,
6466
}
6567

6668
impl ApiState {
@@ -73,6 +75,8 @@ impl ApiState {
7375
http_requests: Family::default(),
7476
};
7577

78+
let explorer_metrics = Arc::new(ExplorerMetrics::new(metrics_registry.clone()).await);
79+
7680
let http_requests = metrics.http_requests.clone();
7781
metrics_registry.write().await.register(
7882
"http_requests",
@@ -83,6 +87,7 @@ impl ApiState {
8387
ApiState {
8488
chains,
8589
metrics: Arc::new(metrics),
90+
explorer_metrics,
8691
history,
8792
metrics_registry,
8893
}

apps/fortuna/src/api/explorer.rs

Lines changed: 108 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,100 @@
11
use {
22
crate::{
33
api::{ApiBlockChainState, NetworkId, RestError, StateTag},
4-
history::RequestStatus,
4+
history::{RequestQueryBuilder, RequestStatus, SearchField},
55
},
66
axum::{
77
extract::{Query, State},
88
Json,
99
},
1010
chrono::{DateTime, Utc},
11+
prometheus_client::{
12+
encoding::{EncodeLabelSet, EncodeLabelValue},
13+
metrics::{family::Family, histogram::Histogram},
14+
registry::Registry,
15+
},
16+
std::sync::Arc,
17+
tokio::{sync::RwLock, time::Instant},
1118
utoipa::IntoParams,
1219
};
1320

14-
#[derive(Debug, serde::Serialize, serde::Deserialize, IntoParams)]
21+
#[derive(Debug)]
22+
pub struct ExplorerMetrics {
23+
results_latency: Family<QueryTags, Histogram>,
24+
count_latency: Family<QueryTags, Histogram>,
25+
}
26+
27+
#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelSet)]
28+
pub struct QueryTags {
29+
search_type: Option<SearchType>,
30+
has_network_id_filter: bool,
31+
has_state_filter: bool,
32+
limit: i64,
33+
}
34+
35+
impl<'a> From<RequestQueryBuilder<'a>> for QueryTags {
36+
fn from(builder: RequestQueryBuilder<'a>) -> Self {
37+
QueryTags {
38+
search_type: builder.search.map(|val| match val {
39+
SearchField::TxHash(_) => SearchType::TxHash,
40+
SearchField::Sender(_) => SearchType::Sender,
41+
SearchField::SequenceNumber(_) => SearchType::SequenceNumber,
42+
}),
43+
has_network_id_filter: builder.network_id.is_some(),
44+
has_state_filter: builder.state.is_some(),
45+
limit: builder.limit,
46+
}
47+
}
48+
}
49+
50+
#[derive(Debug, Clone, PartialEq, Eq, Hash, EncodeLabelValue)]
51+
enum SearchType {
52+
TxHash,
53+
Sender,
54+
SequenceNumber,
55+
}
56+
57+
impl ExplorerMetrics {
58+
pub async fn new(metrics_registry: Arc<RwLock<Registry>>) -> Self {
59+
let mut guard = metrics_registry.write().await;
60+
let sub_registry = guard.sub_registry_with_prefix("explorer");
61+
62+
let results_latency = Family::<QueryTags, Histogram>::new_with_constructor(|| {
63+
Histogram::new(
64+
[
65+
0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0,
66+
]
67+
.into_iter(),
68+
)
69+
});
70+
sub_registry.register(
71+
"results_latency",
72+
"The latency of requests to the database to collect the limited results.",
73+
results_latency.clone(),
74+
);
75+
76+
let count_latency = Family::<QueryTags, Histogram>::new_with_constructor(|| {
77+
Histogram::new(
78+
[
79+
0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 2.0, 5.0, 10.0, 20.0,
80+
]
81+
.into_iter(),
82+
)
83+
});
84+
sub_registry.register(
85+
"count_latency",
86+
"The latency of requests to the database to collect the total matching result count.",
87+
count_latency.clone(),
88+
);
89+
90+
Self {
91+
results_latency,
92+
count_latency,
93+
}
94+
}
95+
}
96+
97+
#[derive(Debug, Clone, serde::Serialize, serde::Deserialize, IntoParams)]
1598
#[into_params(parameter_in=Query)]
1699
pub struct ExplorerQueryParams {
17100
/// Only return logs that are newer or equal to this timestamp. Timestamp is in ISO 8601 format with UTC timezone.
@@ -96,7 +179,13 @@ pub async fn explorer(
96179
query = query.max_timestamp(max_timestamp);
97180
}
98181

99-
let (requests, total_results) = tokio::join!(query.execute(), query.count_results());
182+
let results_latency = &state.explorer_metrics.results_latency;
183+
let count_latency = &state.explorer_metrics.count_latency;
184+
let query_tags = &query.clone().into();
185+
let (requests, total_results) = tokio::join!(
186+
measure_latency(results_latency, query_tags, query.execute()),
187+
measure_latency(count_latency, query_tags, query.count_results())
188+
);
100189
let requests = requests.map_err(|_| RestError::TemporarilyUnavailable)?;
101190
let total_results = total_results.map_err(|_| RestError::TemporarilyUnavailable)?;
102191

@@ -105,3 +194,19 @@ pub async fn explorer(
105194
total_results,
106195
}))
107196
}
197+
198+
async fn measure_latency<T, F>(
199+
metric: &Family<QueryTags, Histogram>,
200+
query_tags: &QueryTags,
201+
function: F,
202+
) -> T
203+
where
204+
F: std::future::Future<Output = T>,
205+
{
206+
let start = Instant::now();
207+
let return_value = function.await;
208+
metric
209+
.get_or_create(query_tags)
210+
.observe(start.elapsed().as_secs_f64());
211+
return_value
212+
}

apps/fortuna/src/history.rs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -345,13 +345,13 @@ impl History {
345345
#[derive(Debug, Clone)]
346346
pub struct RequestQueryBuilder<'a> {
347347
pool: &'a Pool<Sqlite>,
348-
search: Option<SearchField>,
349-
network_id: Option<i64>,
350-
state: Option<StateTag>,
351-
limit: i64,
352-
offset: i64,
353-
min_timestamp: DateTime<chrono::Utc>,
354-
max_timestamp: DateTime<chrono::Utc>,
348+
pub search: Option<SearchField>,
349+
pub network_id: Option<i64>,
350+
pub state: Option<StateTag>,
351+
pub limit: i64,
352+
pub offset: i64,
353+
pub min_timestamp: DateTime<chrono::Utc>,
354+
pub max_timestamp: DateTime<chrono::Utc>,
355355
}
356356

357357
impl<'a> RequestQueryBuilder<'a> {
@@ -503,7 +503,7 @@ pub enum RequestQueryBuilderError {
503503
}
504504

505505
#[derive(Debug, Clone)]
506-
enum SearchField {
506+
pub enum SearchField {
507507
TxHash(TxHash),
508508
Sender(Address),
509509
SequenceNumber(i64),

apps/fortuna/src/keeper/keeper_metrics.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -69,24 +69,19 @@ impl Default for KeeperMetrics {
6969
requests_reprocessed: Family::default(),
7070
reveals: Family::default(),
7171
request_duration_ms: Family::new_with_constructor(|| {
72-
Histogram::new(
73-
vec![
74-
1000.0, 2500.0, 5000.0, 7500.0, 10000.0, 20000.0, 30000.0, 40000.0,
75-
50000.0, 60000.0, 120000.0, 180000.0, 240000.0, 300000.0, 600000.0,
76-
]
77-
.into_iter(),
78-
)
72+
Histogram::new(vec![
73+
1000.0, 2500.0, 5000.0, 7500.0, 10000.0, 20000.0, 30000.0, 40000.0, 50000.0,
74+
60000.0, 120000.0, 180000.0, 240000.0, 300000.0, 600000.0,
75+
])
7976
}),
8077
retry_count: Family::new_with_constructor(|| {
81-
Histogram::new(vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0].into_iter())
78+
Histogram::new(vec![0.0, 1.0, 2.0, 3.0, 4.0, 5.0, 10.0, 15.0, 20.0])
8279
}),
8380
final_gas_multiplier: Family::new_with_constructor(|| {
84-
Histogram::new(
85-
vec![100.0, 125.0, 150.0, 200.0, 300.0, 400.0, 500.0, 600.0].into_iter(),
86-
)
81+
Histogram::new(vec![100.0, 125.0, 150.0, 200.0, 300.0, 400.0, 500.0, 600.0])
8782
}),
8883
final_fee_multiplier: Family::new_with_constructor(|| {
89-
Histogram::new(vec![100.0, 110.0, 120.0, 140.0, 160.0, 180.0, 200.0].into_iter())
84+
Histogram::new(vec![100.0, 110.0, 120.0, 140.0, 160.0, 180.0, 200.0])
9085
}),
9186
gas_price_estimate: Family::default(),
9287
highest_revealed_sequence_number: Family::default(),

0 commit comments

Comments
 (0)