1#[cfg(not(windows))]
16pub(crate) mod jemalloc;
17
18use std::task::{Context, Poll};
19use std::time::Instant;
20
21use axum::extract::{MatchedPath, Request};
22use axum::middleware::Next;
23use axum::response::IntoResponse;
24use lazy_static::lazy_static;
25use prometheus::{
26 Histogram, HistogramVec, IntCounter, IntCounterVec, IntGauge, register_histogram,
27 register_histogram_vec, register_int_counter, register_int_counter_vec, register_int_gauge,
28};
29use session::context::QueryContext;
30use tonic::body::Body;
31use tower::{Layer, Service};
32
33pub(crate) const METRIC_DB_LABEL: &str = "db";
34pub(crate) const METRIC_CODE_LABEL: &str = "code";
35pub(crate) const METRIC_TYPE_LABEL: &str = "type";
36pub(crate) const METRIC_PROTOCOL_LABEL: &str = "protocol";
37pub(crate) const METRIC_ERROR_COUNTER_LABEL_MYSQL: &str = "mysql";
38pub(crate) const METRIC_MYSQL_SUBPROTOCOL_LABEL: &str = "subprotocol";
39pub(crate) const METRIC_MYSQL_BINQUERY: &str = "binquery";
40pub(crate) const METRIC_MYSQL_TEXTQUERY: &str = "textquery";
41pub(crate) const METRIC_POSTGRES_SUBPROTOCOL_LABEL: &str = "subprotocol";
42pub(crate) const METRIC_POSTGRES_SIMPLE_QUERY: &str = "simple";
43pub(crate) const METRIC_POSTGRES_EXTENDED_QUERY: &str = "extended";
44pub(crate) const METRIC_METHOD_LABEL: &str = "method";
45pub(crate) const METRIC_PATH_LABEL: &str = "path";
46pub(crate) const METRIC_RESULT_LABEL: &str = "result";
47
48pub(crate) const METRIC_SUCCESS_VALUE: &str = "success";
49pub(crate) const METRIC_FAILURE_VALUE: &str = "failure";
50
51lazy_static! {
52
53 pub static ref HTTP_REQUEST_COUNTER: IntCounterVec = register_int_counter_vec!(
54 "greptime_servers_http_request_counter",
55 "servers http request counter",
56 &[METRIC_METHOD_LABEL, METRIC_PATH_LABEL, METRIC_CODE_LABEL, METRIC_DB_LABEL]
57 ).unwrap();
58
59 pub static ref METRIC_ERROR_COUNTER: IntCounterVec = register_int_counter_vec!(
60 "greptime_servers_error",
61 "servers error",
62 &[METRIC_PROTOCOL_LABEL]
63 )
64 .unwrap();
65 pub static ref METRIC_HTTP_SQL_ELAPSED: HistogramVec = register_histogram_vec!(
67 "greptime_servers_http_sql_elapsed",
68 "servers http sql elapsed",
69 &[METRIC_DB_LABEL],
70 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
71 )
72 .unwrap();
73 pub static ref METRIC_HTTP_PROMQL_ELAPSED: HistogramVec = register_histogram_vec!(
75 "greptime_servers_http_promql_elapsed",
76 "servers http promql elapsed",
77 &[METRIC_DB_LABEL],
78 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
79 )
80 .unwrap();
81 pub static ref METRIC_HTTP_LOGS_ELAPSED: HistogramVec = register_histogram_vec!(
83 "greptime_servers_http_logs_elapsed",
84 "servers http logs elapsed",
85 &[METRIC_DB_LABEL],
86 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
87 )
88 .unwrap();
89 pub static ref METRIC_AUTH_FAILURE: IntCounterVec = register_int_counter_vec!(
90 "greptime_servers_auth_failure_count",
91 "servers auth failure count",
92 &[METRIC_CODE_LABEL]
93 )
94 .unwrap();
95 pub static ref METRIC_HTTP_INFLUXDB_WRITE_ELAPSED: HistogramVec = register_histogram_vec!(
97 "greptime_servers_http_influxdb_write_elapsed",
98 "servers http influxdb write elapsed",
99 &[METRIC_DB_LABEL],
100 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
101 )
102 .unwrap();
103 pub static ref METRIC_HTTP_PROM_STORE_WRITE_ELAPSED: HistogramVec = register_histogram_vec!(
105 "greptime_servers_http_prometheus_write_elapsed",
106 "servers http prometheus write elapsed",
107 &[METRIC_DB_LABEL],
108 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
109 )
110 .unwrap();
111 pub static ref METRIC_HTTP_PROM_STORE_CODEC_ELAPSED: HistogramVec = register_histogram_vec!(
113 "greptime_servers_http_prometheus_codec_elapsed",
114 "servers http prometheus request codec duration",
115 &["type"],
116 )
117 .unwrap();
118 pub static ref METRIC_HTTP_PROM_STORE_DECODE_ELAPSED: Histogram = METRIC_HTTP_PROM_STORE_CODEC_ELAPSED
120 .with_label_values(&["decode"]);
121 pub static ref METRIC_HTTP_PROM_STORE_CONVERT_ELAPSED: Histogram = METRIC_HTTP_PROM_STORE_CODEC_ELAPSED
123 .with_label_values(&["convert"]);
124 pub static ref PROM_STORE_REMOTE_WRITE_SAMPLES: IntCounterVec = register_int_counter_vec!(
126 "greptime_servers_prometheus_remote_write_samples",
127 "frontend prometheus remote write samples",
128 &[METRIC_DB_LABEL]
129 )
130 .unwrap();
131 pub static ref PROM_STORE_REMOTE_WRITE_HISTOGRAMS: IntCounterVec = register_int_counter_vec!(
133 "greptime_servers_prometheus_remote_write_histograms",
134 "frontend prometheus remote write native histograms",
135 &[METRIC_DB_LABEL]
136 )
137 .unwrap();
138 pub static ref PENDING_BATCHES: IntGauge = register_int_gauge!(
139 "greptime_prom_store_pending_batches",
140 "Number of pending batches waiting to be flushed"
141 )
142 .unwrap();
143 pub static ref PENDING_ROWS: IntGauge = register_int_gauge!(
144 "greptime_prom_store_pending_rows",
145 "Number of pending rows waiting to be flushed"
146 )
147 .unwrap();
148 pub static ref PENDING_WORKERS: IntGauge = register_int_gauge!(
149 "greptime_prom_store_pending_workers",
150 "Number of active pending rows batch workers"
151 )
152 .unwrap();
153 pub static ref FLUSH_TOTAL: IntCounter = register_int_counter!(
154 "greptime_prom_store_flush_total",
155 "Total number of batch flushes"
156 )
157 .unwrap();
158 pub static ref FLUSH_ROWS: Histogram = register_histogram!(
159 "greptime_prom_store_flush_rows",
160 "Number of rows per flush",
161 vec![100.0, 1000.0, 10000.0, 50000.0, 100000.0, 500000.0]
162 )
163 .unwrap();
164 pub static ref FLUSH_ELAPSED: Histogram = register_histogram!(
165 "greptime_prom_store_flush_elapsed",
166 "Elapsed time of pending rows batch flush in seconds",
167 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
168 )
169 .unwrap();
170 pub static ref FLUSH_DROPPED_ROWS: IntCounter = register_int_counter!(
171 "greptime_pending_rows_flush_dropped_rows",
172 "Total rows dropped due to pending rows flush failures"
173 )
174 .unwrap();
175 pub static ref FLUSH_FAILURES: IntCounter = register_int_counter!(
176 "greptime_pending_rows_flush_failures",
177 "Total pending rows flush failures"
178 )
179 .unwrap();
180 pub static ref FLOW_NOTIFICATION_DROPPED: IntCounterVec = register_int_counter_vec!(
181 "greptime_prom_store_flow_notification_dropped_total",
182 "Total flow notifications dropped by the pending rows batcher",
183 &["reason"]
184 )
185 .unwrap();
186 pub static ref PENDING_ROWS_BATCH_INGEST_STAGE_ELAPSED: HistogramVec = register_histogram_vec!(
187 "greptime_prom_store_pending_rows_batch_ingest_stage_elapsed",
188 "Elapsed time of pending rows batch ingestion stages in seconds",
189 &["stage"],
190 vec![0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0]
191 )
192 .unwrap();
193 pub static ref PENDING_ROWS_BATCH_FLUSH_STAGE_ELAPSED: HistogramVec = register_histogram_vec!(
194 "greptime_prom_store_pending_rows_batch_flush_stage_elapsed",
195 "Elapsed time of pending rows batch flush stages in seconds",
196 &["stage"],
197 vec![0.0005, 0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0]
198 )
199 .unwrap();
200 pub static ref METRIC_HTTP_PROM_STORE_READ_ELAPSED: HistogramVec = register_histogram_vec!(
202 "greptime_servers_http_prometheus_read_elapsed",
203 "servers http prometheus read elapsed",
204 &[METRIC_DB_LABEL]
205 )
206 .unwrap();
207 pub static ref METRIC_HTTP_PROMETHEUS_PROMQL_ELAPSED: HistogramVec = register_histogram_vec!(
209 "greptime_servers_http_prometheus_promql_elapsed",
210 "servers http prometheus promql elapsed",
211 &[METRIC_DB_LABEL, METRIC_METHOD_LABEL]
212 )
213 .unwrap();
214 pub static ref METRIC_HTTP_OPENTELEMETRY_METRICS_ELAPSED: HistogramVec =
215 register_histogram_vec!(
216 "greptime_servers_http_otlp_metrics_elapsed",
217 "servers_http_otlp_metrics_elapsed",
218 &[METRIC_DB_LABEL]
219 )
220 .unwrap();
221 pub static ref METRIC_HTTP_OPENTELEMETRY_TRACES_ELAPSED: HistogramVec =
222 register_histogram_vec!(
223 "greptime_servers_http_otlp_traces_elapsed",
224 "servers http otlp traces elapsed",
225 &[METRIC_DB_LABEL]
226 )
227 .unwrap();
228 pub static ref METRIC_HTTP_OPENTELEMETRY_LOGS_ELAPSED: HistogramVec =
229 register_histogram_vec!(
230 "greptime_servers_http_otlp_logs_elapsed",
231 "servers http otlp logs elapsed",
232 &[METRIC_DB_LABEL]
233 )
234 .unwrap();
235 pub static ref METRIC_HTTP_LOGS_INGESTION_COUNTER: IntCounterVec = register_int_counter_vec!(
236 "greptime_servers_http_logs_ingestion_counter",
237 "servers http logs ingestion counter",
238 &[METRIC_DB_LABEL]
239 )
240 .unwrap();
241 pub static ref METRIC_HTTP_LOGS_INGESTION_ELAPSED: HistogramVec =
242 register_histogram_vec!(
243 "greptime_servers_http_logs_ingestion_elapsed",
244 "servers http logs ingestion elapsed",
245 &[METRIC_DB_LABEL, METRIC_RESULT_LABEL]
246 )
247 .unwrap();
248
249 pub static ref METRIC_LOKI_LOGS_INGESTION_COUNTER: IntCounterVec = register_int_counter_vec!(
251 "greptime_servers_loki_logs_ingestion_counter",
252 "servers loki logs ingestion counter",
253 &[METRIC_DB_LABEL]
254 )
255 .unwrap();
256 pub static ref METRIC_LOKI_LOGS_INGESTION_ELAPSED: HistogramVec =
257 register_histogram_vec!(
258 "greptime_servers_loki_logs_ingestion_elapsed",
259 "servers loki logs ingestion elapsed",
260 &[METRIC_DB_LABEL, METRIC_RESULT_LABEL]
261 )
262 .unwrap();
263 pub static ref METRIC_ELASTICSEARCH_LOGS_INGESTION_ELAPSED: HistogramVec =
264 register_histogram_vec!(
265 "greptime_servers_elasticsearch_logs_ingestion_elapsed",
266 "servers elasticsearch logs ingestion elapsed",
267 &[METRIC_DB_LABEL]
268 )
269 .unwrap();
270
271 pub static ref METRIC_ELASTICSEARCH_LOGS_DOCS_COUNT: IntCounterVec = register_int_counter_vec!(
273 "greptime_servers_elasticsearch_logs_docs_count",
274 "servers elasticsearch ingest logs docs count",
275 &[METRIC_DB_LABEL]
276 )
277 .unwrap();
278
279 pub static ref METRIC_HTTP_LOGS_TRANSFORM_ELAPSED: HistogramVec =
280 register_histogram_vec!(
281 "greptime_servers_http_logs_transform_elapsed",
282 "servers http logs transform elapsed",
283 &[METRIC_DB_LABEL, METRIC_RESULT_LABEL]
284 )
285 .unwrap();
286 pub static ref METRIC_MYSQL_CONNECTIONS: IntGauge = register_int_gauge!(
287 "greptime_servers_mysql_connection_count",
288 "servers mysql connection count"
289 )
290 .unwrap();
291 pub static ref METRIC_MYSQL_QUERY_TIMER: HistogramVec = register_histogram_vec!(
292 "greptime_servers_mysql_query_elapsed",
293 "servers mysql query elapsed",
294 &[METRIC_MYSQL_SUBPROTOCOL_LABEL, METRIC_DB_LABEL],
295 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
296 )
297 .unwrap();
298 pub static ref METRIC_MYSQL_PREPARED_COUNT: IntCounterVec = register_int_counter_vec!(
299 "greptime_servers_mysql_prepared_count",
300 "servers mysql prepared count",
301 &[METRIC_DB_LABEL]
302 )
303 .unwrap();
304 pub static ref METRIC_POSTGRES_CONNECTIONS: IntGauge = register_int_gauge!(
305 "greptime_servers_postgres_connection_count",
306 "servers postgres connection count"
307 )
308 .unwrap();
309 pub static ref METRIC_POSTGRES_QUERY_TIMER: HistogramVec = register_histogram_vec!(
310 "greptime_servers_postgres_query_elapsed",
311 "servers postgres query elapsed",
312 &[METRIC_POSTGRES_SUBPROTOCOL_LABEL, METRIC_DB_LABEL],
313 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
314 )
315 .unwrap();
316 pub static ref METRIC_POSTGRES_PREPARED_COUNT: IntCounter = register_int_counter!(
317 "greptime_servers_postgres_prepared_count",
318 "servers postgres prepared count"
319 )
320 .unwrap();
321 pub static ref METRIC_SERVER_GRPC_DB_REQUEST_TIMER: HistogramVec = register_histogram_vec!(
322 "greptime_servers_grpc_db_request_elapsed",
323 "servers grpc db request elapsed",
324 &[METRIC_DB_LABEL, METRIC_TYPE_LABEL, METRIC_CODE_LABEL]
325 )
326 .unwrap();
327 pub static ref METRIC_SERVER_GRPC_PROM_REQUEST_TIMER: HistogramVec = register_histogram_vec!(
328 "greptime_servers_grpc_prom_request_elapsed",
329 "servers grpc prom request elapsed",
330 &[METRIC_DB_LABEL],
331 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
332 )
333 .unwrap();
334 pub static ref METRIC_HTTP_REQUESTS_TOTAL: IntCounterVec = register_int_counter_vec!(
335 "greptime_servers_http_requests_total",
336 "servers http requests total",
337 &[METRIC_METHOD_LABEL, METRIC_PATH_LABEL, METRIC_CODE_LABEL, METRIC_DB_LABEL]
338 )
339 .unwrap();
340 pub static ref METRIC_HTTP_REQUESTS_ELAPSED: HistogramVec = register_histogram_vec!(
341 "greptime_servers_http_requests_elapsed",
342 "servers http requests elapsed",
343 &[METRIC_METHOD_LABEL, METRIC_PATH_LABEL, METRIC_CODE_LABEL, METRIC_DB_LABEL],
344 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
345 )
346 .unwrap();
347 pub static ref METRIC_GRPC_REQUESTS_TOTAL: IntCounterVec = register_int_counter_vec!(
348 "greptime_servers_grpc_requests_total",
349 "servers grpc requests total",
350 &[METRIC_PATH_LABEL, METRIC_CODE_LABEL]
351 )
352 .unwrap();
353 pub static ref METRIC_GRPC_REQUESTS_ELAPSED: HistogramVec = register_histogram_vec!(
354 "greptime_servers_grpc_requests_elapsed",
355 "servers grpc requests elapsed",
356 &[METRIC_PATH_LABEL, METRIC_CODE_LABEL],
357 vec![0.005, 0.01, 0.05, 0.1, 0.5, 1.0, 5.0, 10.0, 60.0, 300.0]
358 )
359 .unwrap();
360 pub static ref METRIC_JAEGER_QUERY_ELAPSED: HistogramVec = register_histogram_vec!(
361 "greptime_servers_jaeger_query_elapsed",
362 "servers jaeger query elapsed",
363 &[METRIC_DB_LABEL, METRIC_PATH_LABEL]
364 ).unwrap();
365
366 pub static ref GRPC_BULK_INSERT_ELAPSED: Histogram = register_histogram!(
367 "greptime_servers_bulk_insert_elapsed",
368 "servers handle bulk insert elapsed",
369 ).unwrap();
370
371 pub static ref REQUEST_MEMORY_IN_USE: IntGauge = register_int_gauge!(
374 "greptime_servers_request_memory_in_use_bytes",
375 "bytes currently reserved for all concurrent request bodies and messages"
376 ).unwrap();
377
378 pub static ref REQUEST_MEMORY_LIMIT: IntGauge = register_int_gauge!(
380 "greptime_servers_request_memory_limit_bytes",
381 "maximum bytes allowed for all concurrent request bodies and messages"
382 ).unwrap();
383
384 pub static ref REQUEST_MEMORY_REJECTED: IntCounterVec = register_int_counter_vec!(
386 "greptime_servers_request_memory_rejected_total",
387 "number of requests rejected due to memory limit",
388 &["reason"]
389 ).unwrap();
390}
391
392#[derive(Debug, Clone, Default)]
396pub(crate) struct MetricsMiddlewareLayer;
397
398impl<S> Layer<S> for MetricsMiddlewareLayer {
399 type Service = MetricsMiddleware<S>;
400
401 fn layer(&self, service: S) -> Self::Service {
402 MetricsMiddleware { inner: service }
403 }
404}
405
406#[derive(Debug, Clone)]
407pub(crate) struct MetricsMiddleware<S> {
408 inner: S,
409}
410
411impl<S> Service<http::Request<Body>> for MetricsMiddleware<S>
412where
413 S: Service<http::Request<Body>, Response = http::Response<Body>> + Clone + Send + 'static,
414 S::Future: Send + 'static,
415{
416 type Response = S::Response;
417 type Error = S::Error;
418 type Future = futures::future::BoxFuture<'static, Result<Self::Response, Self::Error>>;
419
420 fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
421 self.inner.poll_ready(cx)
422 }
423
424 fn call(&mut self, req: http::Request<Body>) -> Self::Future {
425 let clone = self.inner.clone();
429 let mut inner = std::mem::replace(&mut self.inner, clone);
430
431 Box::pin(async move {
432 let start = Instant::now();
433 let path = req.uri().path().to_string();
434
435 let response = inner.call(req).await?;
437
438 let latency = start.elapsed().as_secs_f64();
439 let status = response.status().as_u16().to_string();
440
441 let labels = [path.as_str(), status.as_str()];
442 METRIC_GRPC_REQUESTS_TOTAL.with_label_values(&labels).inc();
443 METRIC_GRPC_REQUESTS_ELAPSED
444 .with_label_values(&labels)
445 .observe(latency);
446
447 Ok(response)
448 })
449 }
450}
451
452pub(crate) async fn http_metrics_layer(req: Request, next: Next) -> impl IntoResponse {
455 let start = Instant::now();
456 let path = if let Some(matched_path) = req.extensions().get::<MatchedPath>() {
457 matched_path.as_str().to_string()
458 } else {
459 req.uri().path().to_string()
460 };
461 let method = req.method().clone();
462
463 let db = req
464 .extensions()
465 .get::<QueryContext>()
466 .map(|ctx| ctx.get_db_string())
467 .unwrap_or_else(|| "unknown".to_string());
468
469 let response = next.run(req).await;
470
471 let latency = start.elapsed().as_secs_f64();
472 let status = response.status();
473 let status = status.as_str();
474 let method_str = method.as_str();
475
476 let labels = [method_str, &path, status, db.as_str()];
477 METRIC_HTTP_REQUESTS_TOTAL.with_label_values(&labels).inc();
478 METRIC_HTTP_REQUESTS_ELAPSED
479 .with_label_values(&labels)
480 .observe(latency);
481
482 response
483}