From f1866b5e5591b50867e2af6bd3ffa42a0571382c Mon Sep 17 00:00:00 2001 From: Jannis Pohlmann Date: Thu, 26 Oct 2023 14:35:39 +0200 Subject: [PATCH] feat: add prometheus metrics support to http indexer service --- Cargo.lock | 275 +++++++++++++++++- common/Cargo.toml | 1 + common/src/indexer_service/http/config.rs | 1 + .../indexer_service/http/indexer_service.rs | 26 +- 4 files changed, 287 insertions(+), 16 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index e91efb74c..3e61e1f94 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -644,16 +644,36 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "52c47a2283b04388a392a7bff8a0f68db615d967e4d177068f573773fcefa91b" dependencies = [ - "autometrics-macros", + "autometrics-macros 0.3.3", "const_format", - "metrics-exporter-prometheus", + "metrics-exporter-prometheus 0.11.0", "once_cell", - "opentelemetry-prometheus", - "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry-prometheus 0.11.0", + "opentelemetry_api 0.18.0", + "opentelemetry_sdk 0.18.0", "prometheus", ] +[[package]] +name = "autometrics" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95cef5eb1e18adfb843202bf71587174e480ed67c0ca3e976bf40e82d9adce86" +dependencies = [ + "autometrics-macros 0.6.0", + "cfg_aliases", + "http", + "linkme", + "metrics-exporter-prometheus 0.12.1", + "once_cell", + "opentelemetry-prometheus 0.13.0", + "opentelemetry_sdk 0.20.0", + "prometheus", + "prometheus-client", + "spez", + "thiserror", +] + [[package]] name = "autometrics-macros" version = "0.3.3" @@ -666,6 +686,18 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "autometrics-macros" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "543250f01aa62c3b2666e327b335be532845a35e440eb984f5e6bad69106833d" +dependencies = [ + "percent-encoding", + "proc-macro2", + "quote", + "syn 1.0.109", +] + [[package]] name = "axum" version = "0.5.17" @@ -1171,6 +1203,12 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "cfg_aliases" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" + [[package]] name = "chrono" version = "0.4.31" @@ -1759,6 +1797,12 @@ version = "0.15.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aaf95b3e5c8f23aa320147307562d361db0ae0d51242340f558153b4eb2439b" +[[package]] +name = "dtoa" +version = "1.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dcbb2bf8e87535c23f7a8a321e364ce21462d0ff10cb6407820e8e96dfff6653" + [[package]] name = "dunce" version = "1.0.4" @@ -2694,6 +2738,15 @@ dependencies = [ "ahash 0.7.6", ] +[[package]] +name = "hashbrown" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33ff8ae62cd3a9102e5637afc8452c55acf3844001bd5374e0b0bd7b6616c038" +dependencies = [ + "ahash 0.8.3", +] + [[package]] name = "hashbrown" version = "0.14.0" @@ -3032,6 +3085,7 @@ dependencies = [ "anyhow", "arc-swap", "async-trait", + "autometrics 0.6.0", "axum 0.6.20", "build-info", "env_logger", @@ -3308,6 +3362,26 @@ dependencies = [ "vcpkg", ] +[[package]] +name = "linkme" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91ed2ee9464ff9707af8e9ad834cffa4802f072caad90639c583dd3c62e6e608" +dependencies = [ + "linkme-impl", +] + +[[package]] +name = "linkme-impl" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba125974b109d512fccbc6c0244e7580143e460895dfd6ea7f8bbb692fd94396" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "linux-raw-sys" version = "0.3.8" @@ -3354,6 +3428,15 @@ dependencies = [ "libc", ] +[[package]] +name = "mach2" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d0d1830bcd151a6fc4aea1369af235b36c1528fe976b8ff678683c9995eade8" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -3412,10 +3495,21 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7b9b8653cec6897f73b519a43fba5ee3d50f62fe9af80b428accdcc093b4a849" dependencies = [ "ahash 0.7.6", - "metrics-macros", + "metrics-macros 0.6.0", "portable-atomic 0.3.20", ] +[[package]] +name = "metrics" +version = "0.21.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fde3af1a009ed76a778cb84fdef9e7dbbdf5775ae3e4cc1f434a6a307f6f76c5" +dependencies = [ + "ahash 0.8.3", + "metrics-macros 0.7.0", + "portable-atomic 1.3.3", +] + [[package]] name = "metrics-exporter-prometheus" version = "0.11.0" @@ -3423,11 +3517,25 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8603921e1f54ef386189335f288441af761e0fc61bcb552168d9cedfe63ebc70" dependencies = [ "indexmap 1.9.3", - "metrics", - "metrics-util", + "metrics 0.20.1", + "metrics-util 0.14.0", "parking_lot", "portable-atomic 0.3.20", - "quanta", + "quanta 0.10.1", + "thiserror", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a4964177ddfdab1e3a2b37aec7cf320e14169abb0ed73999f558136409178d5" +dependencies = [ + "base64 0.21.4", + "indexmap 1.9.3", + "metrics 0.21.1", + "metrics-util 0.15.1", + "quanta 0.11.1", "thiserror", ] @@ -3442,6 +3550,17 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "metrics-macros" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ddece26afd34c31585c74a4db0630c376df271c285d682d1e55012197830b6df" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "metrics-util" version = "0.14.0" @@ -3451,11 +3570,26 @@ dependencies = [ "crossbeam-epoch", "crossbeam-utils", "hashbrown 0.12.3", - "metrics", + "metrics 0.20.1", "num_cpus", "parking_lot", "portable-atomic 0.3.20", - "quanta", + "quanta 0.10.1", + "sketches-ddsketch", +] + +[[package]] +name = "metrics-util" +version = "0.15.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4de2ed6e491ed114b40b732e4d1659a9d53992ebd87490c44a6ffe23739d973e" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.13.1", + "metrics 0.21.1", + "num_cpus", + "quanta 0.11.1", "sketches-ddsketch", ] @@ -3751,8 +3885,8 @@ version = "0.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69d6c3d7288a106c0a363e4b0e8d308058d56902adefb16f4936f417ffef086e" dependencies = [ - "opentelemetry_api", - "opentelemetry_sdk", + "opentelemetry_api 0.18.0", + "opentelemetry_sdk 0.18.0", ] [[package]] @@ -3766,6 +3900,19 @@ dependencies = [ "protobuf", ] +[[package]] +name = "opentelemetry-prometheus" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c7d81bc254e2d572120363a2b16cdb0d715d301b5789be0cfc26ad87e4e10e53" +dependencies = [ + "once_cell", + "opentelemetry_api 0.20.0", + "opentelemetry_sdk 0.20.0", + "prometheus", + "protobuf", +] + [[package]] name = "opentelemetry_api" version = "0.18.0" @@ -3782,6 +3929,22 @@ dependencies = [ "thiserror", ] +[[package]] +name = "opentelemetry_api" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a81f725323db1b1206ca3da8bb19874bbd3f57c3bcd59471bfb04525b265b9b" +dependencies = [ + "futures-channel", + "futures-util", + "indexmap 1.9.3", + "js-sys", + "once_cell", + "pin-project-lite", + "thiserror", + "urlencoding", +] + [[package]] name = "opentelemetry_sdk" version = "0.18.0" @@ -3796,18 +3959,44 @@ dependencies = [ "futures-executor", "futures-util", "once_cell", - "opentelemetry_api", + "opentelemetry_api 0.18.0", "percent-encoding", "rand 0.8.5", "thiserror", ] +[[package]] +name = "opentelemetry_sdk" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8e705a0612d48139799fcbaba0d4a90f06277153e43dd2bdc16c6f0edd8026" +dependencies = [ + "async-trait", + "futures-channel", + "futures-executor", + "futures-util", + "once_cell", + "opentelemetry_api 0.20.0", + "ordered-float", + "regex", + "thiserror", +] + [[package]] name = "option-ext" version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" +[[package]] +name = "ordered-float" +version = "3.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f1e1c390732d15f1d48471625cd92d154e66db2c56645e29a9cd26f4699f72dc" +dependencies = [ + "num-traits", +] + [[package]] name = "overload" version = "0.1.1" @@ -4240,6 +4429,29 @@ dependencies = [ "thiserror", ] +[[package]] +name = "prometheus-client" +version = "0.21.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c99afa9a01501019ac3a14d71d9f94050346f55ca471ce90c799a15c58f61e2" +dependencies = [ + "dtoa", + "itoa", + "parking_lot", + "prometheus-client-derive-encode", +] + +[[package]] +name = "prometheus-client-derive-encode" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "440f724eba9f6996b75d63681b0a92b06947f1457076d503a4d2e2c8f56442b8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "proptest" version = "1.2.0" @@ -4302,6 +4514,22 @@ dependencies = [ "winapi", ] +[[package]] +name = "quanta" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a17e662a7a8291a865152364c20c7abc5e60486ab2001e8ec10b24862de0b9ab" +dependencies = [ + "crossbeam-utils", + "libc", + "mach2", + "once_cell", + "raw-cpuid", + "wasi 0.11.0+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + [[package]] name = "quick-error" version = "1.2.3" @@ -5170,7 +5398,7 @@ dependencies = [ "anyhow", "async-graphql 4.0.16", "async-graphql-axum", - "autometrics", + "autometrics 0.3.3", "axum 0.5.17", "build-info", "build-info-build", @@ -5390,6 +5618,17 @@ dependencies = [ "unicode-xid", ] +[[package]] +name = "spez" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c87e960f4dca2788eeb86bbdde8dd246be8948790b7618d656e68f9b720a86e8" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.28", +] + [[package]] name = "spin" version = "0.5.2" @@ -6390,6 +6629,12 @@ dependencies = [ "serde", ] +[[package]] +name = "urlencoding" +version = "2.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da" + [[package]] name = "utf-8" version = "0.7.6" diff --git a/common/Cargo.toml b/common/Cargo.toml index 18839bde2..db5024be0 100644 --- a/common/Cargo.toml +++ b/common/Cargo.toml @@ -40,6 +40,7 @@ async-trait = "0.1.74" headers-derive = "0.1.1" headers = "0.3.9" build-info = "0.0.34" +autometrics = { version = "0.6.0", features = ["prometheus-exporter"] } [dev-dependencies] env_logger = "0.9.0" diff --git a/common/src/indexer_service/http/config.rs b/common/src/indexer_service/http/config.rs index a008b4367..421c44c62 100644 --- a/common/src/indexer_service/http/config.rs +++ b/common/src/indexer_service/http/config.rs @@ -26,6 +26,7 @@ pub struct EscrowSubgraphConfig { #[derive(Clone, Debug, Deserialize, Serialize)] pub struct ServerConfig { pub host_and_port: SocketAddr, + pub metrics_host_and_port: SocketAddr, pub url_prefix: String, pub free_query_auth_token: Option, } diff --git a/common/src/indexer_service/http/indexer_service.rs b/common/src/indexer_service/http/indexer_service.rs index df1c888da..2c21e932e 100644 --- a/common/src/indexer_service/http/indexer_service.rs +++ b/common/src/indexer_service/http/indexer_service.rs @@ -1,8 +1,11 @@ -use std::{collections::HashMap, fmt::Debug, path::PathBuf, sync::Arc, time::Duration}; +use std::{ + collections::HashMap, fmt::Debug, net::SocketAddr, path::PathBuf, sync::Arc, time::Duration, +}; use alloy_primitives::Address; use alloy_sol_types::eip712_domain; use anyhow; +use autometrics::prometheus_exporter; use axum::{ async_trait, body::Body, @@ -12,6 +15,7 @@ use axum::{ }; use build_info::BuildInfo; use eventuals::Eventual; +use log::info; use reqwest::StatusCode; use serde::{de::DeserializeOwned, Serialize}; use sqlx::postgres::PgPoolOptions; @@ -264,8 +268,28 @@ impl IndexerService { .merge(options.extra_routes) .with_state(state); + Self::serve_metrics(options.config.server.metrics_host_and_port); + + info!("Serving at {}", options.config.server.host_and_port); + Ok(Server::bind(&options.config.server.host_and_port) .serve(router.into_make_service()) .await?) } + + fn serve_metrics(host_and_port: SocketAddr) { + info!("Serving prometheus metrics at {host_and_port}"); + + tokio::spawn(async move { + let router = Router::new().route( + "/metrics", + get(|| async { prometheus_exporter::encode_http_response() }), + ); + + Server::bind(&host_and_port) + .serve(router.into_make_service()) + .await + .expect("Failed to serve metrics") + }); + } }