diff --git a/Cargo.lock b/Cargo.lock index fe2d102..710eca7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2538,6 +2538,7 @@ dependencies = [ "config", "db", "hyper 0.14.32", + "metrics", "metrics-exporter-prometheus", "observability", "sea-orm", @@ -3130,6 +3131,7 @@ dependencies = [ "db", "git", "hyper 0.14.32", + "metrics", "metrics-exporter-prometheus", "observability", "reqwest 0.13.2", diff --git a/apps/email/Cargo.toml b/apps/email/Cargo.toml index 433d94d..900e792 100644 --- a/apps/email/Cargo.toml +++ b/apps/email/Cargo.toml @@ -29,6 +29,7 @@ chrono = { workspace = true, features = ["serde"] } hyper = { workspace = true } serde_json = { workspace = true } sea-orm = { workspace = true } +metrics = "0.22" metrics-exporter-prometheus = "0.13" [lints] diff --git a/apps/email/src/main.rs b/apps/email/src/main.rs index 0a8faf2..8e4b168 100644 --- a/apps/email/src/main.rs +++ b/apps/email/src/main.rs @@ -1,5 +1,6 @@ use clap::Parser; use config::AppConfig; +use metrics::{describe_counter, Unit}; use metrics_exporter_prometheus::PrometheusHandle; use observability::{init_tracing_subscriber, install_recorder}; use sea_orm::ConnectionTrait; @@ -64,6 +65,17 @@ async fn main() -> anyhow::Result<()> { let args = Args::parse(); let cfg = AppConfig::load(); init_tracing_subscriber(&args.log_level, false); + + // Pre-register all email/queue metrics so they appear in /metrics even before first event. + describe_counter!("email_queued_total", Unit::Count, "Emails written to Redis stream"); + describe_counter!("email_consumed_total", Unit::Count, "Emails consumed from queue"); + describe_counter!("email_batch_size", Unit::Count, "Email consumer batch sizes accumulated"); + describe_counter!("email_validation_skipped_total", Unit::Count, "Emails skipped due to invalid recipient"); + describe_counter!("email_build_errors_total", Unit::Count, "Email message build failures"); + describe_counter!("email_send_attempts_total", Unit::Count, "SMTP send attempts (including retries)"); + describe_counter!("email_sent_total", Unit::Count, "Emails sent successfully"); + describe_counter!("email_send_failures_total", Unit::Count, "Emails that failed after all retries"); + let metrics_handle = Arc::new(install_recorder()); tracing::info!("Starting email worker"); diff --git a/apps/git-hook/Cargo.toml b/apps/git-hook/Cargo.toml index bec78a0..04354fa 100644 --- a/apps/git-hook/Cargo.toml +++ b/apps/git-hook/Cargo.toml @@ -26,6 +26,7 @@ tokio-util = { workspace = true } hyper = { workspace = true } serde_json = { workspace = true } sea-orm = { workspace = true } +metrics = "0.22" metrics-exporter-prometheus = "0.13" chrono = { workspace = true, features = ["serde"] } reqwest = { workspace = true } diff --git a/apps/git-hook/src/main.rs b/apps/git-hook/src/main.rs index cff90e9..209a3c1 100644 --- a/apps/git-hook/src/main.rs +++ b/apps/git-hook/src/main.rs @@ -3,6 +3,7 @@ use config::AppConfig; use db::cache::AppCache; use db::database::AppDatabase; use git::hook::HookService; +use metrics::{describe_counter, Unit}; use metrics_exporter_prometheus::PrometheusHandle; use observability::{init_tracing_subscriber, install_recorder}; use sea_orm::ConnectionTrait; @@ -66,6 +67,17 @@ async fn main() -> anyhow::Result<()> { // 2. Init tracing + metrics let log_level = cfg.log_level().unwrap_or_else(|_| "info".to_string()); init_tracing_subscriber(&log_level, false); + + // Pre-register all hook metrics so they appear in /metrics even before first increment. + describe_counter!("hook_tasks_total", Unit::Count, "Total hook tasks dequeued"); + describe_counter!("hook_tasks_success_total", Unit::Count, "Hook tasks completed successfully"); + describe_counter!("hook_tasks_failed_total", Unit::Count, "Hook tasks that failed"); + describe_counter!("hook_tasks_locked_total", Unit::Count, "Hook tasks re-queued due to repo lock"); + describe_counter!("hook_tasks_retried_total", Unit::Count, "Hook tasks that entered retry"); + describe_counter!("hook_tasks_exhausted_total", Unit::Count, "Hook tasks that exhausted retries"); + describe_counter!("hook_sync_branches_changed_total", Unit::Count, "Branches changed during sync"); + describe_counter!("hook_sync_tags_changed_total", Unit::Count, "Tags changed during sync"); + let metrics_handle = Arc::new(install_recorder()); // 3. Connect to database