Skip to main content

otelite_api/api/
mod.rs

1// API module
2
3use axum::{http::StatusCode, Json};
4use otelite_core::api::ErrorResponse;
5
6pub mod admin;
7pub mod genai;
8pub mod health;
9pub mod help;
10pub mod logs;
11pub mod metrics;
12pub mod resource_keys;
13pub mod sessions;
14pub mod stats;
15pub mod traces;
16
17pub use genai::get_token_usage;
18pub use health::health_check;
19pub use help::api_help;
20
21pub(crate) fn validate_time_range(
22    start_time: Option<i64>,
23    end_time: Option<i64>,
24) -> Result<(), (StatusCode, Json<ErrorResponse>)> {
25    if let Some(start_time) = start_time {
26        if start_time < 0 {
27            return Err(time_range_error("start_time must be non-negative"));
28        }
29    }
30
31    if let Some(end_time) = end_time {
32        if end_time < 0 {
33            return Err(time_range_error("end_time must be non-negative"));
34        }
35    }
36
37    if let (Some(start_time), Some(end_time)) = (start_time, end_time) {
38        if start_time >= end_time {
39            return Err(time_range_error("start_time must be less than end_time"));
40        }
41    }
42
43    Ok(())
44}
45
46fn time_range_error(message: &'static str) -> (StatusCode, Json<ErrorResponse>) {
47    (
48        StatusCode::BAD_REQUEST,
49        Json(ErrorResponse::bad_request(message)),
50    )
51}
52
53/// Parse a `query` parameter: one structured predicate, or several joined
54/// with `&&` (serde_urlencoded rejects repeated keys, so the wire format
55/// is a single parameter). Returns a 400 on any parse failure — never a
56/// silently-ignored filter.
57pub(crate) fn parse_query_param(
58    raw: &str,
59) -> Result<Vec<otelite_core::query::QueryPredicate>, (StatusCode, Json<ErrorResponse>)> {
60    let mut out = Vec::new();
61    for part in raw.split("&&").map(str::trim).filter(|p| !p.is_empty()) {
62        out.extend(otelite_core::query::parse_query(part).map_err(|e| {
63            (
64                StatusCode::BAD_REQUEST,
65                Json(ErrorResponse::bad_request(format!(
66                    "Invalid query '{part}': {e}"
67                ))),
68            )
69        })?);
70    }
71    Ok(out)
72}