Skip to content

Commit 678e6e9

Browse files
authored
Merge pull request #2059 from input-output-hk/sfauvel/2023/record_aggregator_metrics_in_event_store
Record aggregator metrics in event store
2 parents bd9b7be + 10703b4 commit 678e6e9

File tree

16 files changed

+562
-8
lines changed

16 files changed

+562
-8
lines changed

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.

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 daily metrics. |
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
# Aggregator metrics
2+
3+
A view `metrics_per_day` is available to calculate the value of a metric over a day.
4+
5+
The following request displays the sum of counter for each metric on the specify day.
6+
Format of `DAY` variable should be `YYYY-MM-DD` (ie: `2024-10-28`).
7+
8+
```sh
9+
$> sqlite3 -table -batch \
10+
$DATA_STORES_DIRECTORY/monitoring.sqlite3 \
11+
`select date, counter_name, value from metrics_per_day where date='$DAY';`
12+
```
13+
14+
The result looks like:
15+
16+
```
17+
+------------+-------------------------------------------------------------+--------+
18+
| date | counter_name | value |
19+
+------------+-------------------------------------------------------------+--------+
20+
| 2024-10-29 | mithril_aggregator_certificate_total_produced_since_startup | 135532 |
21+
| 2024-10-29 | mithril_aggregator_runtime_cycle_success_since_startup | 563246 |
22+
| 2024-10-29 | mithril_aggregator_runtime_cycle_total_since_startup | 237513 |
23+
+------------+-------------------------------------------------------------+--------+
24+
```

docs/website/root/manual/developer-docs/nodes/mithril-aggregator.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -456,6 +456,7 @@ Here is a list of the available parameters:
456456
| `enable_metrics_server` | `--enable-metrics-server` | - | `ENABLE_METRICS_SERVER` | Enable metrics HTTP server (Prometheus endpoint on /metrics) | `false` | - | - |
457457
| `metrics_server_ip` | `--metrics-server-ip` | - | `METRICS_SERVER_IP` | Metrics HTTP server IP | `0.0.0.0` | - | - |
458458
| `metrics_server_port` | `--metrics-server-port` | - | `METRICS_SERVER_PORT` | Metrics HTTP server listening port | `9090` | - | - |
459+
| `persist_usage_report_interval_in_seconds` | | - | `PERSIST_USAGE_REPORT_INTERVAL_IN_SECONDS` | Duration in seconds between two recording of usage metrics | `10` | `5` | - |
459460

460461
`genesis bootstrap` command:
461462

mithril-aggregator/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mithril-aggregator"
3-
version = "0.5.94"
3+
version = "0.5.95"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/commands/serve_command.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -221,6 +221,18 @@ impl ServeCommand {
221221
}
222222
}
223223
}
224+
225+
let mut usage_reporter = dependencies_builder
226+
.create_usage_reporter()
227+
.await
228+
.with_context(|| "Dependencies Builder can not create usage reporter")?;
229+
join_set.spawn(async move {
230+
let interval_duration =
231+
Duration::from_secs(config.persist_usage_report_interval_in_seconds);
232+
usage_reporter.run_forever(interval_duration).await;
233+
Ok(())
234+
});
235+
224236
let metrics_service = dependencies_builder
225237
.get_metrics_service()
226238
.await

mithril-aggregator/src/configuration.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -183,6 +183,9 @@ pub struct Configuration {
183183

184184
/// Metrics HTTP Server listening port.
185185
pub metrics_server_port: u16,
186+
187+
/// Time interval at which usage metrics are persisted in event database (in seconds).
188+
pub persist_usage_report_interval_in_seconds: u64,
186189
}
187190

188191
/// Uploader needed to copy the snapshot once computed.
@@ -266,6 +269,7 @@ impl Configuration {
266269
enable_metrics_server: true,
267270
metrics_server_ip: "0.0.0.0".to_string(),
268271
metrics_server_port: 9090,
272+
persist_usage_report_interval_in_seconds: 10,
269273
}
270274
}
271275

