1use lazy_static::lazy_static;
13use prometheus::{
14 opts, register_counter_vec, register_gauge, register_histogram_vec, CounterVec, Encoder, Gauge,
15 HistogramVec, TextEncoder,
16};
17
18lazy_static! {
19 pub static ref HTTP_REQUESTS_TOTAL: CounterVec = register_counter_vec!(
21 opts!(
22 "bindcar_http_requests_total",
23 "Total number of HTTP requests processed"
24 ),
25 &["method", "path", "status"]
26 )
27 .expect("Failed to create HTTP_REQUESTS_TOTAL metric");
28
29 pub static ref HTTP_REQUEST_DURATION_SECONDS: HistogramVec = register_histogram_vec!(
31 "bindcar_http_request_duration_seconds",
32 "HTTP request duration in seconds",
33 &["method", "path"],
34 vec![0.001, 0.005, 0.01, 0.025, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
35 )
36 .expect("Failed to create HTTP_REQUEST_DURATION_SECONDS metric");
37
38 pub static ref ZONE_OPERATIONS_TOTAL: CounterVec = register_counter_vec!(
40 opts!(
41 "bindcar_zone_operations_total",
42 "Total number of zone operations"
43 ),
44 &["operation", "result"]
45 )
46 .expect("Failed to create ZONE_OPERATIONS_TOTAL metric");
47
48 pub static ref RNDC_COMMANDS_TOTAL: CounterVec = register_counter_vec!(
50 opts!(
51 "bindcar_rndc_commands_total",
52 "Total number of RNDC commands executed"
53 ),
54 &["command", "result"]
55 )
56 .expect("Failed to create RNDC_COMMANDS_TOTAL metric");
57
58 pub static ref RNDC_COMMAND_DURATION_SECONDS: HistogramVec = register_histogram_vec!(
60 "bindcar_rndc_command_duration_seconds",
61 "RNDC command execution duration in seconds",
62 &["command"],
63 vec![0.01, 0.05, 0.1, 0.25, 0.5, 1.0, 2.5, 5.0, 10.0]
64 )
65 .expect("Failed to create RNDC_COMMAND_DURATION_SECONDS metric");
66
67 pub static ref ZONES_MANAGED_TOTAL: Gauge = register_gauge!(
69 opts!(
70 "bindcar_zones_managed_total",
71 "Total number of zones currently managed"
72 )
73 )
74 .expect("Failed to create ZONES_MANAGED_TOTAL metric");
75
76 pub static ref APP_INFO: CounterVec = register_counter_vec!(
78 opts!(
79 "bindcar_app_info",
80 "Application information"
81 ),
82 &["version"]
83 )
84 .expect("Failed to create APP_INFO metric");
85
86 pub static ref RATE_LIMIT_REQUESTS_TOTAL: CounterVec = register_counter_vec!(
88 opts!(
89 "bindcar_rate_limit_requests_total",
90 "Total number of rate limit checks"
91 ),
92 &["result"]
93 )
94 .expect("Failed to create RATE_LIMIT_REQUESTS_TOTAL metric");
95}
96
97pub fn init_metrics() {
99 APP_INFO
100 .with_label_values(&[env!("CARGO_PKG_VERSION")])
101 .inc();
102}
103
104pub fn gather_metrics() -> Result<String, Box<dyn std::error::Error>> {
106 let encoder = TextEncoder::new();
107 let metric_families = prometheus::gather();
108 let mut buffer = Vec::new();
109 encoder.encode(&metric_families, &mut buffer)?;
110 Ok(String::from_utf8(buffer)?)
111}
112
113pub fn record_http_request(method: &str, path: &str, status: u16, duration: f64) {
115 HTTP_REQUESTS_TOTAL
116 .with_label_values(&[method, path, &status.to_string()])
117 .inc();
118 HTTP_REQUEST_DURATION_SECONDS
119 .with_label_values(&[method, path])
120 .observe(duration);
121}
122
123pub fn record_zone_operation(operation: &str, success: bool) {
125 let result = if success { "success" } else { "error" };
126 ZONE_OPERATIONS_TOTAL
127 .with_label_values(&[operation, result])
128 .inc();
129}
130
131pub fn record_rndc_command(command: &str, success: bool, duration: f64) {
133 let result = if success { "success" } else { "error" };
134 RNDC_COMMANDS_TOTAL
135 .with_label_values(&[command, result])
136 .inc();
137 RNDC_COMMAND_DURATION_SECONDS
138 .with_label_values(&[command])
139 .observe(duration);
140}
141
142pub fn update_zones_count(count: i64) {
144 ZONES_MANAGED_TOTAL.set(count as f64);
145}
146
147pub fn record_rate_limit(allowed: bool) {
149 let result = if allowed { "allowed" } else { "rejected" };
150 RATE_LIMIT_REQUESTS_TOTAL.with_label_values(&[result]).inc();
151}
152
153pub fn record_nsupdate_command(operation: &str, success: bool, duration: f64) {
155 let result = if success { "success" } else { "error" };
156 let command = format!("nsupdate_{}", operation);
157 RNDC_COMMANDS_TOTAL
158 .with_label_values(&[command.as_str(), result])
159 .inc();
160 RNDC_COMMAND_DURATION_SECONDS
161 .with_label_values(&[command.as_str()])
162 .observe(duration);
163}
164
165pub fn record_record_operation(operation: &str, success: bool) {
167 let result = if success { "success" } else { "error" };
168 let op = format!("record_{}", operation);
169 ZONE_OPERATIONS_TOTAL
170 .with_label_values(&[op.as_str(), result])
171 .inc();
172}