030e59e
zhenyi
refactor(lib): migrate storage and security tier to central lib/config (auth, cache, db, email, jwt, payment, queue, rate_limit, storage)
030e59e
use std::sync::Once;
use std::time::Instant;
use metrics::{Unit, counter, describe_counter, describe_histogram, histogram};
pub const OUTCOME_SUCCESS: &str = "success";
pub const OUTCOME_ERROR: &str = "error";
pub const OUTCOME_ACQUIRED: &str = "acquired";
pub const OUTCOME_REJECTED: &str = "rejected";
static DESCRIBE_ONCE: Once = Once::new();
pub fn ensure_described() {
DESCRIBE_ONCE.call_once(describe_all);
}
fn describe_all() {
describe_counter!(
"gitssh_sessions_total",
"SSH client sessions partitioned by outcome (acquired, rejected) when the session semaphore is granted or full."
);
describe_counter!(
"gitssh_exec_total",
"SSH exec requests partitioned by git service and outcome (success, error)."
);
describe_counter!(
"gitssh_subprocess_total",
"Git subprocess runs partitioned by git service and status (success, error)."
);
describe_histogram!(
"gitssh_subprocess_duration_seconds",
Unit::Seconds,
"Duration of git subprocess runs."
);
}
pub(crate) fn outcome(ok: bool) -> &'static str {
if ok { OUTCOME_SUCCESS } else { OUTCOME_ERROR }
}
pub(crate) fn record_session(acquired: bool) {
ensure_described();
counter!(
"gitssh_sessions_total",
"outcome" => if acquired { OUTCOME_ACQUIRED } else { OUTCOME_REJECTED }
)
.increment(1);
}
pub(crate) fn record_exec(service: &'static str, ok: bool) {
ensure_described();
counter!(
"gitssh_exec_total",
"service" => service,
"outcome" => outcome(ok)
)
.increment(1);
}
pub(crate) fn record_subprocess(service: &'static str, ok: bool) {
ensure_described();
counter!(
"gitssh_subprocess_total",
"service" => service,
"status" => outcome(ok)
)
.increment(1);
}
pub(crate) struct SubprocessTimer {
start: Instant,
}
impl SubprocessTimer {
pub(crate) fn start() -> Self {
ensure_described();
Self {
start: Instant::now(),
}
}
}
impl Drop for SubprocessTimer {
fn drop(&mut self) {
histogram!("gitssh_subprocess_duration_seconds").record(self.start.elapsed());
}
}