laminar_connectors/postgres/cdc/
metrics.rs1use prometheus::{IntCounter, IntGauge, Registry};
6
7use crate::prom::reg_or_local;
8
9#[derive(Debug, Clone)]
14pub struct PostgresCdcMetrics {
15 pub events_received: IntCounter,
17
18 pub bytes_received: IntCounter,
20
21 pub batches_produced: IntCounter,
23
24 pub inserts: IntCounter,
26
27 pub updates: IntCounter,
29
30 pub deletes: IntCounter,
32
33 pub transactions: IntCounter,
35
36 pub confirmed_flush_lsn: IntGauge,
38
39 pub replication_lag_bytes: IntGauge,
41}
42
43impl PostgresCdcMetrics {
44 #[must_use]
50 pub fn new(registry: Option<&Registry>) -> Self {
51 let mut local = None;
52 let reg = reg_or_local(registry, &mut local);
53
54 Self {
55 events_received: reg.counter(
56 "postgres_cdc_events_received_total",
57 "Total CDC change events received",
58 ),
59 bytes_received: reg.counter(
60 "postgres_cdc_bytes_received_total",
61 "Total bytes from WAL stream",
62 ),
63 batches_produced: reg.counter(
64 "postgres_cdc_batches_produced_total",
65 "Total batches produced",
66 ),
67 inserts: reg.counter("postgres_cdc_inserts_total", "Total INSERT events"),
68 updates: reg.counter("postgres_cdc_updates_total", "Total UPDATE events"),
69 deletes: reg.counter("postgres_cdc_deletes_total", "Total DELETE events"),
70 transactions: reg.counter(
71 "postgres_cdc_transactions_total",
72 "Total transactions received",
73 ),
74 confirmed_flush_lsn: reg.gauge(
75 "postgres_cdc_confirmed_flush_lsn",
76 "Current confirmed flush LSN",
77 ),
78 replication_lag_bytes: reg.gauge(
79 "postgres_cdc_replication_lag_bytes",
80 "Replication lag in bytes",
81 ),
82 }
83 }
84
85 pub fn record_insert(&self) {
87 self.inserts.inc();
88 self.events_received.inc();
89 }
90
91 pub fn record_update(&self) {
93 self.updates.inc();
94 self.events_received.inc();
95 }
96
97 pub fn record_delete(&self) {
99 self.deletes.inc();
100 self.events_received.inc();
101 }
102
103 pub fn record_transaction(&self) {
105 self.transactions.inc();
106 }
107
108 pub fn record_bytes(&self, bytes: u64) {
110 self.bytes_received.inc_by(bytes);
111 }
112
113 pub fn record_batch(&self) {
115 self.batches_produced.inc();
116 }
117
118 pub fn set_confirmed_flush_lsn(&self, lsn: u64) {
120 self.confirmed_flush_lsn
121 .set(i64::from_ne_bytes(lsn.to_ne_bytes()));
122 }
123
124 pub fn set_replication_lag_bytes(&self, lag: u64) {
126 self.replication_lag_bytes
127 .set(i64::from_ne_bytes(lag.to_ne_bytes()));
128 }
129}
130
131impl Default for PostgresCdcMetrics {
132 fn default() -> Self {
133 Self::new(None)
134 }
135}
136
137#[cfg(test)]
138mod tests {
139 use super::*;
140
141 #[test]
142 fn test_record_operations() {
143 let m = PostgresCdcMetrics::new(None);
144 m.record_insert();
145 m.record_insert();
146 m.record_update();
147 m.record_delete();
148 m.record_transaction();
149 m.record_bytes(1024);
150 m.record_batch();
151
152 assert_eq!(m.events_received.get(), 4);
153 assert_eq!(m.inserts.get(), 2);
154 assert_eq!(m.updates.get(), 1);
155 assert_eq!(m.deletes.get(), 1);
156 assert_eq!(m.transactions.get(), 1);
157 assert_eq!(m.bytes_received.get(), 1024);
158 assert_eq!(m.batches_produced.get(), 1);
159 }
160
161 #[test]
162 fn test_lsn_and_lag_tracking() {
163 let m = PostgresCdcMetrics::new(None);
164 m.set_confirmed_flush_lsn(0x1234_ABCD);
165 m.set_replication_lag_bytes(4096);
166
167 assert_eq!(m.confirmed_flush_lsn.get(), 0x1234_ABCD_i64);
168 assert_eq!(m.replication_lag_bytes.get(), 4096);
169 }
170}