@@ -395,6 +399,9 @@ pub struct DefaultConfiguration {
395399

396400
/// Metrics HTTP server listening port.
397401
pub metrics_server_port: u16,
402+
403+
/// Time interval at which metrics are persisted in event database (in seconds).
404+
pub persist_usage_report_interval_in_seconds: u64,
398405
}
399406

400407
impl Default for DefaultConfiguration {
@@ -426,6 +433,7 @@ impl Default for DefaultConfiguration {
426433
enable_metrics_server: "false".to_string(),
427434
metrics_server_ip: "0.0.0.0".to_string(),
428435
metrics_server_port: 9090,
436+
persist_usage_report_interval_in_seconds: 10,
429437
}
430438
}
431439
}
@@ -465,7 +473,6 @@ impl Source for DefaultConfiguration {
465473
}
466474
let mut result = Map::new();
467475
let myself = self.clone();
468-
469476
insert_default_configuration!(result, myself.environment);
470477
insert_default_configuration!(result, myself.server_ip);
471478
insert_default_configuration!(result, myself.server_port);
@@ -496,6 +503,7 @@ impl Source for DefaultConfiguration {
496503
insert_default_configuration!(result, myself.enable_metrics_server);
497504
insert_default_configuration!(result, myself.metrics_server_ip);
498505
insert_default_configuration!(result, myself.metrics_server_port);
506+
insert_default_configuration!(result, myself.persist_usage_report_interval_in_seconds);
499507
result.insert(
500508
"cardano_transactions_signing_config".to_string(),
501509
into_value(HashMap::from([
@@ -513,7 +521,6 @@ impl Source for DefaultConfiguration {
513521
),
514522
])),
515523
);
516-
517524
Ok(result)
518525
}
519526
}

mithril-aggregator/src/dependency_injection/builder.rs

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,7 @@ use crate::{
6969
CardanoTransactionsImporter, CertifierService, MessageService, MithrilCertifierService,
7070
MithrilEpochService, MithrilMessageService, MithrilProverService,
7171
MithrilSignedEntityService, MithrilStakeDistributionService, ProverService,
72-
SignedEntityService, StakeDistributionService, UpkeepService,
72+
SignedEntityService, StakeDistributionService, UpkeepService, UsageReporter,
7373
},
7474
tools::{CExplorerSignerRetriever, GcpFileUploader, GenesisToolsDependency, SignersImporter},
7575
AggregatorConfig, AggregatorRunner, AggregatorRuntime, CertificatePendingStore,
@@ -1392,6 +1392,17 @@ impl DependenciesBuilder {
13921392
Ok(self.metrics_service.as_ref().cloned().unwrap())
13931393
}
13941394

1395+
/// Create a [UsageReporter] instance.
1396+
pub async fn create_usage_reporter(&mut self) -> Result<UsageReporter> {
1397+
let usage_reporter = UsageReporter::new(
1398+
self.get_event_transmitter().await?,
1399+
self.get_metrics_service().await?,
1400+
self.root_logger(),
1401+
);
1402+
1403+
Ok(usage_reporter)
1404+
}
1405+
13951406
/// Return an unconfigured [DependencyContainer]
13961407
pub async fn build_dependency_container(&mut self) -> Result<DependencyContainer> {
13971408
let dependency_manager = DependencyContainer {

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

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,5 +20,18 @@ 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 metric_date as date, action as counter_name, sum(counter) value from
27+
(
28+
select action, json_extract(content, '$.content.counter') counter, date(json_extract(content, '$.content.date')) metric_date
29+
from event
30+
where source='Metrics'
31+
)
32+
group by action, date;
33+
create index metric_date_index on event(date(json_extract(content, '$.content.date')));
34+
"#,
35+
),
2336
]
2437
}

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 event 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)