use std::time::Instant;
use metrale_telemetry::Telemetry;
use metrale_telemetry::request::RequestTiming;
use metrale_telemetry::sched::SchedShape;
use metrale_speculative::snapshot::{SchedulerSnapshot, SnapshotCell};
use metrale_speculative::spec_stats::SpecStats;
use crate::scheduler::dumps::RunDumps;
use crate::scheduler::mtp_timing::{Phase, RunTiming, StepTimer, step_done};
pub trait TelemetryIo: Send + Sync + std::fmt::Debug {
fn mark(&self, phase: Phase, since: Instant);
fn step_timer(&self, seq_len: usize) -> StepTimer<'_>;
fn step_done(&self, step_start: Instant, seq_len: usize);
fn stats(&self) -> &SpecStats;
fn dumps(&self) -> &RunDumps;
fn publish(&self, snapshot: SchedulerSnapshot);
fn count_spec_verify(&self, mode: &str, outcome: &str);
fn enabled(&self) -> bool;
fn spec_verified(&self, drafts: usize, accepted: usize);
fn spec_draft_confidence(&self, lp: f32, accepted: bool);
fn tokens(&self, n: u64);
fn request_finished(&self, timing: RequestTiming);
fn finished_output_tokens(&self) -> u64;
fn step_begin(&self);
fn lane_begin(&self, lane: usize);
fn lane_end(&self, lane: usize);
}
pub struct SysTelemetry {
tel: &'static Telemetry,
timing: RunTiming,
stats: SpecStats,
dumps: RunDumps,
snapshot: std::sync::Arc<SnapshotCell>,
}
impl SysTelemetry {
pub fn from_env(tel: &'static Telemetry, snapshot: std::sync::Arc<SnapshotCell>) -> Self {
Self {
tel,
timing: RunTiming::from_env(),
stats: SpecStats::new(),
dumps: RunDumps::from_env(),
snapshot,
}
}
pub fn quiet(snapshot: std::sync::Arc<SnapshotCell>) -> Self {
static QUIET: Telemetry = Telemetry::new(&metrale_telemetry::clock::MonotonicClock);
Self {
tel: &QUIET,
timing: RunTiming::default(),
stats: SpecStats::new(),
dumps: RunDumps::default(),
snapshot,
}
}
}
impl std::fmt::Debug for SysTelemetry {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("SysTelemetry")
.field("timing", &self.timing)
.field("stats", &self.stats)
.field("dumps", &self.dumps)
.finish_non_exhaustive()
}
}
impl TelemetryIo for SysTelemetry {
fn mark(&self, phase: Phase, since: Instant) {
self.timing.record(phase, since);
self.tel.phase(phase as usize, since);
}
fn step_timer(&self, seq_len: usize) -> StepTimer<'_> {
StepTimer::new(&self.timing, seq_len)
}
fn step_done(&self, step_start: Instant, seq_len: usize) {
step_done(&self.timing, step_start, seq_len);
}
fn stats(&self) -> &SpecStats {
&self.stats
}
fn dumps(&self) -> &RunDumps {
&self.dumps
}
fn publish(&self, snapshot: SchedulerSnapshot) {
self.tel.sched_tick(&SchedShape {
pending: u64::from(snapshot.pending_len),
active: u64::from(snapshot.active_seqs),
prefilling: u64::from(snapshot.prefilling_seqs),
swapped: u64::from(snapshot.swapped_seqs),
kv_blocks_free: u64::from(snapshot.kv_blocks_free),
kv_blocks_total: u64::from(snapshot.kv_blocks_total),
ssm_slots_used: u64::from(snapshot.ssm_slots_used),
ssm_slots_total: u64::from(snapshot.ssm_slots_total),
ticks: snapshot.steps_total,
});
self.snapshot.publish(snapshot);
}
fn count_spec_verify(&self, mode: &str, outcome: &str) {
crate::metrics::SPEC_DECODE_VERIFY
.with_label_values(&[mode, outcome])
.inc();
}
fn enabled(&self) -> bool {
self.tel.level() != metrale_telemetry::Level::Off
}
fn spec_verified(&self, drafts: usize, accepted: usize) {
self.tel.spec_verified(drafts, accepted);
}
fn spec_draft_confidence(&self, lp: f32, accepted: bool) {
self.tel.spec_draft_confidence(lp, accepted);
}
fn tokens(&self, n: u64) {
self.tel.tokens(n);
}
fn request_finished(&self, timing: RequestTiming) {
self.tel.request_finished(&timing);
}
fn finished_output_tokens(&self) -> u64 {
self.tel.requests.output_tokens.get()
}
fn step_begin(&self) {
if self.tel.lane_spans() {
metrale_gpu_runtime::timing::harvest();
self.tel.step_begin();
}
}
fn lane_begin(&self, lane: usize) {
if self.tel.lane_spans() {
#[cfg(feature = "nvtx")]
metrale_telemetry::kernel::nvtx_push_lane(lane);
metrale_gpu_runtime::timing::lane_begin(lane);
}
}
fn lane_end(&self, lane: usize) {
if self.tel.lane_spans() {
metrale_gpu_runtime::timing::lane_end(lane);
#[cfg(feature = "nvtx")]
metrale_telemetry::kernel::nvtx_pop();
}
}
}