1use std::sync::Arc;
16use std::time::Instant;
17
18use axum::extract::State;
19use axum::response::{IntoResponse, Response};
20use axum::{Extension, Json};
21use common_telemetry::tracing;
22use log_query::{Limit, LogQuery};
23use session::context::{Channel, QueryContext};
24
25use crate::http::result::greptime_result_v1::GreptimedbV1Response;
26use crate::query_handler::LogQueryHandlerRef;
27
28const DEFAULT_FETCH: usize = 1000;
29
30fn apply_default_fetch(limit: &mut Limit) {
31 limit.fetch.get_or_insert(DEFAULT_FETCH);
32}
33
34#[axum_macros::debug_handler]
35#[tracing::instrument(skip_all, fields(protocol = "http", request_type = "logs"))]
36pub async fn logs(
37 State(handler): State<LogQueryHandlerRef>,
38 Extension(mut query_ctx): Extension<QueryContext>,
39 Json(mut params): Json<LogQuery>,
40) -> Response {
41 let exec_start = Instant::now();
42 let db = query_ctx.get_db_string();
43
44 query_ctx.set_channel(Channel::Log);
45 let query_ctx = Arc::new(query_ctx);
46 apply_default_fetch(&mut params.limit);
47
48 let _timer = crate::metrics::METRIC_HTTP_LOGS_ELAPSED
49 .with_label_values(&[db.as_str()])
50 .start_timer();
51
52 let output = handler.query(params, query_ctx).await;
53 let resp = GreptimedbV1Response::from_output(vec![output]).await;
54
55 resp.with_execution_time(exec_start.elapsed().as_millis() as u64)
56 .into_response()
57}
58
59#[cfg(test)]
60mod tests {
61 use super::*;
62
63 #[test]
64 fn test_apply_default_fetch() {
65 let mut limit = Limit {
66 skip: None,
67 fetch: None,
68 };
69 apply_default_fetch(&mut limit);
70 assert_eq!(limit.fetch, Some(DEFAULT_FETCH));
71
72 let mut limit = Limit {
73 skip: Some(10),
74 fetch: None,
75 };
76 apply_default_fetch(&mut limit);
77 assert_eq!(limit.skip, Some(10));
78 assert_eq!(limit.fetch, Some(DEFAULT_FETCH));
79
80 let mut limit = Limit {
81 skip: Some(10),
82 fetch: Some(42),
83 };
84 apply_default_fetch(&mut limit);
85 assert_eq!(limit.skip, Some(10));
86 assert_eq!(limit.fetch, Some(42));
87 }
88}