1use crate::monitoring::metrics::DbxMetrics;
7
8pub fn export_prometheus(metrics: &DbxMetrics) -> String {
20 let mut out = String::with_capacity(4096);
21 let snap = metrics.snapshot();
22
23 append_counter(
25 &mut out,
26 "dbx_inserts_total",
27 snap.inserts_total,
28 "Total number of INSERT operations",
29 );
30 append_counter(
31 &mut out,
32 "dbx_gets_total",
33 snap.gets_total,
34 "Total number of GET operations",
35 );
36 append_counter(
37 &mut out,
38 "dbx_deletes_total",
39 snap.deletes_total,
40 "Total number of DELETE operations",
41 );
42 append_counter(
43 &mut out,
44 "dbx_sql_queries_total",
45 snap.sql_queries_total,
46 "Total number of SQL queries executed",
47 );
48 append_counter(
49 &mut out,
50 "dbx_flush_total",
51 snap.flush_total,
52 "Total number of Delta Store flush operations",
53 );
54
55 append_counter(
57 &mut out,
58 "dbx_delta_hits_total",
59 snap.delta_hits,
60 "Cache hits in Tier 1 (Delta Store)",
61 );
62 append_counter(
63 &mut out,
64 "dbx_delta_misses_total",
65 snap.delta_misses,
66 "Cache misses in Tier 1 (Delta Store)",
67 );
68 append_gauge_f64(
69 &mut out,
70 "dbx_delta_hit_rate",
71 snap.delta_hit_rate,
72 "Hit rate of Tier 1 Delta Store (0.0 - 1.0)",
73 );
74
75 append_counter(
76 &mut out,
77 "dbx_cache_hits_total",
78 snap.cache_hits,
79 "Cache hits in Tier 2 (Columnar Cache)",
80 );
81 append_counter(
82 &mut out,
83 "dbx_cache_misses_total",
84 snap.cache_misses,
85 "Cache misses in Tier 2 (Columnar Cache)",
86 );
87 append_gauge_f64(
88 &mut out,
89 "dbx_cache_hit_rate",
90 snap.cache_hit_rate,
91 "Hit rate of Tier 2 Columnar Cache (0.0 - 1.0)",
92 );
93
94 append_counter(
95 &mut out,
96 "dbx_wos_hits_total",
97 snap.wos_hits,
98 "Cache hits in Tier 3 (Write-Optimized Store)",
99 );
100 append_counter(
101 &mut out,
102 "dbx_wos_misses_total",
103 snap.wos_misses,
104 "Cache misses in Tier 3 (Write-Optimized Store)",
105 );
106 append_gauge_f64(
107 &mut out,
108 "dbx_wos_hit_rate",
109 snap.wos_hit_rate,
110 "Hit rate of Tier 3 WOS (0.0 - 1.0)",
111 );
112
113 append_counter(
115 &mut out,
116 "dbx_scatter_writes_total",
117 snap.scatter_writes_total,
118 "Total number of scatter write operations (sharding)",
119 );
120 append_counter(
121 &mut out,
122 "dbx_scatter_reads_total",
123 snap.scatter_reads_total,
124 "Total number of scatter read operations (sharding)",
125 );
126
127 append_counter(
129 &mut out,
130 "dbx_partition_prune_hits_total",
131 snap.partition_prune_hits,
132 "Total number of partition pruning hits",
133 );
134
135 append_counter(
137 &mut out,
138 "dbx_wal_appends_total",
139 snap.wal_appends_total,
140 "Total number of WAL append operations",
141 );
142 append_counter(
143 &mut out,
144 "dbx_wal_compactions_total",
145 snap.wal_compactions_total,
146 "Total number of WAL compaction operations",
147 );
148
149 append_gauge(
151 &mut out,
152 "dbx_avg_query_latency_us",
153 snap.avg_query_latency_us,
154 "Average SQL query latency in microseconds",
155 );
156 append_gauge(
157 &mut out,
158 "dbx_avg_insert_latency_us",
159 snap.avg_insert_latency_us,
160 "Average INSERT latency in microseconds",
161 );
162
163 metrics.query_latency_us.export_prometheus(&mut out);
165 metrics.insert_latency_us.export_prometheus(&mut out);
166
167 out
168}
169
170fn append_counter(out: &mut String, name: &str, value: u64, help: &str) {
171 out.push_str(&format!("# HELP {name} {help}\n"));
172 out.push_str(&format!("# TYPE {name} counter\n"));
173 out.push_str(&format!("{name} {value}\n\n"));
174}
175
176fn append_gauge(out: &mut String, name: &str, value: u64, help: &str) {
177 out.push_str(&format!("# HELP {name} {help}\n"));
178 out.push_str(&format!("# TYPE {name} gauge\n"));
179 out.push_str(&format!("{name} {value}\n\n"));
180}
181
182fn append_gauge_f64(out: &mut String, name: &str, value: f64, help: &str) {
183 out.push_str(&format!("# HELP {name} {help}\n"));
184 out.push_str(&format!("# TYPE {name} gauge\n"));
185 out.push_str(&format!("{name} {:.4}\n\n", value));
186}
187
188#[cfg(test)]
189mod tests {
190 use super::*;
191
192 #[test]
193 fn test_prometheus_format() {
194 let m = DbxMetrics::new();
195 m.inc_inserts();
196 m.inc_inserts();
197 m.inc_sql_queries();
198 m.query_latency_us.observe(500);
199
200 let output = export_prometheus(&m);
201
202 assert!(
203 output.contains("dbx_inserts_total 2"),
204 "inserts_total should be 2"
205 );
206 assert!(
207 output.contains("dbx_sql_queries_total 1"),
208 "sql_queries_total should be 1"
209 );
210 assert!(output.contains("# TYPE dbx_inserts_total counter"));
211 assert!(output.contains("# TYPE dbx_cache_hit_rate gauge"));
212 assert!(output.contains("# TYPE dbx_query_latency_us histogram"));
213 assert!(output.contains("dbx_query_latency_us_count 1"));
214 }
215
216 #[test]
217 fn test_hit_rate_export() {
218 let m = DbxMetrics::new();
219 m.inc_cache_hit();
220 m.inc_cache_hit();
221 m.inc_cache_miss();
222
223 let output = export_prometheus(&m);
224 assert!(output.contains("dbx_cache_hit_rate 0.6667"));
226 }
227}