Skip to main content

liquid_cache/cache/observer/
stats.rs

1use std::fmt;
2use std::path::PathBuf;
3use std::sync::atomic::{AtomicU64, Ordering};
4
5/// Macro to define runtime statistics metrics.
6///
7/// Usage:
8/// ```ignore
9/// define_runtime_stats! {
10///     (field_name, "doc comment", method_name),
11///     ...
12/// }
13/// ```
14///
15/// This generates:
16/// - Fields in `RuntimeStats` struct
17/// - Fields in `RuntimeStatsSnapshot` struct
18/// - Increment methods (`incr_*`)
19/// - `consume_snapshot` implementation
20/// - `reset` implementation
21macro_rules! define_runtime_stats {
22    (
23        $(
24            ($field:ident, $doc:literal, $method:ident)
25        ),* $(,)?
26    ) => {
27        /// Atomic runtime counters for cache API calls.
28        #[derive(Debug, Default)]
29        pub struct RuntimeStats {
30            $(
31                #[doc = $doc]
32                pub(crate) $field: AtomicU64,
33            )*
34        }
35
36        /// Immutable snapshot of [`RuntimeStats`].
37        #[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize)]
38        pub struct RuntimeStatsSnapshot {
39            $(
40                #[doc = concat!("Total ", stringify!($field), ".")]
41                pub $field: u64,
42            )*
43        }
44
45        impl RuntimeStats {
46            /// Return an immutable snapshot of the current runtime counters and reset the stats to 0.
47            pub fn consume_snapshot(&self) -> RuntimeStatsSnapshot {
48                let v = RuntimeStatsSnapshot {
49                    $(
50                        $field: self.$field.load(Ordering::Relaxed),
51                    )*
52                };
53                self.reset();
54                v
55            }
56
57            $(
58                /// Increment counter.
59                #[inline]
60                pub fn $method(&self) {
61                    self.$field.fetch_add(1, Ordering::Relaxed);
62                }
63            )*
64
65            /// Reset the runtime stats to 0.
66            pub fn reset(&self) {
67                $(
68                    self.$field.store(0, Ordering::Relaxed);
69                )*
70            }
71        }
72
73        impl fmt::Display for RuntimeStats {
74            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
75                writeln!(f, "RuntimeStats:")?;
76                $(
77                    writeln!(f, "  {}: {}", stringify!($field), self.$field.load(Ordering::Relaxed))?;
78                )*
79                Ok(())
80            }
81        }
82
83        impl fmt::Display for RuntimeStatsSnapshot {
84            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
85                writeln!(f, "RuntimeStatsSnapshot:")?;
86                $(
87                    writeln!(f, "  {}: {}", stringify!($field), self.$field)?;
88                )*
89                Ok(())
90            }
91        }
92    };
93}
94
95// Define all runtime statistics metrics here.
96// To add a new metric, add a line: (field_name, "doc comment", method_name)
97define_runtime_stats! {
98    (get, "Number of `get` calls issued via `CachedData`.", incr_get),
99    (get_with_selection, "Number of `get_with_selection` calls issued via `CachedData`.", incr_get_with_selection),
100    (eval_predicate, "Number of `eval_predicate` calls issued via `CachedData`.", incr_eval_predicate),
101    (get_squeezed_success, "Number of Squeezed-Liquid full evaluations finished without IO.", incr_get_squeezed_success),
102    (get_squeezed_needs_io, "Number of Squeezed-Liquid full paths that required IO.", incr_get_squeezed_needs_io),
103    (try_read_liquid_calls, "Number of `try_read_liquid` calls issued via `CachedData`.", incr_try_read_liquid),
104    (hit_date32_expression_calls, "Number of `hit_date32_expression` calls.", incr_hit_date32_expression),
105    (read_io_count, "Number of read IO operations.", incr_read_io_count),
106    (write_io_count, "Number of write IO operations.", incr_write_io_count),
107    (eval_predicate_on_liquid_failed, "Number of `eval_predicate` calls that failed on Liquid array.", incr_eval_predicate_on_liquid_failed),
108    (squeezed_decompressed_count, "Number of decompressed Squeezed-Liquid entries.", __incr_squeezed_decompressed_count),
109    (squeezed_total_count, "Total number of Squeezed-Liquid entries.", __incr_squeezed_total_count),
110    (squeeze_io_saved, "Number of io saved by squeezing.", incr_squeeze_io_saved),
111}
112
113impl RuntimeStats {
114    /// Track the number of decompressed Squeezed-Liquid entries.
115    pub fn track_decompress_squeezed_count(&self, decompressed: usize, total: usize) {
116        self.squeezed_decompressed_count
117            .fetch_add(decompressed as u64, Ordering::Relaxed);
118        self.squeezed_total_count
119            .fetch_add(total as u64, Ordering::Relaxed);
120    }
121}
122
123/// Snapshot of cache statistics.
124#[derive(Debug, Clone, serde::Serialize, serde::Deserialize)]
125pub struct CacheStats {
126    /// Total number of entries in the cache.
127    pub total_entries: usize,
128    /// Number of in-memory Arrow entries.
129    pub memory_arrow_entries: usize,
130    /// Number of in-memory Liquid entries.
131    pub memory_liquid_entries: usize,
132    /// Number of in-memory Squeezed-Liquid entries.
133    pub memory_squeezed_liquid_entries: usize,
134    /// Number of on-disk Liquid entries.
135    pub disk_liquid_entries: usize,
136    /// Number of on-disk Arrow entries.
137    pub disk_arrow_entries: usize,
138    /// Total size of in-memory Arrow entries in bytes.
139    pub memory_arrow_bytes: usize,
140    /// Total size of in-memory Liquid entries in bytes.
141    pub memory_liquid_bytes: usize,
142    /// Total size of in-memory Squeezed-Liquid entries in bytes.
143    pub memory_squeezed_liquid_bytes: usize,
144    /// Total memory usage of the cache.
145    pub memory_usage_bytes: usize,
146    /// Total disk usage of the cache.
147    pub disk_usage_bytes: usize,
148    /// Maximum cache size.
149    pub max_cache_bytes: usize,
150    /// Cache root directory.
151    pub cache_root_dir: PathBuf,
152    /// Runtime counters snapshot.
153    pub runtime: RuntimeStatsSnapshot,
154}