fix(hooks,email): add describe_counter! to pre-register metrics
Some checks are pending
CI / Rust Lint & Check (push) Waiting to run
CI / Rust Tests (push) Waiting to run
CI / Frontend Lint & Type Check (push) Waiting to run
CI / Frontend Build (push) Blocked by required conditions

Hook tasks and email metrics were missing from /metrics because
describe_counter! was never called before install_recorder(), so
unincremented counters were not exported. Room metrics appeared
because RoomMetrics::new() already described them.

- apps/git-hook: describe 8 hook_tasks_*/hook_sync_* counters
- apps/email: describe 8 email_* counters
- both: add metrics = "0.22" as direct dependency
This commit is contained in:
ZhenYi 2026-04-26 00:42:59 +08:00
parent 02b7a5beda
commit 468007177f
5 changed files with 28 additions and 0 deletions

2
Cargo.lock generated
View File

@ -2538,6 +2538,7 @@ dependencies = [
"config", "config",
"db", "db",
"hyper 0.14.32", "hyper 0.14.32",
"metrics",
"metrics-exporter-prometheus", "metrics-exporter-prometheus",
"observability", "observability",
"sea-orm", "sea-orm",
@ -3130,6 +3131,7 @@ dependencies = [
"db", "db",
"git", "git",
"hyper 0.14.32", "hyper 0.14.32",
"metrics",
"metrics-exporter-prometheus", "metrics-exporter-prometheus",
"observability", "observability",
"reqwest 0.13.2", "reqwest 0.13.2",

View File

@ -29,6 +29,7 @@ chrono = { workspace = true, features = ["serde"] }
hyper = { workspace = true } hyper = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
sea-orm = { workspace = true } sea-orm = { workspace = true }
metrics = "0.22"
metrics-exporter-prometheus = "0.13" metrics-exporter-prometheus = "0.13"
[lints] [lints]

View File

@ -1,5 +1,6 @@
use clap::Parser; use clap::Parser;
use config::AppConfig; use config::AppConfig;
use metrics::{describe_counter, Unit};
use metrics_exporter_prometheus::PrometheusHandle; use metrics_exporter_prometheus::PrometheusHandle;
use observability::{init_tracing_subscriber, install_recorder}; use observability::{init_tracing_subscriber, install_recorder};
use sea_orm::ConnectionTrait; use sea_orm::ConnectionTrait;
@ -64,6 +65,17 @@ async fn main() -> anyhow::Result<()> {
let args = Args::parse(); let args = Args::parse();
let cfg = AppConfig::load(); let cfg = AppConfig::load();
init_tracing_subscriber(&args.log_level, false); 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()); let metrics_handle = Arc::new(install_recorder());
tracing::info!("Starting email worker"); tracing::info!("Starting email worker");

View File

@ -26,6 +26,7 @@ tokio-util = { workspace = true }
hyper = { workspace = true } hyper = { workspace = true }
serde_json = { workspace = true } serde_json = { workspace = true }
sea-orm = { workspace = true } sea-orm = { workspace = true }
metrics = "0.22"
metrics-exporter-prometheus = "0.13" metrics-exporter-prometheus = "0.13"
chrono = { workspace = true, features = ["serde"] } chrono = { workspace = true, features = ["serde"] }
reqwest = { workspace = true } reqwest = { workspace = true }

View File

@ -3,6 +3,7 @@ use config::AppConfig;
use db::cache::AppCache; use db::cache::AppCache;
use db::database::AppDatabase; use db::database::AppDatabase;
use git::hook::HookService; use git::hook::HookService;
use metrics::{describe_counter, Unit};
use metrics_exporter_prometheus::PrometheusHandle; use metrics_exporter_prometheus::PrometheusHandle;
use observability::{init_tracing_subscriber, install_recorder}; use observability::{init_tracing_subscriber, install_recorder};
use sea_orm::ConnectionTrait; use sea_orm::ConnectionTrait;
@ -66,6 +67,17 @@ async fn main() -> anyhow::Result<()> {
// 2. Init tracing + metrics // 2. Init tracing + metrics
let log_level = cfg.log_level().unwrap_or_else(|_| "info".to_string()); let log_level = cfg.log_level().unwrap_or_else(|_| "info".to_string());
init_tracing_subscriber(&log_level, false); 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()); let metrics_handle = Arc::new(install_recorder());
// 3. Connect to database // 3. Connect to database