Skip to main content

wp_knowledge/
telemetry.rs

1use std::sync::{Arc, OnceLock, RwLock};
2use std::time::Duration;
3
4use crate::loader::ProviderKind;
5use crate::runtime::QueryModeTag;
6
7#[derive(Debug, Clone, Copy, PartialEq, Eq)]
8pub enum CacheLayer {
9    Local,
10    Result,
11    Metadata,
12}
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15pub enum CacheOutcome {
16    Hit,
17    Miss,
18}
19
20#[derive(Debug, Clone)]
21pub struct CacheTelemetryEvent {
22    pub layer: CacheLayer,
23    pub outcome: CacheOutcome,
24    pub provider_kind: Option<ProviderKind>,
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq)]
28pub enum ReloadOutcome {
29    Success,
30    Failure,
31}
32
33#[derive(Debug, Clone)]
34pub struct ReloadTelemetryEvent {
35    pub outcome: ReloadOutcome,
36    pub provider_kind: ProviderKind,
37}
38
39#[derive(Debug, Clone)]
40pub struct QueryTelemetryEvent {
41    pub provider_kind: ProviderKind,
42    pub mode: QueryModeTag,
43    pub success: bool,
44    pub elapsed: Duration,
45}
46
47pub trait KnowledgeTelemetry: Send + Sync {
48    fn on_cache(&self, _event: &CacheTelemetryEvent) {}
49    fn on_reload(&self, _event: &ReloadTelemetryEvent) {}
50    fn on_query(&self, _event: &QueryTelemetryEvent) {}
51}
52
53#[derive(Debug, Default)]
54pub struct NoopTelemetry;
55
56impl KnowledgeTelemetry for NoopTelemetry {}
57
58fn telemetry_slot() -> &'static RwLock<Arc<dyn KnowledgeTelemetry>> {
59    static SLOT: OnceLock<RwLock<Arc<dyn KnowledgeTelemetry>>> = OnceLock::new();
60    SLOT.get_or_init(|| RwLock::new(Arc::new(NoopTelemetry)))
61}
62
63pub fn telemetry() -> Arc<dyn KnowledgeTelemetry> {
64    telemetry_slot()
65        .read()
66        .expect("knowledge telemetry lock poisoned")
67        .clone()
68}
69
70pub fn install_telemetry(telemetry: Arc<dyn KnowledgeTelemetry>) -> Arc<dyn KnowledgeTelemetry> {
71    let mut guard = telemetry_slot()
72        .write()
73        .expect("knowledge telemetry lock poisoned");
74    std::mem::replace(&mut *guard, telemetry)
75}
76
77pub fn reset_telemetry() -> Arc<dyn KnowledgeTelemetry> {
78    install_telemetry(Arc::new(NoopTelemetry))
79}