@@ -8,16 +8,37 @@ use hive_router_query_planner::{
88} ;
99use rand:: Rng ;
1010use vrl:: {
11- compiler:: compile as vrl_compile,
12- compiler:: Program as VrlProgram ,
13- compiler:: TargetValue as VrlTargetValue ,
11+ compiler:: { compile as vrl_compile, Program as VrlProgram , TargetValue as VrlTargetValue } ,
1412 core:: Value as VrlValue ,
15- prelude:: { state:: RuntimeState as VrlState , Context as VrlContext , TimeZone as VrlTimeZone } ,
13+ prelude:: {
14+ state:: RuntimeState as VrlState , Context as VrlContext , ExpressionError ,
15+ TimeZone as VrlTimeZone ,
16+ } ,
1617 stdlib:: all as vrl_build_functions,
1718 value:: Secrets as VrlSecrets ,
1819} ;
1920
20- use super :: error:: PipelineError ;
21+ #[ derive( thiserror:: Error , Debug ) ]
22+ #[ error( "Failed to compile override label expression for label '{label}': {error}" ) ]
23+ pub struct OverrideLabelsCompileError {
24+ pub label : String ,
25+ pub error : String ,
26+ }
27+
28+ #[ derive( thiserror:: Error , Debug ) ]
29+ pub enum LabelEvaluationError {
30+ #[ error(
31+ "Failed to resolve VRL expression for override label '{label}'. Runtime error: {source}"
32+ ) ]
33+ ExpressionResolutionFailure {
34+ label : String ,
35+ source : ExpressionError ,
36+ } ,
37+ #[ error(
38+ "VRL expression for override label '{label}' did not evaluate to a boolean. Got: {got}"
39+ ) ]
40+ ExpressionWrongType { label : String , got : String } ,
41+ }
2142
2243/// Contains the request-specific context for progressive overrides.
2344/// This is stored in the request extensions
@@ -33,24 +54,11 @@ pub struct RequestOverrideContext {
3354pub fn request_override_context < ' req , F > (
3455 override_labels_evaluator : & OverrideLabelsEvaluator ,
3556 get_client_request : F ,
36- ) -> Result < RequestOverrideContext , PipelineError >
57+ ) -> Result < RequestOverrideContext , LabelEvaluationError >
3758where
3859 F : FnOnce ( ) -> ClientRequestDetails < ' req > ,
3960{
40- // No active flags by default - until we implement it
41- let active_flags = override_labels_evaluator. evaluate ( get_client_request) ;
42-
43- // for (flag_name, override_value) in override_labels_config.iter() {
44- // match override_value {
45- // LabelOverrideValue::Boolean(true) => {
46- // active_flags.insert(flag_name.clone());
47- // }
48- // // For other cases, we currently do nothing
49- // _ => {
50- // // TODO: support expressions
51- // }
52- // }
53- // }
61+ let active_flags = override_labels_evaluator. evaluate ( get_client_request) ?;
5462
5563 // Generate the random percentage value for this request.
5664 // Percentage is 0 - 100_000_000_000 (100*PERCENTAGE_SCALE_FACTOR)
@@ -116,7 +124,9 @@ pub struct OverrideLabelsEvaluator {
116124}
117125
118126impl OverrideLabelsEvaluator {
119- pub ( crate ) fn from_config ( override_labels_config : & OverrideLabelsConfig ) -> Self {
127+ pub ( crate ) fn from_config (
128+ override_labels_config : & OverrideLabelsConfig ,
129+ ) -> Result < Self , OverrideLabelsCompileError > {
120130 let mut static_enabled_labels = HashSet :: new ( ) ;
121131 let mut expressions = HashMap :: new ( ) ;
122132 let vrl_functions = vrl_build_functions ( ) ;
@@ -127,27 +137,41 @@ impl OverrideLabelsEvaluator {
127137 static_enabled_labels. insert ( label. clone ( ) ) ;
128138 }
129139 LabelOverrideValue :: Expression { expression } => {
130- let compilation_result = vrl_compile ( expression, & vrl_functions) . unwrap ( ) ;
140+ let compilation_result =
141+ vrl_compile ( expression, & vrl_functions) . map_err ( |diagnostics| {
142+ OverrideLabelsCompileError {
143+ label : label. clone ( ) ,
144+ error : diagnostics
145+ . errors ( )
146+ . into_iter ( )
147+ . map ( |d| d. code . to_string ( ) + ": " + & d. message )
148+ . collect :: < Vec < _ > > ( )
149+ . join ( ", " ) ,
150+ }
151+ } ) ?;
131152 expressions. insert ( label. clone ( ) , compilation_result. program ) ;
132153 }
133154 _ => { } // Skip false booleans
134155 }
135156 }
136157
137- Self {
158+ Ok ( Self {
138159 static_enabled_labels,
139160 expressions,
140- }
161+ } )
141162 }
142163
143- pub fn evaluate < ' req , F > ( & self , get_client_request : F ) -> HashSet < String >
164+ pub ( crate ) fn evaluate < ' req , F > (
165+ & self ,
166+ get_client_request : F ,
167+ ) -> Result < HashSet < String > , LabelEvaluationError >
144168 where
145169 F : FnOnce ( ) -> ClientRequestDetails < ' req > ,
146170 {
147171 let mut active_flags = self . static_enabled_labels . clone ( ) ;
148172
149173 if self . expressions . is_empty ( ) {
150- return active_flags;
174+ return Ok ( active_flags) ;
151175 }
152176
153177 let client_request = get_client_request ( ) ;
@@ -165,20 +189,30 @@ impl OverrideLabelsEvaluator {
165189 let mut ctx = VrlContext :: new ( & mut target, & mut state, & timezone) ;
166190
167191 for ( label, expression) in & self . expressions {
168- let evaluated_value = expression. resolve ( & mut ctx) . unwrap ( ) ;
169- match evaluated_value {
170- VrlValue :: Boolean ( true ) => {
171- active_flags. insert ( label. clone ( ) ) ;
172- }
173- VrlValue :: Boolean ( false ) => {
174- // Do nothing for false
175- }
176- _ => {
177- // TODO: error handling for non-boolean results
192+ match expression. resolve ( & mut ctx) {
193+ Ok ( evaluated_value) => match evaluated_value {
194+ VrlValue :: Boolean ( true ) => {
195+ active_flags. insert ( label. clone ( ) ) ;
196+ }
197+ VrlValue :: Boolean ( false ) => {
198+ // Do nothing for false
199+ }
200+ invalid_value => {
201+ return Err ( LabelEvaluationError :: ExpressionWrongType {
202+ label : label. clone ( ) ,
203+ got : format ! ( "{:?}" , invalid_value) ,
204+ } ) ;
205+ }
206+ } ,
207+ Err ( err) => {
208+ return Err ( LabelEvaluationError :: ExpressionResolutionFailure {
209+ label : label. clone ( ) ,
210+ source : err,
211+ } ) ;
178212 }
179213 }
180214 }
181215
182- active_flags
216+ Ok ( active_flags)
183217 }
184218}
0 commit comments