Skip to content

Commit 24f5bc4

Browse files
committed
Add a view to get metric values per day
1 parent 71273a3 commit 24f5bc4

File tree

4 files changed

+153
-0
lines changed

4 files changed

+153
-0
lines changed

docs/runbook/README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,3 +23,4 @@ This page gathers the available guides to operate a Mithril network.
2323
| **Publish packages to npm manually** | [manual-publish-npm](./manual-publish-npm/README.md) | Manually publish packages to npm registry. |
2424
| **Client multi-platform test** | [test-client-multiplatform](./test-client-multiplatform/README.md) | Run multi-platform client CLI binaries, docker and WASM package tests. |
2525
| **Maintain the networks configuration file** | [maintain-networks-configuration-file](./maintain-networks-configuration-file/README.md) | Maintain the `networks.json` file |
26+
| **Aggregator metrics** | [aggregator-metrics](./aggregator-metrics/README.md) | Display aggregator metrics . |
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
# Aggregator metrics
2+
3+
Aggregator metrics are stored in `monitoring.sqlite3` database as an event.
4+
5+
They are stored in database with `Metrics` as `source` and the name of the metric as `action`.
6+
7+
| event_id | created_at | source | action | content |
8+
| -------- | ----------------------------------- | ------- | ------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------- |
9+
| 104 | 2024-10-29T10:27:49.843362986+00:00 | Metrics | mithril_aggregator_signer_registration_total_received_since_startup | `{"content":{"counter":2,"date":"2024-10-29T10:27:49.842316726Z","duration":{"nanos":0,"secs":3}},"headers":{}} ` |
10+
| |
11+
12+
The content of the metric is a json that contains the counter value, the date the value was measured and the duration that corresponds to the measurement.
13+
14+
Json sample:
15+
16+
```json
17+
{
18+
"content": {
19+
"counter": 6,
20+
"date": "2024-10-28T16:43:18.858027008Z",
21+
"duration": {
22+
"nanos": 0,
23+
"secs": 10
24+
}
25+
},
26+
"headers": {}
27+
}
28+
```
29+
30+
Each event represents the number of hits on the counter since the last period of timed.
31+
32+
A view `metrics_per_day` is available to calculate the value of a metric over a day.
33+
34+
The following request displays the sum of counter for each metric on the specify day.
35+
`select date, counter_name, value from metrics_per_day where date='2024-10-29';`
36+
37+
The result looks like:
38+
39+
```
40+
2024-10-29|mithril_aggregator_certificate_total_produced_since_startup|32
41+
2024-10-29|mithril_aggregator_runtime_cycle_success_since_startup|131
42+
2024-10-29|mithril_aggregator_runtime_cycle_total_since_startup|239
43+
```
44+
45+
NOTE: These metrics should not be used to have an exact count. There may be slight discrepancies with reality.
46+
When stopping the aggregator, last measure may not be counted.
47+
48+
The measurement extends over a period of time which may have started the previous day.
49+
In this case, the value is counted for the day the measurement was taken.
50+
51+
The measurement frequency is relatively short and can be configured by setting the environment variable `PERSIST_USAGE_REPORT_INTERVAL_IN_SECONDS`.

mithril-aggregator/src/event_store/database/migration.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,17 @@ create table if not exists event (
2020
);
2121
"#,
2222
),
23+
SqlMigration::new(
24+
2,
25+
r#"
26+
create view if not exists metrics_per_day as select date(metric_date) as date, action as counter_name, sum(counter) value from
27+
(
28+
select action, json_extract(content, '$.content.counter') counter, json_extract(content, '$.content.date') metric_date
29+
from event
30+
where source='Metrics'
31+
)
32+
group by action, date;
33+
"#,
34+
),
2335
]
2436
}

mithril-aggregator/src/event_store/database/repository.rs

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,4 +58,93 @@ mod tests {
5858
let _event = persister.persist(message)?;
5959
Ok(())
6060
}
61+
62+
mod metrics_per_day_view {
63+
use std::time::Duration;
64+
65+
use crate::event_store::database::test_helper::event_store_db_connection;
66+
use chrono::{DateTime, Utc};
67+
use serde::{Deserialize, Serialize};
68+
69+
use mithril_common::StdResult;
70+
71+
use sqlite::ConnectionThreadSafe;
72+
73+
use super::*;
74+
#[derive(Serialize, Deserialize)]
75+
struct MetricMessage {
76+
counter: i64,
77+
duration: Duration,
78+
date: DateTime<Utc>,
79+
}
80+
81+
fn get_all_metrics(
82+
connection: Arc<ConnectionThreadSafe>,
83+
) -> StdResult<Vec<(String, String, i64)>> {
84+
let query = "SELECT date, counter_name, value FROM metrics_per_day";
85+
let mut statement = connection.prepare(query)?;
86+
let mut result = Vec::new();
87+
while let Ok(sqlite::State::Row) = statement.next() {
88+
result.push((
89+
statement.read::<String, _>("date")?,
90+
statement.read::<String, _>("counter_name")?,
91+
statement.read::<i64, _>("value")?,
92+
));
93+
}
94+
95+
Ok(result)
96+
}
97+
98+
/// Insert a metric evnet in the database.
99+
/// date format is "%Y-%m-%d %H:%M:%S %z", example: "2015-09-05 23:56:04 +0000"
100+
fn insert_metric_event(
101+
persister: &EventPersister,
102+
date: &str,
103+
metric_name: &str,
104+
value: i64,
105+
) {
106+
let metric_date =
107+
DateTime::parse_from_str(&format!("{date} +0000"), "%Y-%m-%d %H:%M:%S %z").unwrap();
108+
109+
let message = EventMessage::new(
110+
"Metrics",
111+
metric_name,
112+
serde_json::json!(MetricMessage {
113+
counter: value,
114+
duration: Duration::from_secs(3),
115+
date: metric_date.into(),
116+
}),
117+
);
118+
119+
let _event = persister.persist(message).unwrap();
120+
}
121+
122+
#[test]
123+
fn retrieved_inserted_event() {
124+
let connection = Arc::new(event_store_db_connection().unwrap());
125+
let persister = EventPersister::new(connection.clone());
126+
insert_metric_event(&persister, "2024-10-29 23:56:04", "metric_1", 15);
127+
128+
let result = get_all_metrics(connection).unwrap();
129+
130+
assert!(result.contains(&("2024-10-29".to_string(), "metric_1".to_string(), 15)));
131+
}
132+
133+
#[test]
134+
fn sum_metric_per_day() {
135+
let connection = Arc::new(event_store_db_connection().unwrap());
136+
let persister = EventPersister::new(connection.clone());
137+
insert_metric_event(&persister, "2024-10-29 21:00:00", "metric_1", 15);
138+
insert_metric_event(&persister, "2024-10-29 22:00:00", "metric_1", 60);
139+
insert_metric_event(&persister, "2024-10-29 23:00:00", "metric_2", 100);
140+
insert_metric_event(&persister, "2024-10-30 17:00:00", "metric_1", 12);
141+
insert_metric_event(&persister, "2024-10-30 18:00:00", "metric_1", 4);
142+
143+
let result = get_all_metrics(connection).unwrap();
144+
145+
assert!(result.contains(&("2024-10-29".to_string(), "metric_1".to_string(), 75)));
146+
assert!(result.contains(&("2024-10-29".to_string(), "metric_2".to_string(), 100)));
147+
assert!(result.contains(&("2024-10-30".to_string(), "metric_1".to_string(), 16)));
148+
}
149+
}
61150
}

0 commit comments

Comments
 (0)