Skip to content

Commit a51d8f7

Browse files
feat(aggregation-mode): add grafana dashboard
1 parent cef571e commit a51d8f7

File tree

11 files changed

+693
-11
lines changed

11 files changed

+693
-11
lines changed

aggregation_mode/Cargo.lock

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

aggregation_mode/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ aligned-sdk = { path = "../crates/sdk/" }
1616
db = { path = "./db" }
1717
sp1-sdk = "5.0.0"
1818
risc0-zkvm = { version = "3.0.3" }
19+
prometheus = { version = "0.13.4", features = ["process"] }
20+
anyhow = { version = "1.0" }
21+
warp = "0.3.7"
1922

2023
[profile.release]
2124
opt-level = 3

aggregation_mode/gateway/Cargo.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ edition = "2021"
77
serde = { workspace = true }
88
serde_json = { workspace = true }
99
serde_yaml = { workspace = true }
10+
prometheus = { workspace = true }
11+
anyhow = { workspace = true }
12+
warp = { workspace = true }
1013
agg_mode_sdk = { path = "../sdk"}
1114
aligned-sdk = { workspace = true }
1215
sp1-sdk = { workspace = true }
@@ -15,6 +18,7 @@ tracing-subscriber = { version = "0.3.0", features = ["env-filter"] }
1518
bincode = "1.3.3"
1619
actix-web = "4"
1720
actix-multipart = "0.7.2"
21+
actix-web-prometheus = "0.1.0-beta.8"
1822
alloy = { workspace = true }
1923
tokio = { version = "1", features = ["time"]}
2024
# TODO: enable tls

aggregation_mode/gateway/src/config.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct Config {
88
pub db_connection_url: String,
99
pub network: String,
1010
pub max_daily_proofs_per_user: i64,
11+
pub metrics_port: u16,
1112
}
1213

