#[cfg(not(native_cache))]
use super::disabled as session;
#[cfg(native_cache)]
use super::session;
use alloc::string::String;
use core::time::Duration;
use serde::{Deserialize, Serialize};
pub const ROOT: &str = "records/v1";
pub const SESSIONS: &str = "records/v1/sessions";
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
#[serde(rename_all = "snake_case")]
#[repr(u8)]
pub enum RecordLevel {
Off = 0,
#[default]
Basic = 1,
Full = 2,
}
#[derive(Debug, Clone, Copy, Default, PartialEq, Eq, Serialize, Deserialize)]
pub struct RecordsConfig {
#[serde(default)]
pub level: RecordLevel,
#[serde(default)]
pub keep_sessions: Option<u32>,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum RecordEffect {
Changed,
Observed,
}
pub trait Record {
const KIND: &'static str;
fn namespace() -> String {
alloc::format!("{ROOT}/{}", Self::KIND.trim_matches('/'))
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
#[serde(transparent)]
pub struct SessionId(pub u64);
impl core::fmt::Display for SessionId {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
write!(f, "{}", self.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
pub struct Session {
pub id: SessionId,
pub started_unix_ms: u64,
pub cubecl_version: String,
pub label: Option<String>,
pub process: u32,
pub os: String,
pub arch: String,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
pub struct Stamp {
pub session: SessionId,
pub seq: u64,
pub offset: Duration,
}
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Stamped<V> {
pub stamp: Stamp,
pub record: V,
}
pub fn configure(config: RecordsConfig) {
session::configure(config);
}
pub fn level() -> RecordLevel {
session::level()
}
pub fn enabled() -> bool {
level() != RecordLevel::Off
}
pub fn label<S: Into<String>>(label: S) {
session::label(label.into());
}
pub fn write<R: Record + Serialize>(effect: RecordEffect, record: &R) -> Option<Stamp> {
let stamp = session::stamp()?;
write_stamped(stamp, effect, record).then_some(stamp)
}
pub(crate) fn write_stamped<R: Record + Serialize>(
stamp: Stamp,
effect: RecordEffect,
record: &R,
) -> bool {
let namespace = R::namespace();
debug_assert_ne!(namespace, SESSIONS, "`sessions` is not a record kind");
session::write(&namespace, effect, &Stamped { stamp, record })
}