Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: Refactor metrics/make API use binaries #2735

Merged
merged 13 commits into from
Aug 28, 2024
18 changes: 18 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 0 additions & 3 deletions core/lib/prover_interface/src/api.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,9 +65,6 @@ pub enum SubmitProofRequest {
SkippedProofGeneration,
}

#[derive(Debug, Serialize, Deserialize)]
pub struct OptionalProofGenerationDataRequest(pub Option<L1BatchNumber>);

#[derive(Debug, Serialize, Deserialize)]
pub struct VerifyProofRequest(pub Box<L1BatchProofForL1>);

Expand Down
2 changes: 1 addition & 1 deletion core/node/external_proof_integration_api/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ keywords.workspace = true
categories.workspace = true

[dependencies]
axum.workspace = true
axum = { workspace = true, features = ["multipart"] }
tracing.workspace = true
zksync_prover_interface.workspace = true
zksync_basic_types.workspace = true
Expand Down
57 changes: 43 additions & 14 deletions core/node/external_proof_integration_api/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,19 +1,28 @@
mod error;
mod metrics;
mod middleware;
mod processor;

use std::{net::SocketAddr, sync::Arc};

use anyhow::Context;
use axum::{extract::Path, routing::post, Json, Router};
use axum::{
extract::{Multipart, Path, Request},
middleware::Next,
routing::{get, post},
Router,
};
use tokio::sync::watch;
use zksync_basic_types::commitment::L1BatchCommitmentMode;
use zksync_config::configs::external_proof_integration_api::ExternalProofIntegrationApiConfig;
use zksync_dal::{ConnectionPool, Core};
use zksync_object_store::ObjectStore;
use zksync_prover_interface::api::{OptionalProofGenerationDataRequest, VerifyProofRequest};

use crate::processor::Processor;
use crate::{
metrics::{CallOutcome, Method},
middleware::MetricsMiddleware,
processor::Processor,
};

pub async fn run_server(
config: ExternalProofIntegrationApiConfig,
Expand All @@ -23,7 +32,7 @@ pub async fn run_server(
mut stop_receiver: watch::Receiver<bool>,
) -> anyhow::Result<()> {
let bind_address = SocketAddr::from(([0, 0, 0, 0], config.http_port));
tracing::debug!("Starting external prover API server on {bind_address}");
tracing::info!("Starting external prover API server on {bind_address}");
let app = create_router(blob_store, connection_pool, commitment_mode).await;

let listener = tokio::net::TcpListener::bind(bind_address)
Expand All @@ -50,25 +59,45 @@ async fn create_router(
let mut processor =
Processor::new(blob_store.clone(), connection_pool.clone(), commitment_mode);
let verify_proof_processor = processor.clone();
let specific_proof_processor = processor.clone();

let middleware_factory = |method: Method| {
axum::middleware::from_fn(move |req: Request, next: Next| async move {
let middleware = MetricsMiddleware::new(method);
let response = next.run(req).await;
let outcome = match response.status().is_success() {
true => CallOutcome::Success,
false => CallOutcome::Failure,
};
middleware.observe(outcome);
response
})
};

Router::new()
.route(
"/proof_generation_data",
Artemka374 marked this conversation as resolved.
Show resolved Hide resolved
post(
// we use post method because the returned data is not idempotent,
// i.e we return different result on each call.
move |payload: Json<OptionalProofGenerationDataRequest>| async move {
processor.get_proof_generation_data(payload).await
},
),
get(move || async move { processor.get_proof_generation_data().await })
.layer(middleware_factory(Method::GetLatestProofGenerationData)),
)
.route(
"/proof_generation_data/:l1_batch_number",
get(move |l1_batch_number: Path<u32>| async move {
specific_proof_processor
.proof_generation_data_for_existing_batch(l1_batch_number)
.await
})
.layer(middleware_factory(Method::GetSpecificProofGenerationData)),
)
.route(
"/verify_proof/:l1_batch_number",
post(
move |l1_batch_number: Path<u32>, payload: Json<VerifyProofRequest>| async move {
move |l1_batch_number: Path<u32>, multipart: Multipart| async move {
verify_proof_processor
.verify_proof(l1_batch_number, payload)
.verify_proof(l1_batch_number, multipart)
.await
},
),
)
.layer(middleware_factory(Method::VerifyProof)),
)
}
27 changes: 0 additions & 27 deletions core/node/external_proof_integration_api/src/metrics.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::time::Duration;

use tokio::time::Instant;
use vise::{EncodeLabelSet, EncodeLabelValue, Histogram, LabeledFamily, Metrics};

#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, EncodeLabelSet, EncodeLabelValue)]
Expand All @@ -25,31 +24,5 @@ pub(crate) struct ProofIntegrationApiMetrics {
pub call_latency: LabeledFamily<(Method, CallOutcome), Histogram<Duration>, 2>,
}

pub(crate) struct MethodCallGuard {
method_type: Method,
outcome: CallOutcome,
started_at: Instant,
}

impl MethodCallGuard {
pub(crate) fn new(method_type: Method) -> Self {
MethodCallGuard {
method_type,
outcome: CallOutcome::Failure,
started_at: Instant::now(),
}
}

pub(crate) fn mark_successful(&mut self) {
self.outcome = CallOutcome::Success;
}
}

impl Drop for MethodCallGuard {
fn drop(&mut self) {
METRICS.call_latency[&(self.method_type, self.outcome)].observe(self.started_at.elapsed());
}
}

#[vise::register]
pub(crate) static METRICS: vise::Global<ProofIntegrationApiMetrics> = vise::Global::new();
22 changes: 22 additions & 0 deletions core/node/external_proof_integration_api/src/middleware.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use tokio::time::Instant;

use crate::metrics::{CallOutcome, Method, METRICS};

#[derive(Debug)]
pub(crate) struct MetricsMiddleware {
Artemka374 marked this conversation as resolved.
Show resolved Hide resolved
method: Method,
started_at: Instant,
}

impl MetricsMiddleware {
pub fn new(method: Method) -> MetricsMiddleware {
MetricsMiddleware {
method,
started_at: Instant::now(),
}
}

pub fn observe(&self, outcome: CallOutcome) {
METRICS.call_latency[&(self.method, outcome)].observe(self.started_at.elapsed());
}
}
Loading
Loading