1314
impl Config {

aggregation_mode/gateway/src/http.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
use std::{
2+
collections::HashMap,
23
str::FromStr,
34
time::{SystemTime, UNIX_EPOCH},
45
};
@@ -8,6 +9,7 @@ use actix_web::{
89
web::{self, Data},
910
App, HttpRequest, HttpResponse, HttpServer, Responder,
1011
};
12+
use actix_web_prometheus::PrometheusMetricsBuilder;
1113
use agg_mode_sdk::types::Network;
1214
use aligned_sdk::aggregation_layer::AggregationModeProvingSystem;
1315
use alloy::signers::Signature;
@@ -23,6 +25,7 @@ use crate::{
2325
config::Config,
2426
db::Db,
2527
helpers::get_time_left_day_formatted,
28+
metrics::GatewayMetrics,
2629
types::{GetReceiptsResponse, SubmitProofRequestRisc0, SubmitProofRequestSP1},
2730
verifiers::{verify_sp1_proof, VerificationError},
2831
};
@@ -32,15 +35,22 @@ pub struct GatewayServer {
3235
db: Db,
3336
config: Config,
3437
network: Network,
38+
metrics: GatewayMetrics,
3539
}
3640

3741
impl GatewayServer {
3842
pub fn new(db: Db, config: Config) -> Self {
3943
let network = Network::from_str(&config.network).expect("A valid network in config file");
44+
45+
tracing::info!("Starting metrics server on port {}", config.metrics_port);
46+
let metrics =
47+
GatewayMetrics::start(config.metrics_port).expect("Failed to start metrics server");
48+
4049
Self {
4150
db,
4251
config,
4352
network,
53+
metrics,
4454
}
4555
}
4656

@@ -49,10 +59,19 @@ impl GatewayServer {
4959
let port = self.config.port;
5060
let state = self.clone();
5161

62+
let mut labels = HashMap::new();
63+
labels.insert("label1".to_string(), "value1".to_string());
64+
let prometheus = PrometheusMetricsBuilder::new("api")
65+
.endpoint("/metrics")
66+
.const_labels(labels)
67+
.build()
68+
.unwrap();
69+
5270
tracing::info!("Starting server at port {}", self.config.port);
5371
HttpServer::new(move || {
5472
App::new()
5573
.app_data(Data::new(state.clone()))
74+
.wrap(prometheus.clone())
5675
.route("/nonce/{address}", web::get().to(Self::get_nonce))
5776
.route("/receipts", web::get().to(Self::get_receipts))
5877
.route("/proof/sp1", web::post().to(Self::post_proof_sp1))

aggregation_mode/gateway/src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@ pub mod config;
22
pub mod db;
33
mod helpers;
44
pub mod http;
5+
mod metrics;
56
mod types;
67
mod verifiers;
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
use prometheus::{self, opts, register_int_counter, IntCounter};
2+
use warp::{reject::Rejection, reply::Reply, Filter};
3+
4+
#[derive(Clone, Debug)]
5+
pub struct GatewayMetrics {
6+
pub success_response: IntCounter,
7+
pub server_error_response: IntCounter,
8+
pub user_error_response: IntCounter,
9+
}
10+
11+
impl GatewayMetrics {
12+
pub fn start(metrics_port: u16) -> anyhow::Result<Self> {
13+
let registry = prometheus::Registry::new();
14+
15+
let success_response =
16+
register_int_counter!(opts!("success_response_count", "Success Responses"))?;
17+
18+
let server_error_response =
19+
register_int_counter!(opts!("server_error_response_count", "Success Responses"))?;
20+
21+
let user_error_response =
22+
register_int_counter!(opts!("user_error_response_count", "Success Responses"))?;
23+
24+
registry.register(Box::new(success_response.clone()))?;
25+
registry.register(Box::new(server_error_response.clone()))?;
26+
registry.register(Box::new(user_error_response.clone()))?;
27+
28+
let metrics_route = warp::path!("metrics")
29+
.and(warp::any().map(move || registry.clone()))
30+
.and_then(GatewayMetrics::metrics_handler);
31+
32+
tokio::task::spawn(async move {
33+
warp::serve(metrics_route)
34+
.run(([0, 0, 0, 0], metrics_port))
35+
.await;
36+
});
37+
38+
Ok(Self {
39+
success_response,
40+
server_error_response,
41+
user_error_response,
42+
})
43+
}
44+
45+
pub async fn metrics_handler(registry: prometheus::Registry) -> Result<impl Reply, Rejection> {
46+
use prometheus::Encoder;
47+
let encoder = prometheus::TextEncoder::new();
48+
49+
let mut buffer = Vec::new();
50+
if let Err(e) = encoder.encode(&registry.gather(), &mut buffer) {
51+
eprintln!("could not encode prometheus metrics: {}", e);
52+
};
53+
let res = String::from_utf8(buffer.clone())
54+
.inspect_err(|e| eprintln!("prometheus metrics could not be parsed correctly: {e}"))
55+
.unwrap_or_default();
56+
buffer.clear();
57+
58+
Ok(res)
59+
}
60+
61+
pub fn inc_success_response(&self) {
62+
self.success_response.inc();
63+
}
64+
65+
pub fn inc_server_error_response(&self) {
66+
self.server_error_response.inc();
67+
}
68+
69+
pub fn inc_user_error_response(&self) {
70+
self.user_error_response.inc();
71+
}
72+
}

config-files/config-agg-mode-gateway-ethereum-package.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@ eth_rpc_url: "http://localhost:8545"
44
payment_service_address: "0x922D6956C99E12DFeB3224DEA977D0939758A1Fe"
55
network: "devnet"
66
max_daily_proofs_per_user: 32
7+
last_block_fetched_filepath: "config-files/proof-aggregator.last_block_fetched.json"
8+
9+
# Metrics
10+
metrics_port: 9093

config-files/config-agg-mode-gateway.yaml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,3 +5,6 @@ payment_service_address: "0x922D6956C99E12DFeB3224DEA977D0939758A1Fe"
55
network: "devnet"
66
max_daily_proofs_per_user: 4
77
last_block_fetched_filepath: "config-files/proof-aggregator.last_block_fetched.json"
8+
9+
# Metrics
10+
metrics_port: 9093

0 commit comments

Comments
 (0)