chore: add loadtest observability setup

This commit is contained in:
kdletters
2026-05-16 22:44:30 +08:00
parent 7f16e88e57
commit 0305b79440
55 changed files with 2867 additions and 1622 deletions

View File

@@ -0,0 +1,75 @@
use std::time::Duration;
use opentelemetry::{KeyValue, global, metrics::Counter};
use crate::SpacetimeClientError;
// SpacetimeDB procedure 指标只使用 procedure / status_class 等低基数字段,避免把用户或作品 ID 写进指标标签。
pub(crate) struct ProcedureMetricsGuard {
procedure: &'static str,
started_at: std::time::Instant,
}
pub(crate) fn begin_procedure(procedure: &'static str) -> ProcedureMetricsGuard {
ProcedureMetricsGuard {
procedure,
started_at: std::time::Instant::now(),
}
}
impl ProcedureMetricsGuard {
pub(crate) fn finish<T>(&self, result: &Result<T, SpacetimeClientError>) {
let duration = self.started_at.elapsed();
record_procedure(self.procedure, duration, result.is_err());
}
}
struct SpacetimeMetrics {
calls: Counter<u64>,
errors: Counter<u64>,
duration_ms: opentelemetry::metrics::Histogram<f64>,
}
fn spacetime_metrics() -> &'static SpacetimeMetrics {
static METRICS: std::sync::OnceLock<SpacetimeMetrics> = std::sync::OnceLock::new();
METRICS.get_or_init(|| {
let meter = global::meter("genarrative-spacetime-client");
SpacetimeMetrics {
calls: meter
.u64_counter("genarrative.spacetime.procedure.calls")
.with_description("SpacetimeDB procedure call count")
.build(),
errors: meter
.u64_counter("genarrative.spacetime.procedure.errors")
.with_description("SpacetimeDB procedure error count")
.build(),
duration_ms: meter
.f64_histogram("genarrative.spacetime.procedure.duration_ms")
.with_unit("ms")
.with_description("SpacetimeDB procedure duration in milliseconds")
.build(),
}
})
}
fn record_procedure(
procedure: &'static str,
duration: Duration,
failed: bool,
) {
let labels = vec![
KeyValue::new("procedure", procedure),
KeyValue::new(
"status_class",
if failed { "error" } else { "ok" },
),
];
let metrics = spacetime_metrics();
metrics.calls.add(1, &labels);
metrics
.duration_ms
.record(duration.as_secs_f64() * 1000.0, &labels);
if failed {
metrics.errors.add(1, &labels);
}
}