From c37f87b6d5f4d4f178d2d5fad51ec3b3c0a7493a Mon Sep 17 00:00:00 2001 From: Akshola00 Date: Mon, 10 Nov 2025 12:39:39 +0100 Subject: [PATCH] integrate prometheus and grafana --- server/Cargo.lock | 149 ++++++++++++++++++++++++++++++++++++++ server/Cargo.toml | 3 +- server/docker-compose.yml | 26 ++++++- server/prometheus.yml | 8 ++ server/src/libs/router.rs | 7 +- 5 files changed, 190 insertions(+), 3 deletions(-) create mode 100644 server/prometheus.yml diff --git a/server/Cargo.lock b/server/Cargo.lock index b473032..bbcd774 100644 --- a/server/Cargo.lock +++ b/server/Cargo.lock @@ -28,6 +28,18 @@ dependencies = [ "cpufeatures", ] +[[package]] +name = "ahash" +version = "0.8.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a15f179cd60c4584b8a8c596927aadc462e27f2ca70c04e0071964a73ba7a75" +dependencies = [ + "cfg-if", + "once_cell", + "version_check", + "zerocopy", +] + [[package]] name = "aho-corasick" version = "1.1.3" @@ -203,6 +215,26 @@ dependencies = [ "tracing", ] +[[package]] +name = "axum-prometheus" +version = "0.9.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fb15221c30bbb32e99873d348d89d7bc2138d6199520aa473a1bdb0d8e5721e8" +dependencies = [ + "axum", + "bytes", + "futures-core", + "http", + "http-body", + "matchit", + "metrics", + "metrics-exporter-prometheus", + "pin-project-lite", + "tokio", + "tower", + "tower-http", +] + [[package]] name = "backtrace" version = "0.3.75" @@ -483,6 +515,15 @@ dependencies = [ "cfg-if", ] +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + [[package]] name = "crossbeam-queue" version = "0.3.12" @@ -1604,6 +1645,46 @@ version = "2.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "32a282da65faaf38286cf3be983213fcf1d2e2a58700e808f83f4ea9a4804bc0" +[[package]] +name = "metrics" +version = "0.24.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "25dea7ac8057892855ec285c440160265225438c3c45072613c25a4b26e98ef5" +dependencies = [ + "ahash", + "portable-atomic", +] + +[[package]] +name = "metrics-exporter-prometheus" +version = "0.17.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b166dea96003ee2531cf14833efedced545751d800f03535801d833313f8c15" +dependencies = [ + "base64 0.22.1", + "indexmap 2.10.0", + "metrics", + "metrics-util", + "quanta", + "thiserror 2.0.16", +] + +[[package]] +name = "metrics-util" +version = "0.20.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe8db7a05415d0f919ffb905afa37784f71901c9a773188876984b4f769ab986" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", + "hashbrown 0.15.5", + "metrics", + "quanta", + "rand 0.9.2", + "rand_xoshiro", + "sketches-ddsketch", +] + [[package]] name = "mime" version = "0.3.17" @@ -1898,6 +1979,12 @@ version = "0.3.32" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7edddbd0b52d732b21ad9a5fab5c704c14cd949e5e9a1ec5929a24fded1b904c" +[[package]] +name = "portable-atomic" +version = "1.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f84267b20a16ea918e43c6a88433c2d54fa145c92a811b5b047ccbe153674483" + [[package]] name = "potential_utf" version = "0.1.2" @@ -1984,6 +2071,21 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "quanta" +version = "0.12.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3ab5a9d756f0d97bdc89019bd2e4ea098cf9cde50ee7564dde6b81ccc8f06c7" +dependencies = [ + "crossbeam-utils", + "libc", + "once_cell", + "raw-cpuid", + "wasi 0.11.1+wasi-snapshot-preview1", + "web-sys", + "winapi", +] + [[package]] name = "quinn" version = "0.11.8" @@ -2119,6 +2221,24 @@ dependencies = [ "getrandom 0.3.3", ] +[[package]] +name = "rand_xoshiro" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41" +dependencies = [ + "rand_core 0.9.3", +] + +[[package]] +name = "raw-cpuid" +version = "11.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "498cd0dc59d73224351ee52a95fee0f1a617a2eae0e7d9d720cc622c73a54186" +dependencies = [ + "bitflags", +] + [[package]] name = "redis" version = "0.32.7" @@ -2617,6 +2737,7 @@ dependencies = [ "argon2", "axum", "axum-extra", + "axum-prometheus", "bb8-redis", "bigdecimal", "dotenvy", @@ -2732,6 +2853,12 @@ dependencies = [ "time", ] +[[package]] +name = "sketches-ddsketch" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c1e9a774a6c28142ac54bb25d25562e6bcf957493a184f15ad4eebccb23e410a" + [[package]] name = "slab" version = "0.4.11" @@ -3945,6 +4072,22 @@ dependencies = [ "wasite", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -3954,6 +4097,12 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + [[package]] name = "windows-core" version = "0.61.2" diff --git a/server/Cargo.toml b/server/Cargo.toml index 966ddae..2ca439f 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -44,4 +44,5 @@ sha2 = "0.10.9" uuid = { version = "1.18.1", features = ["v4"] } bb8-redis = "0.24" redis-macros = "0.5.6" -redis = "0.32.7" \ No newline at end of file +redis = "0.32.7" +axum-prometheus = "0.9.0" \ No newline at end of file diff --git a/server/docker-compose.yml b/server/docker-compose.yml index 01d766f..45b0bff 100644 --- a/server/docker-compose.yml +++ b/server/docker-compose.yml @@ -38,6 +38,30 @@ services: restart: always ports: - "6379:6379" - + + prometheus: + image: prom/prometheus + container_name: prometheus + ports: + - "9091:9090" + command: --config.file=/etc/prometheus/prometheus.yml + volumes: + - ./prometheus.yml:/etc/prometheus/prometheus.yml + extra_hosts: + - "hosts.docker.internal:host-gateway" + + grafana: + image: grafana/grafana:latest + container_name: grafana + restart: always + ports: + - "3000:3000" + environment: + GF_SECURITY_ADMIN_USER: "${GRAFANA_ADMIN_USER}" + GF_SECURITY_ADMIN_PASSWORD: "${GRAFANA_ADMIN_PASSWORD}" + depends_on: + - prometheus + + volumes: pgdata: diff --git a/server/prometheus.yml b/server/prometheus.yml new file mode 100644 index 0000000..4593f50 --- /dev/null +++ b/server/prometheus.yml @@ -0,0 +1,8 @@ +global: + scrape_interval: 5s + evaluation_interval: 30s + +scrape_configs: + - job_name: "paymesh_app_monitoring" + static_configs: + - targets: ["host.docker.internal:8080"] \ No newline at end of file diff --git a/server/src/libs/router.rs b/server/src/libs/router.rs index 8eb72db..8f8ed48 100644 --- a/server/src/libs/router.rs +++ b/server/src/libs/router.rs @@ -3,8 +3,9 @@ use axum::{ http::{ HeaderName, Method, StatusCode, header::{AUTHORIZATION, CONTENT_TYPE}, - }, + }, routing::get, }; +use axum_prometheus::PrometheusMetricLayer; use tower_http::cors::CorsLayer; use utoipa::OpenApi; use utoipa_axum::router::OpenApiRouter; @@ -29,13 +30,17 @@ pub fn router(state: AppState) -> Router { HeaderName::from_static("paymesh-api-key"), ]); + let (prometheus_layer, metric_handle) = PrometheusMetricLayer::pair(); + let (router, api) = OpenApiRouter::with_openapi(ApiDoc::openapi()) .routes(routes!(health::health_check)) .nest("/users", routes::user::router()) .nest("/groups", routes::groups::router()) .nest("/admin", routes::admin::router()) .nest("/crowdfunding", routes::crowd_funding::router()) + .route("/metrics", get(|| async move { metric_handle.render() })) .with_state(state) + .layer(prometheus_layer) .layer(cors) .fallback(|| async { (StatusCode::UNAUTHORIZED, "UNAUTHORIZED ORIGIN") }) .split_for_parts();