Skip to content

Commit 54faa24

Browse files
authored
Merge pull request #1239 from input-output-hk/greg/1127/download_statistics
add snapshot downloads statistics
2 parents e432c59 + 2ed485b commit 54faa24

File tree

14 files changed

+269
-10
lines changed

14 files changed

+269
-10
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
.DS_Store
55
.direnv/
66
.tmp/
7+
.vscode/
78
target
89
target-*
910
test-results.xml

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
@@ -10,6 +10,7 @@ This page gathers the available guides to operate a Mithril network.
1010
|------------|------------|------------
1111
| **Genesis manually** | [manual-genesis](./genesis-manually/README.md) | Proceed to manual (re)genesis of the aggregator certificate chain.
1212
| **Era markers** | [era-markers](./era-markers/README.md) | Create and update era markers on the Cardano chain.
13+
| **Downloads statistics** | [downloads statistics](./statistics/README.md) | Display the number of downloads per day.
1314
| **Signer registrations monitoring** | [registrations-monitoring](./registrations-monitoring/README.md) | Gather aggregated data about signer registrations (versions, stake, ...).
1415
| **Update protocol parameters** | [protocol-parameters](./protocol-parameters/README.md) | Update the protocol parameters of a Mithril network.
1516
| **Recompute certificates hash** | [recompute-certificates-hash](./recompute-certificates-hash/README.md) | Recompute the certificates has of an aggregator.

docs/runbook/statistics/README.md

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
# Statistics
2+
3+
## Snapshot downloads per day
4+
5+
```sh
6+
$> sqlite3 -table -batch \
7+
$DATA_STORES_DIRECTORY/monitoring.sqlite3 \
8+
< snapshot_downloads.sql
9+
```
10+
11+
The variable `$DATA_STORES_DIRECTORY` should point to the directory where the
12+
databases files are stored (see files in `mithril-aggregator/config` using the
13+
key `data_stores_directory` to know where they are).
14+
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
select
2+
date(created_at) as downloaded_at,
3+
count(*) as downloads
4+
from event
5+
where
6+
source = 'HTTP::statistics'
7+
and action = 'snapshot_downloaded'
8+
group by 1
9+
order by
10+
downloaded_at desc,
11+
downloads desc
12+

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.3.93"
3+
version = "0.3.94"
44
description = "A Mithril Aggregator server"
55
authors = { workspace = true }
66
edition = { workspace = true }

mithril-aggregator/src/http_server/routes/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,3 +6,4 @@ mod reply;
66
pub mod router;
77
mod signatures_routes;
88
mod signer_routes;
9+
mod statistics_routes;

mithril-aggregator/src/http_server/routes/router.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use crate::http_server::routes::{
22
artifact_routes, certificate_routes, epoch_routes, signatures_routes, signer_routes,
3+
statistics_routes,
34
};
45
use crate::http_server::SERVER_BASE_PATH;
56
use crate::DependencyContainer;
@@ -49,6 +50,7 @@ pub fn routes(
4950
.or(signer_routes::routes(dependency_manager.clone()))
5051
.or(signatures_routes::routes(dependency_manager.clone()))
5152
.or(epoch_routes::routes(dependency_manager.clone()))
53+
.or(statistics_routes::routes(dependency_manager.clone()))
5254
.with(cors),
5355
)
5456
.recover(handle_custom)
Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,108 @@
1+
use std::sync::Arc;
2+
use warp::Filter;
3+
4+
use crate::http_server::routes::middlewares;
5+
use crate::DependencyContainer;
6+
7+
pub fn routes(
8+
dependency_manager: Arc<DependencyContainer>,
9+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
10+
post_statistics(dependency_manager)
11+
}
12+
13+
/// POST /statistics/snapshot
14+
fn post_statistics(
15+
dependency_manager: Arc<DependencyContainer>,
16+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
17+
warp::path!("statistics" / "snapshot")
18+
.and(warp::post())
19+
.and(warp::body::json())
20+
.and(middlewares::with_event_transmitter(
21+
dependency_manager.clone(),
22+
))
23+
.and_then(handlers::post_snapshot_statistics)
24+
}
25+
26+
mod handlers {
27+
use std::{convert::Infallible, sync::Arc};
28+
29+
use mithril_common::messages::SnapshotMessage;
30+
use reqwest::StatusCode;
31+
32+
use crate::event_store::{EventMessage, TransmitterService};
33+
use crate::http_server::routes::reply;
34+
35+
pub async fn post_snapshot_statistics(
36+
snapshot_message: SnapshotMessage,
37+
event_transmitter: Arc<TransmitterService<EventMessage>>,
38+
) -> Result<impl warp::Reply, Infallible> {
39+
let headers: Vec<(&str, &str)> = Vec::new();
40+
41+
match event_transmitter.send_event_message(
42+
"HTTP::statistics",
43+
"snapshot_downloaded",
44+
&snapshot_message,
45+
headers,
46+
) {
47+
Err(e) => Ok(reply::internal_server_error(e)),
48+
Ok(_) => Ok(reply::empty(StatusCode::CREATED)),
49+
}
50+
}
51+
}
52+
53+
#[cfg(test)]
54+
mod tests {
55+
use super::*;
56+
57+
use mithril_common::messages::SnapshotMessage;
58+
use mithril_common::test_utils::apispec::APISpec;
59+
60+
use warp::{http::Method, test::request};
61+
62+
use crate::{
63+
dependency_injection::DependenciesBuilder, http_server::SERVER_BASE_PATH, Configuration,
64+
};
65+
66+
fn setup_router(
67+
dependency_manager: Arc<DependencyContainer>,
68+
) -> impl Filter<Extract = (impl warp::Reply,), Error = warp::Rejection> + Clone {
69+
let cors = warp::cors()
70+
.allow_any_origin()
71+
.allow_headers(vec!["content-type"])
72+
.allow_methods(vec![Method::GET, Method::POST, Method::OPTIONS]);
73+
74+
warp::any()
75+
.and(warp::path(SERVER_BASE_PATH))
76+
.and(routes(dependency_manager).with(cors))
77+
}
78+
79+
#[tokio::test]
80+
async fn post_statistics_ok() {
81+
let config = Configuration::new_sample();
82+
let mut builder = DependenciesBuilder::new(config);
83+
let mut rx = builder.get_event_transmitter_receiver().await.unwrap();
84+
let dependency_manager = builder.build_dependency_container().await.unwrap();
85+
let snapshot_message = SnapshotMessage::dummy();
86+
87+
let method = Method::POST.as_str();
88+
let path = "/statistics/snapshot";
89+
90+
let response = request()
91+
.method(method)
92+
.json(&snapshot_message)
93+
.path(&format!("/{SERVER_BASE_PATH}{path}"))
94+
.reply(&setup_router(Arc::new(dependency_manager)))
95+
.await;
96+
97+
APISpec::verify_conformity(
98+
APISpec::get_all_spec_files(),
99+
method,
100+
path,
101+
"application/json",
102+
&snapshot_message,
103+
&response,
104+
);
105+
106+
let _ = rx.try_recv().unwrap();
107+
}
108+
}

mithril-client/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-client"
3-
version = "0.4.0"
3+
version = "0.4.1"
44
description = "A Mithril Client"
55
authors = { workspace = true }
66
edition = { workspace = true }

0 commit comments

Comments
 (0)