From 8dfe08f9c8e64628073e527db8ca4e036fac754a Mon Sep 17 00:00:00 2001 From: Ashish Kolhe Date: Mon, 26 Oct 2026 17:17:20 +0530 Subject: [PATCH] fix(license): keep router modules, helpers and comments in repo order --- src/api/http/src/handler/http/router/mod.rs | 210 ++++++++++---------- 1 file changed, 102 insertions(+), 108 deletions(-) diff --git a/src/api/http/src/handler/http/router/mod.rs b/src/api/http/src/handler/http/router/mod.rs index 616433520b..a7b7a1c822 100644 --- a/src/api/http/src/handler/http/router/mod.rs +++ b/src/api/http/src/handler/http/router/mod.rs @@ -13,6 +13,18 @@ // You should have received a copy of the GNU Affero General Public License // along with this program. If not, see . +pub mod decompression; +pub mod middlewares; +#[cfg(all(test, feature = "enterprise"))] +mod one_ack_oncall_off_tests; +#[cfg(all(test, feature = "enterprise"))] +mod one_ack_tests; +pub mod openapi; +#[cfg(test)] +mod openapi_coverage; +#[cfg(test)] +mod search_gate_tests; + use std::time::Duration; use axum::{ @@ -23,6 +35,7 @@ use axum::{ response::{IntoResponse, Redirect, Response}, routing::{delete, get, patch, post, put}, }; +use common::meta::http::ERROR_HEADER; use config::{get_config, meta::feature::Feature}; use openobserve_api_common::{X_O2_ASSISTANT_SESSION_ID, X_O2_ASSISTANT_TURN_ID}; use openobserve_api_ingest::request::{clusters, logs, metrics, profiles, rum}; @@ -92,20 +105,6 @@ use crate::{ }, }; -pub mod decompression; -pub mod middlewares; -#[cfg(all(test, feature = "enterprise"))] -mod one_ack_oncall_off_tests; -#[cfg(all(test, feature = "enterprise"))] -mod one_ack_tests; -pub mod openapi; -#[cfg(test)] -mod openapi_coverage; -#[cfg(test)] -mod search_gate_tests; - -use common::meta::http::ERROR_HEADER; - /// How long a refused agent waits before reconnecting while fleet management is off. #[cfg(feature = "enterprise")] const FLEET_RETRY_AFTER_SECS: &str = "60"; @@ -1283,11 +1282,6 @@ fn alert_calibration_routes(router: Router) -> Router { } #[rustfmt::skip] -pub fn service_routes() -> Router { - with_service_layers(service_route_table()) -} - -/// The `/api` route table before the auth, audit and org layers wrap it. fn service_route_table() -> Router { // Downtimes, Slack, search and service streams live in their own tables to keep this function under the line limit. let mut router = public_dashboard_admin_routes( @@ -2255,7 +2249,6 @@ fn service_route_table() -> Router { fn with_service_layers(router: Router) -> Router { let cfg = get_config(); - // Set server header #[cfg(feature = "enterprise")] let server = format!( "{}-{}", @@ -2301,6 +2294,95 @@ fn service_streams_routes() -> Router { .route("/{org_id}/service_streams/_reset", delete(service_streams::reset_services)) } +/// Routes that read customer data through search; the licence gate answers 429 while search is blocked. +#[rustfmt::skip] +fn search_routes() -> Router { + #[cfg(feature = "enterprise")] + let llm_eval = get_o2_config().llm_eval_config.enabled; + #[cfg(not(feature = "enterprise"))] + let llm_eval = false; + search_routes_with(llm_eval) +} + +#[rustfmt::skip] +#[cfg_attr(not(feature = "enterprise"), allow(unused_variables))] +fn search_routes_with(llm_eval: bool) -> Router { + let router = Router::new() + .route("/{org_id}/_search_multi", post(search::multi_streams::search_multi)) + .route("/{org_id}/_search_multi_stream", post(search::multi_streams::search_multi_stream)) + .route("/{org_id}/_search_partition_multi", post(search::multi_streams::_search_partition_multi)) + .route("/{org_id}/{stream_names}/_around_multi", get(search::multi_streams::around_multi)) + .route("/{org_id}/{stream_name}/traces/{trace_id}/details", get(traces::details::get_trace_details)) + .route("/{org_id}/prometheus/api/v1/label/{label_name}/values", get(promql::label_values)) + .route("/v2/{org_id}/downtimes/resources", post(downtimes::downtime_resources)) + .route("/v2/{org_id}/downtimes/values", post(downtimes::downtime_values)) + // A manual trigger of an anomaly alert runs detection now, and a retrain trains now. + .route("/v2/{org_id}/alerts/{alert_id}/trigger", patch(alerts::trigger_alert)) + .route("/v2/{org_id}/alerts/{alert_id}/retrain", patch(alerts::retrain_alert)) + + // Both builds register these so OSS answers 403, not 404; OFGA keys on this path segment. + .route("/{org_id}/db_monitoring/databases", get(db_monitoring::handler::get_dbm_databases)) + .route("/{org_id}/db_monitoring/queries", get(db_monitoring::handler::get_dbm_queries)) + .route("/{org_id}/db_monitoring/query/history", get(db_monitoring::handler::get_dbm_query_history)) + .route("/{org_id}/db_monitoring/query/endpoints", get(db_monitoring::handler::get_dbm_query_endpoints)) + .route("/{org_id}/db_monitoring/samples", get(db_monitoring::handler::get_dbm_samples)) + .route("/{org_id}/db_monitoring/deadlocks", get(db_monitoring::handler::get_dbm_deadlocks)) + .route("/{org_id}/db_monitoring/blocking", get(db_monitoring::handler::get_dbm_blocking)) + .route("/{org_id}/db_monitoring/activity", get(db_monitoring::handler::get_dbm_activity)) + // plans and server_metrics are superseded by query/insights; kept for compatibility + .route("/{org_id}/db_monitoring/query/insights", get(db_monitoring::handler::get_dbm_query_insights)) + .route("/{org_id}/db_monitoring/query/plans", get(db_monitoring::handler::get_dbm_query_plans)) + .route("/{org_id}/db_monitoring/query/server_metrics", get(db_monitoring::handler::get_dbm_query_server_metrics)) + .route("/{org_id}/db_monitoring/server_queries", get(db_monitoring::handler::get_dbm_server_queries)) + .route("/{org_id}/db_monitoring/server_samples", get(db_monitoring::handler::get_dbm_server_samples)) + .route("/{org_id}/db_monitoring/table_health", get(db_monitoring::handler::get_dbm_table_health)) + .route("/{org_id}/db_monitoring/instances", get(db_monitoring::handler::get_dbm_instances)) + .route( + "/{org_id}/db_monitoring/instance_metrics", + get(db_monitoring::handler::get_dbm_instance_metrics), + ) + .route("/{org_id}/db_monitoring/badges", get(db_monitoring::handler::get_dbm_badges)); + #[cfg(feature = "enterprise")] + let router = { + let router = router + .route("/{org_id}/anomaly_detection/{config_id}/train", post(anomaly_detection::train_model)) + .route("/{org_id}/anomaly_detection/{config_id}/detect", post(anomaly_detection::detect_anomalies)) + .route("/{org_id}/search_jobs", post(search::search_job::submit_job)) + .route("/{org_id}/search_jobs/{job_id}/result", get(search::search_job::get_job_result)) + .route("/{org_id}/search_jobs/{job_id}/retry", post(search::search_job::retry_job)) + .route("/{org_id}/traces/service_graph/topology/current", get(traces::get_current_topology)) + .route("/{org_id}/traces/service_graph/edge/history", get(traces::get_edge_history)) + .route("/{org_id}/traces/agent_signals", get(traces::get_agent_signals)) + .route("/{org_id}/traces/agent_signals/compare", post(traces::compare_agent_versions)) + .route("/{org_id}/streams/{stream_name}/patterns/extract", post(patterns::extract_patterns)); + if llm_eval { + router + .route("/{org_id}/annotation_queues/{queue_id}/items", post(annotation_queues::enqueue_annotation_queue_item)) + .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}", get(annotation_queues::get_annotation_queue_item)) + .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}/reviews", get(annotation_queues::list_annotation_queue_item_reviews)) + .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}/push_to_dataset", post(datasets::push_annotation_queue_item_to_dataset)) + .route("/{org_id}/datasets/{dataset_id}/items", post(datasets::push_dataset_item)) + .route("/{org_id}/experiments/compare", get(experiments::compare_experiments)) + .route("/{org_id}/experiments/{experiment_id}", get(experiments::get_experiment)) + .route("/{org_id}/experiments/{experiment_id}/rows", get(experiments::list_experiment_result_rows)) + .route("/{org_id}/experiments/{experiment_id}/rows/{row_id}", get(experiments::get_experiment_row)) + .route("/{org_id}/discovery", get(discovery::list_discovery_items)) + .route("/{org_id}/tasks/{entity_id}/stats", get(remote_tasks::get_remote_task_stats)) + .route("/{org_id}/eval_jobs/{job_id}/manual_eval", post(eval_jobs::manual_eval_job)) + } else { + router + } + }; + // A route layer, not a layer: it must not reach the ungated methods merged onto the same paths. + #[cfg(feature = "enterprise")] + let router = router.route_layer(middleware::from_fn(search_license_middleware)); + router +} + +pub fn service_routes() -> Router { + with_service_layers(service_route_table()) +} + /// Downtimes routes; the literal segments stay before the {downtime_id} catch-all. #[rustfmt::skip] pub fn downtime_routes() -> Router { @@ -2332,94 +2414,6 @@ fn report_routes() -> Router { .route("/v2/{org_id}/reports/{report_id}/trigger", put(dashboards::reports::trigger_report_v2)) } -/// Routes that read customer data through search; the licence gate answers 429 while search is blocked. -#[rustfmt::skip] -fn search_routes() -> Router { - #[cfg(feature = "enterprise")] - let llm_eval = get_o2_config().llm_eval_config.enabled; - #[cfg(not(feature = "enterprise"))] - let llm_eval = false; - search_routes_with(llm_eval) -} - -#[rustfmt::skip] -#[cfg_attr(not(feature = "enterprise"), allow(unused_variables))] -fn search_routes_with(llm_eval: bool) -> Router { - let router = Router::new() - // Multi-stream search - .route("/{org_id}/_search_multi", post(search::multi_streams::search_multi)) - .route("/{org_id}/_search_multi_stream", post(search::multi_streams::search_multi_stream)) - .route("/{org_id}/_search_partition_multi", post(search::multi_streams::_search_partition_multi)) - .route("/{org_id}/{stream_names}/_around_multi", get(search::multi_streams::around_multi)) - .route("/{org_id}/{stream_name}/traces/{trace_id}/details", get(traces::details::get_trace_details)) - .route("/{org_id}/prometheus/api/v1/label/{label_name}/values", get(promql::label_values)) - .route("/v2/{org_id}/downtimes/resources", post(downtimes::downtime_resources)) - .route("/v2/{org_id}/downtimes/values", post(downtimes::downtime_values)) - // A manual trigger of an anomaly alert runs detection now, and a retrain trains now. - .route("/v2/{org_id}/alerts/{alert_id}/trigger", patch(alerts::trigger_alert)) - .route("/v2/{org_id}/alerts/{alert_id}/retrain", patch(alerts::retrain_alert)) - - // Both builds register these so OSS answers 403, not 404; OFGA keys on this path segment. - .route("/{org_id}/db_monitoring/databases", get(db_monitoring::handler::get_dbm_databases)) - .route("/{org_id}/db_monitoring/queries", get(db_monitoring::handler::get_dbm_queries)) - .route("/{org_id}/db_monitoring/query/history", get(db_monitoring::handler::get_dbm_query_history)) - .route("/{org_id}/db_monitoring/query/endpoints", get(db_monitoring::handler::get_dbm_query_endpoints)) - .route("/{org_id}/db_monitoring/samples", get(db_monitoring::handler::get_dbm_samples)) - // Server-vantage events (read the canonical o2_dbm_* columns) - .route("/{org_id}/db_monitoring/deadlocks", get(db_monitoring::handler::get_dbm_deadlocks)) - .route("/{org_id}/db_monitoring/blocking", get(db_monitoring::handler::get_dbm_blocking)) - .route("/{org_id}/db_monitoring/activity", get(db_monitoring::handler::get_dbm_activity)) - // plans and server_metrics are superseded by query/insights; kept for compatibility - .route("/{org_id}/db_monitoring/query/insights", get(db_monitoring::handler::get_dbm_query_insights)) - .route("/{org_id}/db_monitoring/query/plans", get(db_monitoring::handler::get_dbm_query_plans)) - .route("/{org_id}/db_monitoring/query/server_metrics", get(db_monitoring::handler::get_dbm_query_server_metrics)) - .route("/{org_id}/db_monitoring/server_queries", get(db_monitoring::handler::get_dbm_server_queries)) - .route("/{org_id}/db_monitoring/server_samples", get(db_monitoring::handler::get_dbm_server_samples)) - .route("/{org_id}/db_monitoring/table_health", get(db_monitoring::handler::get_dbm_table_health)) - .route("/{org_id}/db_monitoring/instances", get(db_monitoring::handler::get_dbm_instances)) - .route( - "/{org_id}/db_monitoring/instance_metrics", - get(db_monitoring::handler::get_dbm_instance_metrics), - ) - .route("/{org_id}/db_monitoring/badges", get(db_monitoring::handler::get_dbm_badges)); - #[cfg(feature = "enterprise")] - let router = { - let router = router - .route("/{org_id}/anomaly_detection/{config_id}/train", post(anomaly_detection::train_model)) - .route("/{org_id}/anomaly_detection/{config_id}/detect", post(anomaly_detection::detect_anomalies)) - .route("/{org_id}/search_jobs", post(search::search_job::submit_job)) - .route("/{org_id}/search_jobs/{job_id}/result", get(search::search_job::get_job_result)) - .route("/{org_id}/search_jobs/{job_id}/retry", post(search::search_job::retry_job)) - .route("/{org_id}/traces/service_graph/topology/current", get(traces::get_current_topology)) - .route("/{org_id}/traces/service_graph/edge/history", get(traces::get_edge_history)) - // Agent behavior signals (loop / failure / cost) — reads the _agent_signals stream - .route("/{org_id}/traces/agent_signals", get(traces::get_agent_signals)) - .route("/{org_id}/traces/agent_signals/compare", post(traces::compare_agent_versions)) - .route("/{org_id}/streams/{stream_name}/patterns/extract", post(patterns::extract_patterns)); - if llm_eval { - router - .route("/{org_id}/annotation_queues/{queue_id}/items", post(annotation_queues::enqueue_annotation_queue_item)) - .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}", get(annotation_queues::get_annotation_queue_item)) - .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}/reviews", get(annotation_queues::list_annotation_queue_item_reviews)) - .route("/{org_id}/annotation_queues/{queue_id}/items/{queue_item_id}/push_to_dataset", post(datasets::push_annotation_queue_item_to_dataset)) - .route("/{org_id}/datasets/{dataset_id}/items", post(datasets::push_dataset_item)) - .route("/{org_id}/experiments/compare", get(experiments::compare_experiments)) - .route("/{org_id}/experiments/{experiment_id}", get(experiments::get_experiment)) - .route("/{org_id}/experiments/{experiment_id}/rows", get(experiments::list_experiment_result_rows)) - .route("/{org_id}/experiments/{experiment_id}/rows/{row_id}", get(experiments::get_experiment_row)) - .route("/{org_id}/discovery", get(discovery::list_discovery_items)) - .route("/{org_id}/tasks/{entity_id}/stats", get(remote_tasks::get_remote_task_stats)) - .route("/{org_id}/eval_jobs/{job_id}/manual_eval", post(eval_jobs::manual_eval_job)) - } else { - router - } - }; - // A route layer, not a layer: it must not reach the ungated methods merged onto the same paths. - #[cfg(feature = "enterprise")] - let router = router.route_layer(middleware::from_fn(search_license_middleware)); - router -} - /// On-call management routes; the caller mounts them only when on-call is enabled. #[cfg(feature = "enterprise")] fn oncall_routes(router: Router) -> Router {