asmo 75a3e6d2c7 Prometheus crate (#883) преди 1 месец
..
src 75a3e6d2c7 Prometheus crate (#883) преди 1 месец
Cargo.toml 75a3e6d2c7 Prometheus crate (#883) преди 1 месец
README.md 75a3e6d2c7 Prometheus crate (#883) преди 1 месец

README.md

CDK Prometheus

A small, focused crate that provides Prometheus metrics for CDK-based services. It bundles a ready-to-use metrics registry, a background HTTP server to expose metrics, helper functions for common CDK domains (HTTP, auth, Lightning, DB, mint operations), and an ergonomic macro for conditional metrics recording.

  • Out-of-the-box metrics for HTTP, auth, Lightning payments, database, and mint operations
  • Global, lazily-initialized metrics instance you can use anywhere
  • Optional background server to expose metrics on /metrics
  • Re-exports the prometheus crate for custom instrumentation
  • Optional system metrics (feature-gated)

Installation

Add the crate to your Cargo.toml (replace the version as needed):

[dependencies] cdk-prometheus = { version = "0.1", features = ["system-metrics"] }
  • Feature flags:
    • system-metrics: include basic process/system metrics collected periodically.

Note for downstream crates: the provided record_metrics! macro is gated at call-site by a feature named prometheus. If you use that macro, declare a prometheus feature in your application crate and enable it to compile the macro calls into real metrics (otherwise they no-op).

Quick start

Docker

Start Prometheus and Grafana with docker-compose:

docker compose up -d prometheus grafana

Start your mintd

./mintd -w ~/.cdk-mintd

Check Prometheus and Grafana

  • curl localhost:9000/metrics for checking CDK metrics
  • http://localhost:9090/targets?search= checking the prometheus collector (you should see http://host.docker.internal:9000/metrics)
  • http://localhost:3011/d/cdk-mint-dashboard/cdk-mint-dashboard Grafana dashboard (default login: admin/admin)

Rust

Expose a Prometheus endpoint with a default registry and CDK metrics:

use cdk_prometheus::start_default_server_with_metrics;
#[tokio::main] async fn main() -> anyhow::Result<()> { // Starts an HTTP server (default bind and path) and registers CDK metrics into its registry start_default_server_with_metrics().await?; Ok(()) }

Or start it in the background (e.g., from your application bootstrap):

use cdk_prometheus::start_background_server_with_metrics;
fn main() -> anyhow::Result<()> { let _handle = start_background_server_with_metrics()?; // Continue bootstrapping your application... Ok(()) }

Recording metrics

You can record metrics using:

  • The global helpers (simple functions)
  • The global singleton METRICS (direct methods)
  • The record_metrics! macro (conditional recording with an optional instance)

Global helpers

use cdk_prometheus::global;
fn handle_request() { 
    global::record_http_request("/health", "200"); global::record_http_request_duration(0.003, "/health");
    global::record_auth_attempt();
    global::record_auth_success();
    
    // Lightning and DB
    global::record_lightning_payment(1500.0, 2.0); // amount, fee (both in base units you track)
    global::record_db_operation(0.015, "select_user");
    global::set_db_connections_active(8);
    
    // Mint operations
    global::inc_in_flight_requests("get_payment_quote");
    // ... do work ...
    global::record_mint_operation("get_payment_quote", true);
    global::record_mint_operation_histogram("get_payment_quote", true, 0.021);
    global::dec_in_flight_requests("get_payment_quote");
    
    // Errors
    global::record_error();
}

Using the global METRICS instance directly

use cdk_prometheus::METRICS;
fn do_db_work() { METRICS.record_db_operation(0.005, "update_user"); }

Using the record_metrics! macro

The macro lets you write grouped calls concisely and optionally pass an instance to use; if no instance is present, it automatically falls back to the global helpers. At call-site, wrap your invocations with a prometheus feature so they can be disabled in minimal builds.

use cdk_prometheus::record_metrics;
fn run_operation(metrics_opt: Option<cdk_prometheus::CdkMetrics>) { // Use instance if present, otherwise fallback to global record_metrics!(metrics_opt => { inc_in_flight_requests("make_payment"); record_mint_operation("make_payment", true); record_mint_operation_histogram("make_payment", true, 0.123); dec_in_flight_requests("make_payment"); });
    // Or call directly on the global helpers
    record_metrics!({
        record_error();
    });
}

Exposing the /metrics endpoint

If you just need sane defaults, use the convenience starters shown above. If you want finer control (bind address, path, system metrics), build the server explicitly:

use cdk_prometheus::{PrometheusBuilder, PrometheusServer, CdkMetrics, prometheus::Registry};
fn build_and_run() -> anyhow::Result<tokio::task::JoinHandle<anyhow::Result<()>>> { // Build a server wired up with the default CDK metrics let server = PrometheusBuilder::new().build_with_cdk_metrics()?; let handle = server.start_background(); Ok(handle) }

Notes:

  • Default bind address and metrics path are set by the server configuration (commonly 127.0.0.1:9090 and /metrics).
  • With system-metrics enabled, the server periodically updates process/system gauges.

What’s included

The default CDK metrics instance (CdkMetrics) registers and maintains counters, histograms, and gauges for common areas:

  • HTTP: request totals, durations
  • Auth: attempts and successes
  • Lightning: payment totals, amounts, fees
  • Database: operation totals, latencies, active connections
  • Mint: operation totals, in-flight gauges, per-operation latencies
  • Errors: a general counter

You can use these immediately through the global helpers or the METRICS instance.

Adding custom metrics

This crate re-exports the prometheus crate and exposes the underlying Registry so you can define and register your own metrics:

use cdk_prometheus::{prometheus, global};
fn register_custom_metric() -> Result<(), prometheus::Error> { let my_counter = prometheus::IntCounter::new("my_counter", "A custom counter")?; let registry = global::registry(); // Arcregistry.register(Box::new(my_counter.clone()))?;
    my_counter.inc();
    Ok(())
}

If you prefer instance-level control:

use std::sync::Arc; use cdk_prometheus::{create_cdk_metrics, prometheus};
fn with_instance() -> anyhow::Result<()> { let metrics = create_cdk_metrics()?; let registry: Arc[prometheus::Registry]() = metrics.registry();
    let hist = prometheus::Histogram::with_opts(
    prometheus::HistogramOpts::new("my_latency_seconds", "My op latency")
)?;
registry.register(Box::new(hist))?;
Ok(())
}

Scraping with Prometheus

Example scrape_config:

scrape_configs:
- job_name: 'cdk' 
  scrape_interval: 15s 
  static_configs:
  - targets: ['127.0.0.1:9090']

If you changed the bind address or path, make sure to update targets or the metrics_path in your Prometheus configuration accordingly.

System metrics (optional)

Enable the system-metrics feature to export basic process/system metrics. The server updates these at a configurable interval.

cdk-prometheus = { version = "0.1", features = ["system-metrics"] }

Error handling

Common error types surfaced by this crate include:

  • Server bind failures
  • Metrics collection/registry errors
  • System metrics collection errors (when enabled)

Handle these at startup and monitor logs during runtime.

Best practices

  • Run the metrics server on localhost or a private interface and use a Prometheus agent/sidecar if needed.
  • Register application-specific metrics early in your bootstrap so they are visible from the first scrape.
  • Use histograms for latencies and size distributions; use counters for event totals; use gauges for in-flight or current-state values.
  • Keep label cardinality bounded.

License

MIT ```