Skip to content

Commit eb2e38f

Browse files
committed
implement dedicated service for /metrics
1 parent e12fb6f commit eb2e38f

5 files changed

Lines changed: 92 additions & 0 deletions

File tree

src/actix/api/service_api.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,3 +222,8 @@ pub fn config_service_api(cfg: &mut web::ServiceConfig) {
222222
.service(get_logger_config)
223223
.service(update_logger_config);
224224
}
225+
226+
// Dedicated service for metrics
227+
pub fn config_metrics_api(cfg: &mut web::ServiceConfig) {
228+
cfg.service(metrics);
229+
}

src/actix/metrics_service.rs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
use std::io;
2+
use std::sync::Arc;
3+
4+
use actix_web::middleware::Compress;
5+
use actix_web::{App, HttpServer, web};
6+
7+
use crate::actix::api::service_api::config_metrics_api;
8+
use crate::actix::certificate_helpers;
9+
use crate::common::telemetry::TelemetryCollector;
10+
use crate::settings::Settings;
11+
12+
pub fn init_metrics(
13+
port: u16,
14+
telemetry_collector: Arc<tokio::sync::Mutex<TelemetryCollector>>,
15+
settings: Settings,
16+
) -> io::Result<()> {
17+
actix_web::rt::System::new().block_on(async {
18+
let telemetry_collector_data = web::Data::from(telemetry_collector);
19+
let service_config = web::Data::new(settings.service.clone());
20+
21+
let mut server = HttpServer::new(move || {
22+
App::new()
23+
.wrap(Compress::default())
24+
.app_data(telemetry_collector_data.clone())
25+
.app_data(service_config.clone())
26+
.configure(config_metrics_api)
27+
})
28+
.workers(1);
29+
30+
let bind_addr = format!("{}:{}", settings.service.host, port);
31+
32+
server = if settings.service.enable_tls {
33+
log::info!(
34+
"TLS enabled for REST API (TTL: {})",
35+
settings
36+
.tls
37+
.as_ref()
38+
.and_then(|tls| tls.cert_ttl)
39+
.map(|ttl| ttl.to_string())
40+
.unwrap_or_else(|| "none".into()),
41+
);
42+
43+
let config = certificate_helpers::actix_tls_server_config(&settings)
44+
.map_err(io::Error::other)?;
45+
server.bind_rustls_0_23(bind_addr, config)?
46+
} else {
47+
log::info!("TLS disabled for REST API");
48+
49+
server.bind(bind_addr)?
50+
};
51+
52+
log::info!("Qdrant metrics listening on {port}");
53+
server.run().await
54+
})
55+
}

src/actix/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ pub mod api;
33
mod auth;
44
mod certificate_helpers;
55
pub mod helpers;
6+
pub mod metrics_service;
67
pub mod web_ui;
78

89
use std::io;

src/main.rs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -558,6 +558,7 @@ fn main() -> anyhow::Result<()> {
558558

559559
{
560560
let dispatcher_arc = dispatcher_arc.clone();
561+
let telemetry_collector = telemetry_collector.clone();
561562
let settings = settings.clone();
562563
let handle = thread::Builder::new()
563564
.name("web".to_string())
@@ -577,6 +578,29 @@ fn main() -> anyhow::Result<()> {
577578
handles.push(handle);
578579
}
579580

581+
//
582+
// Extra `/metrics` server
583+
//
584+
585+
if let Some(metrics_port) = settings.service.metrics_port {
586+
let telemetry_collector = telemetry_collector.clone();
587+
let settings = settings.clone();
588+
let handle = thread::Builder::new()
589+
.name("metrics".to_string())
590+
.spawn(move || {
591+
log_err_if_any(
592+
"Metrics",
593+
actix::metrics_service::init_metrics(
594+
metrics_port,
595+
telemetry_collector,
596+
settings,
597+
),
598+
)
599+
})
600+
.unwrap();
601+
handles.push(handle);
602+
}
603+
580604
//
581605
// gRPC server
582606
//

src/settings.rs

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,13 @@ pub struct ServiceConfig {
2626
pub host: String,
2727
pub http_port: u16,
2828
pub grpc_port: Option<u16>, // None means that gRPC is disabled
29+
30+
/// If specified, qdrant will serve a separate service for `/metrics` on this port.
31+
/// Separate port is not protected by API keys and dedicated for internal monitoring systems.
32+
/// This port should not be exposed to untrusted networks.
33+
#[serde(default)]
34+
pub metrics_port: Option<u16>,
35+
2936
pub max_request_size_mb: usize,
3037
pub max_workers: Option<usize>,
3138
#[serde(default = "default_cors")]

0 commit comments

Comments
 (0)