Skip to content

Commit 5e77ec1

Browse files
add conversion and upload duration to histogram metric (#1793)
* add conversion and upload duration to histogram metric metrics added - conversion_task_duration, object_store_sync_duration with phase - periodic and startup remove conversion and object store sync tasks from query server * custom buckets for conversion and query execution time
1 parent 651b476 commit 5e77ec1

4 files changed

Lines changed: 74 additions & 19 deletions

File tree

‎src/handlers/http/health_check.rs‎

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ use once_cell::sync::Lazy;
3232
use tokio::{sync::Mutex, task::JoinSet};
3333
use tracing::{error, info};
3434

35+
use crate::option::Mode;
3536
use crate::sync::shutdown_local_sync_flush_and_convert;
3637
use crate::utils::get_tenant_id_from_request;
3738
use crate::{parseable::PARSEABLE, storage::object_storage::sync_all_streams};
@@ -65,11 +66,13 @@ pub async fn shutdown() {
6566
//sleep for 5 secs to allow any ongoing requests to finish
6667
tokio::time::sleep(std::time::Duration::from_secs(5)).await;
6768

68-
// Perform sync operations
69-
perform_sync_operations().await;
69+
// Only ingestion-capable nodes own local data that needs flushing.
70+
if matches!(PARSEABLE.options.mode, Mode::Ingest | Mode::All) {
71+
perform_sync_operations().await;
7072

71-
// This is to ensure that all stats data is synced before the server shuts down
72-
perform_sync_operations().await;
73+
// This is to ensure that all stats data is synced before the server shuts down
74+
perform_sync_operations().await;
75+
}
7376
}
7477

7578
async fn set_shutdown_flag() {

‎src/handlers/http/modal/query_server.rs‎

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@
1717
*/
1818

1919
use std::sync::Arc;
20-
use std::thread;
2120

2221
use crate::handlers::airplane;
2322
use crate::handlers::http::cluster;
@@ -33,7 +32,7 @@ use crate::hottier::HotTierManager;
3332
use crate::hottier::HotTierMessage;
3433
use crate::hottier::hottier_runtime;
3534
use crate::rbac::role::Action;
36-
use crate::{analytics, migration, storage, sync};
35+
use crate::{analytics, migration, storage};
3736
use actix_web::web::{ServiceConfig, resource};
3837
use actix_web::{Scope, web};
3938
use actix_web_prometheus::PrometheusMetrics;
@@ -159,18 +158,10 @@ impl ParseableServer for QueryServer {
159158
htm.start_all_tasks().await;
160159
};
161160

162-
// Run sync on a background thread
163-
let (cancel_tx, cancel_rx) = oneshot::channel();
164-
thread::spawn(|| sync::handler(cancel_rx));
165-
166161
tokio::spawn(airplane::server());
167162

168-
let result = self
169-
.start(shutdown_rx, prometheus.clone(), PARSEABLE.options.openid())
170-
.await?;
171-
// Cancel sync jobs
172-
cancel_tx.send(()).expect("Cancellation should not fail");
173-
Ok(result)
163+
self.start(shutdown_rx, prometheus.clone(), PARSEABLE.options.openid())
164+
.await
174165
}
175166
}
176167

