laminar_connectors/mongodb/
metrics.rs1use prometheus::{IntCounter, Registry};
6
7use crate::prom::reg_or_local;
8
9#[derive(Debug, Clone)]
11pub struct MongoDbCdcMetrics {
12 pub events_received: IntCounter,
14 pub bytes_received: IntCounter,
16 pub errors: IntCounter,
18 pub batches_produced: IntCounter,
20 pub inserts: IntCounter,
22 pub updates: IntCounter,
24 pub replaces: IntCounter,
26 pub deletes: IntCounter,
28 pub lifecycle_events: IntCounter,
30 pub reconnects: IntCounter,
32}
33
34impl MongoDbCdcMetrics {
35 #[must_use]
37 #[allow(clippy::missing_panics_doc)]
38 pub fn new(registry: Option<&Registry>) -> Self {
39 let mut local = None;
40 let reg = reg_or_local(registry, &mut local);
41
42 Self {
43 events_received: reg.counter(
44 "mongodb_cdc_events_received_total",
45 "Total MongoDB CDC events received",
46 ),
47 bytes_received: reg.counter(
48 "mongodb_cdc_bytes_received_total",
49 "Total bytes from change stream",
50 ),
51 errors: reg.counter("mongodb_cdc_errors_total", "Total MongoDB CDC errors"),
52 batches_produced: reg.counter(
53 "mongodb_cdc_batches_produced_total",
54 "Total batches produced",
55 ),
56 inserts: reg.counter("mongodb_cdc_inserts_total", "Total INSERT events"),
57 updates: reg.counter("mongodb_cdc_updates_total", "Total UPDATE events"),
58 replaces: reg.counter("mongodb_cdc_replaces_total", "Total REPLACE events"),
59 deletes: reg.counter("mongodb_cdc_deletes_total", "Total DELETE events"),
60 lifecycle_events: reg.counter(
61 "mongodb_cdc_lifecycle_events_total",
62 "Total lifecycle events",
63 ),
64 reconnects: reg.counter(
65 "mongodb_cdc_reconnects_total",
66 "Total reconnection attempts",
67 ),
68 }
69 }
70
71 pub fn record_event(&self, op: &str) {
73 self.events_received.inc();
74 match op {
75 "I" => self.inserts.inc(),
76 "U" => self.updates.inc(),
77 "R" => self.replaces.inc(),
78 "D" => self.deletes.inc(),
79 _ => self.lifecycle_events.inc(),
80 }
81 }
82
83 pub fn record_bytes(&self, bytes: u64) {
85 self.bytes_received.inc_by(bytes);
86 }
87
88 pub fn record_error(&self) {
90 self.errors.inc();
91 }
92
93 pub fn record_batch(&self) {
95 self.batches_produced.inc();
96 }
97
98 pub fn record_reconnect(&self) {
100 self.reconnects.inc();
101 }
102}
103
104impl Default for MongoDbCdcMetrics {
105 fn default() -> Self {
106 Self::new(None)
107 }
108}
109
110#[derive(Debug, Clone)]
112pub struct MongoDbSinkMetrics {
113 pub records_written: IntCounter,
115 pub bytes_written: IntCounter,
117 pub errors: IntCounter,
119 pub batches_flushed: IntCounter,
121 pub bulk_writes: IntCounter,
123 pub inserts: IntCounter,
125 pub upserts: IntCounter,
127 pub deletes: IntCounter,
129}
130
131impl MongoDbSinkMetrics {
132 #[must_use]
134 #[allow(clippy::missing_panics_doc)]
135 pub fn new(registry: Option<&Registry>) -> Self {
136 let mut local = None;
137 let reg = reg_or_local(registry, &mut local);
138
139 Self {
140 records_written: reg.counter(
141 "mongodb_sink_records_written_total",
142 "Total MongoDB sink records written",
143 ),
144 bytes_written: reg.counter(
145 "mongodb_sink_bytes_written_total",
146 "Total MongoDB sink bytes written",
147 ),
148 errors: reg.counter("mongodb_sink_errors_total", "Total MongoDB sink errors"),
149 batches_flushed: reg.counter(
150 "mongodb_sink_batches_flushed_total",
151 "Total batches flushed",
152 ),
153 bulk_writes: reg.counter(
154 "mongodb_sink_bulk_writes_total",
155 "Total bulk write operations",
156 ),
157 inserts: reg.counter("mongodb_sink_inserts_total", "Total insert operations"),
158 upserts: reg.counter("mongodb_sink_upserts_total", "Total upsert operations"),
159 deletes: reg.counter("mongodb_sink_deletes_total", "Total delete operations"),
160 }
161 }
162
163 pub fn record_flush(&self, records: u64, bytes: u64) {
165 self.records_written.inc_by(records);
166 self.bytes_written.inc_by(bytes);
167 self.batches_flushed.inc();
168 }
169
170 pub fn record_bulk_write(&self) {
172 self.bulk_writes.inc();
173 }
174
175 pub fn record_error(&self) {
177 self.errors.inc();
178 }
179
180 pub fn record_inserts(&self, count: u64) {
182 self.inserts.inc_by(count);
183 }
184
185 pub fn record_upserts(&self, count: u64) {
187 self.upserts.inc_by(count);
188 }
189
190 pub fn record_deletes(&self, count: u64) {
192 self.deletes.inc_by(count);
193 }
194}
195
196impl Default for MongoDbSinkMetrics {
197 fn default() -> Self {
198 Self::new(None)
199 }
200}
201
202#[cfg(test)]
203mod tests {
204 use super::*;
205
206 #[test]
207 fn test_source_metrics_record_events() {
208 let m = MongoDbCdcMetrics::new(None);
209 m.record_event("I");
210 m.record_event("I");
211 m.record_event("U");
212 m.record_event("D");
213 m.record_event("DROP");
214 m.record_bytes(1024);
215 m.record_error();
216 m.record_batch();
217 m.record_reconnect();
218
219 assert_eq!(m.events_received.get(), 5);
220 assert_eq!(m.inserts.get(), 2);
221 assert_eq!(m.updates.get(), 1);
222 assert_eq!(m.deletes.get(), 1);
223 assert_eq!(m.lifecycle_events.get(), 1);
224 assert_eq!(m.bytes_received.get(), 1024);
225 assert_eq!(m.errors.get(), 1);
226 assert_eq!(m.batches_produced.get(), 1);
227 assert_eq!(m.reconnects.get(), 1);
228 }
229
230 #[test]
231 fn test_sink_metrics_record_flush() {
232 let m = MongoDbSinkMetrics::new(None);
233 m.record_flush(100, 5000);
234 m.record_bulk_write();
235 m.record_inserts(80);
236 m.record_upserts(15);
237 m.record_deletes(5);
238 m.record_error();
239
240 assert_eq!(m.records_written.get(), 100);
241 assert_eq!(m.bytes_written.get(), 5000);
242 assert_eq!(m.batches_flushed.get(), 1);
243 assert_eq!(m.bulk_writes.get(), 1);
244 assert_eq!(m.inserts.get(), 80);
245 assert_eq!(m.upserts.get(), 15);
246 assert_eq!(m.deletes.get(), 5);
247 assert_eq!(m.errors.get(), 1);
248 }
249}