11use anyhow:: Result ;
2- use asap_planner:: { Controller , ControllerConfig , PlannerOutput , RuntimeOptions } ;
2+ use asap_planner:: {
3+ build_schema_from_prometheus, Controller , ControllerConfig , PlannerOutput , RuntimeOptions ,
4+ } ;
35use sketch_db_common:: enums:: QueryLanguage ;
46use sketch_db_common:: inference_config:: InferenceConfig ;
57use sketch_db_common:: streaming_config:: StreamingConfig ;
8+ use tracing:: warn;
69
710pub struct PlannerResult {
811 pub streaming_config : StreamingConfig ,
@@ -18,13 +21,19 @@ pub trait PlannerClient: Send + Sync {
1821pub struct LocalPlannerClient {
1922 runtime_options : RuntimeOptions ,
2023 query_language : QueryLanguage ,
24+ prometheus_url : String ,
2125}
2226
2327impl LocalPlannerClient {
24- pub fn new ( runtime_options : RuntimeOptions , query_language : QueryLanguage ) -> Self {
28+ pub fn new (
29+ runtime_options : RuntimeOptions ,
30+ query_language : QueryLanguage ,
31+ prometheus_url : String ,
32+ ) -> Self {
2533 Self {
2634 runtime_options,
2735 query_language,
36+ prometheus_url,
2837 }
2938 }
3039}
@@ -34,9 +43,35 @@ impl PlannerClient for LocalPlannerClient {
3443 async fn plan ( & self , config : ControllerConfig ) -> Result < PlannerResult > {
3544 let opts = self . runtime_options . clone ( ) ;
3645 let query_language = self . query_language ;
46+ let prometheus_url = self . prometheus_url . clone ( ) ;
3747
3848 let output: PlannerOutput = tokio:: task:: spawn_blocking ( move || {
39- let schema = config. schema_from_hints ( ) ;
49+ let all_queries: Vec < String > = config
50+ . query_groups
51+ . iter ( )
52+ . flat_map ( |qg| qg. queries . clone ( ) )
53+ . collect ( ) ;
54+ let mut schema = match build_schema_from_prometheus ( & prometheus_url, & all_queries) {
55+ Ok ( s) => s,
56+ Err ( e) => {
57+ warn ! (
58+ "Prometheus metric discovery failed, falling back to config hints: {}" ,
59+ e
60+ ) ;
61+ config. schema_from_hints ( )
62+ }
63+ } ;
64+ // Fall back to config-file hints for metrics not found in Prometheus.
65+ if let Some ( metric_hints) = & config. metrics {
66+ for hint in metric_hints {
67+ if !schema. config . contains_key ( & hint. metric ) {
68+ schema = schema. add_metric (
69+ hint. metric . clone ( ) ,
70+ promql_utilities:: data_model:: KeyByLabelNames :: new ( hint. labels . clone ( ) ) ,
71+ ) ;
72+ }
73+ }
74+ }
4075 let controller = Controller :: new ( config, schema, opts) ;
4176 controller. generate ( )
4277 } )
@@ -127,7 +162,13 @@ mod tests {
127162
128163 #[ tokio:: test]
129164 async fn test_local_planner_client ( ) {
130- let client = LocalPlannerClient :: new ( sample_runtime_options ( ) , QueryLanguage :: promql) ;
165+ // Use a dummy URL; the test config has metric hints so Prometheus discovery
166+ // failures are tolerated via the fallback path.
167+ let client = LocalPlannerClient :: new (
168+ sample_runtime_options ( ) ,
169+ QueryLanguage :: promql,
170+ "http://localhost:9090" . to_string ( ) ,
171+ ) ;
131172 let config = sample_controller_config ( ) ;
132173
133174 let result = client. plan ( config) . await . expect ( "plan should succeed" ) ;
0 commit comments