‎src/metrics/mod.rs‎

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,14 @@ use prometheus::{
3535

3636
pub const METRICS_NAMESPACE: &str = env!("CARGO_PKG_NAME");
3737

38+
const SYNC_TASK_DURATION_BUCKETS: &[f64] = &[
39+
15.0, 30.0, 45.0, 60.0, 90.0, 120.0, 150.0, 180.0, 300.0, 600.0,
40+
];
41+
42+
const QUERY_EXECUTE_TIME_BUCKETS: &[f64] = &[
43+
0.1, 0.2, 0.5, 1.0, 5.0, 15.0, 30.0, 45.0, 60.0, 90.0, 120.0, 150.0, 180.0,
44+
];
45+
3846
pub static METRICS_REGISTRY: Lazy<Registry> = Lazy::new(|| {
3947
let registry = Registry::new();
4048
custom_metrics(&registry);
@@ -322,12 +330,40 @@ mod process_metrics_tests {
322330

323331
pub static QUERY_EXECUTE_TIME: Lazy<HistogramVec> = Lazy::new(|| {
324332
HistogramVec::new(
325-
HistogramOpts::new("query_execute_time", "Query execute time").namespace(METRICS_NAMESPACE),
333+
HistogramOpts::new("query_execute_time", "Query execute time")
334+
.namespace(METRICS_NAMESPACE)
335+
.buckets(QUERY_EXECUTE_TIME_BUCKETS.to_vec()),
326336
&["stream", "tenant_id"],
327337
)
328338
.expect("metric can be created")
329339
});
330340

341+
pub static CONVERSION_TASK_DURATION: Lazy<HistogramVec> = Lazy::new(|| {
342+
HistogramVec::new(
343+
HistogramOpts::new(
344+
"conversion_task_duration",
345+
"Local conversion task duration in seconds",
346+
)
347+
.namespace(METRICS_NAMESPACE)
348+
.buckets(SYNC_TASK_DURATION_BUCKETS.to_vec()),
349+
&["phase"],
350+
)
351+
.expect("metric can be created")
352+
});
353+
354+
pub static OBJECT_STORE_SYNC_DURATION: Lazy<HistogramVec> = Lazy::new(|| {
355+
HistogramVec::new(
356+
HistogramOpts::new(
357+
"object_store_sync_duration",
358+
"Object store sync duration in seconds",
359+
)
360+
.namespace(METRICS_NAMESPACE)
361+
.buckets(SYNC_TASK_DURATION_BUCKETS.to_vec()),
362+
&["phase"],
363+
)
364+
.expect("metric can be created")
365+
});
366+
331367
pub static QUERY_CACHE_HIT: Lazy<IntCounterVec> = Lazy::new(|| {
332368
IntCounterVec::new(
333369
Opts::new("QUERY_CACHE_HIT", "Full Cache hit").namespace(METRICS_NAMESPACE),
@@ -838,6 +874,12 @@ fn custom_metrics(registry: &Registry) {
838874
registry
839875
.register(Box::new(QUERY_EXECUTE_TIME.clone()))
840876
.expect("metric can be registered");
877+
registry
878+
.register(Box::new(CONVERSION_TASK_DURATION.clone()))
879+
.expect("metric can be registered");
880+
registry
881+
.register(Box::new(OBJECT_STORE_SYNC_DURATION.clone()))
882+
.expect("metric can be registered");
841883
registry
842884
.register(Box::new(QUERY_CACHE_HIT.clone()))
843885
.expect("metric can be registered");

‎src/sync.rs‎

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ pub async fn shutdown_local_sync_flush_and_convert() {
8282

8383
use crate::alerts::alert_enums::AlertTask;
8484
use crate::alerts::alerts_utils;
85+
use crate::metrics::{CONVERSION_TASK_DURATION, OBJECT_STORE_SYNC_DURATION};
8586
use crate::parseable::PARSEABLE;
8687
use crate::storage::object_storage::sync_all_streams;
8788
use crate::{LOCAL_SYNC_INTERVAL, STORAGE_UPLOAD_INTERVAL};
@@ -98,7 +99,13 @@ fn next_minute() -> Instant {
9899
Instant::now() + time_till.to_std().expect("Valid duration")
99100
}
100101

101-
pub async fn monitor_task_duration<F, Fut, T>(task_name: &str, threshold: Duration, f: F) -> T
102+
pub async fn monitor_task_duration<F, Fut, T>(
103+
task_name: &str,
104+
threshold: Duration,
105+
duration_metric: &prometheus::HistogramVec,
106+
phase: &str,
107+
f: F,
108+
) -> T
102109
where
103110
F: FnOnce() -> Fut + Send + 'static,
104111
Fut: Future<Output = T> + Send,
@@ -117,10 +124,14 @@ where
117124
warned_once = true;
118125
},
119126
res = &mut future => {
127+
let elapsed = start_time.elapsed();
128+
duration_metric
129+
.with_label_values(&[phase])
130+
.observe(elapsed.as_secs_f64());
120131
if warned_once {
121132
warn!(
122133
"Task '{task_name}' took longer than expected: {:?} (threshold: {threshold:?})",
123-
start_time.elapsed()
134+
elapsed
124135
);
125136
}
126137
break res.expect("Task handle shouldn't error");
@@ -191,6 +202,8 @@ pub fn object_store_sync() -> (
191202
monitor_task_duration(
192203
"object_store_sync_all_streams",
193204
Duration::from_secs(PARSEABLE.options.object_store_sync_threshold),
205+
&OBJECT_STORE_SYNC_DURATION,
206+
"periodic",
194207
|| async {
195208
let mut joinset = JoinSet::new();
196209
sync_all_streams(&mut joinset);
@@ -312,6 +325,8 @@ async fn run_periodic_local_sync_cycle(_permit: OwnedSemaphorePermit) {
312325
monitor_task_duration(
313326
"local_sync_flush_and_convert",
314327
Duration::from_secs(PARSEABLE.options.local_sync_threshold),
328+
&CONVERSION_TASK_DURATION,
329+
"periodic",
315330
|| async {
316331
let mut joinset = JoinSet::new();
317332
PARSEABLE
@@ -357,6 +372,8 @@ async fn sync_start_inner(
357372
monitor_task_duration(
358373
"startup_local_sync",
359374
Duration::from_secs(PARSEABLE.options.local_sync_threshold),
375+
&CONVERSION_TASK_DURATION,
376+
"startup",
360377
|| async move {
361378
// Plans contain all paths from the startup snapshot. Execute
362379
// streams and their event-minute groups sequentially to keep
@@ -386,6 +403,8 @@ async fn sync_start_inner(
386403
monitor_task_duration(
387404
"startup_object_store_sync",
388405
Duration::from_secs(PARSEABLE.options.object_store_sync_threshold),
406+
&OBJECT_STORE_SYNC_DURATION,
407+
"startup",
389408
|| async {
390409
let mut object_store_joinset = JoinSet::new();
391410
sync_all_streams(&mut object_store_joinset);

0 commit comments

Comments
 (0)