2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								package  expr  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								import  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"context" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"encoding/json" 
							 
						 
					
						
							
								
									
										
										
										
											2023-12-12 04:40:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"errors" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"fmt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									"strings" 
							 
						 
					
						
							
								
									
										
										
										
											2022-10-27 04:13:58 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"time" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana-plugin-sdk-go/data" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/expr/mathexp" 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 20:04:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/infra/tracing" 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									"github.com/grafana/grafana/pkg/services/featuremgmt" 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ThresholdCommand  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ReferenceVar   string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									RefID          string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ThresholdFunc  string 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Conditions     [ ] float64 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									Invert         bool 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								const  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ThresholdIsAbove         =  "gt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ThresholdIsBelow         =  "lt" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ThresholdIsWithinRange   =  "within_range" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									ThresholdIsOutsideRange  =  "outside_range" 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								var  (  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									supportedThresholdFuncs  =  [ ] string { ThresholdIsAbove ,  ThresholdIsBelow ,  ThresholdIsWithinRange ,  ThresholdIsOutsideRange } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								)  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  NewThresholdCommand ( refID ,  referenceVar ,  thresholdFunc  string ,  conditions  [ ] float64 )  ( * ThresholdCommand ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-04-20 17:42:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									switch  thresholdFunc  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsOutsideRange ,  ThresholdIsWithinRange : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( conditions )  <  2  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  fmt . Errorf ( "incorrect number of arguments: got %d but need 2" ,  len ( conditions ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsAbove ,  ThresholdIsBelow : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( conditions )  <  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  fmt . Errorf ( "incorrect number of arguments: got %d but need 1" ,  len ( conditions ) ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "expected threshold function to be one of [%s], got %s" ,  strings . Join ( supportedThresholdFuncs ,  ", " ) ,  thresholdFunc ) 
							 
						 
					
						
							
								
									
										
										
										
											2023-04-20 17:42:34 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									return  & ThresholdCommand { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										RefID :          refID , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ReferenceVar :   referenceVar , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										ThresholdFunc :  thresholdFunc , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										Conditions :     conditions , 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ConditionEvalJSON  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Params  [ ] float64  ` json:"params" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Type    string     ` json:"type" `  // e.g. "gt"
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// UnmarshalResampleCommand creates a ResampleCMD from Grafana's frontend query.
  
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  UnmarshalThresholdCommand ( rn  * rawNode ,  features  featuremgmt . FeatureToggles )  ( Command ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									cmdConfig  :=  ThresholdCommandConfig { } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  :=  json . Unmarshal ( rn . QueryRaw ,  & cmdConfig ) ;  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "failed to parse the threshold command: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  cmdConfig . Expression  ==  ""  { 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "no variable specified to reference for refId %v" ,  rn . RefID ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									referenceVar  :=  cmdConfig . Expression 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									// we only support one condition for now, we might want to turn this in to "OR" expressions later
 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  len ( cmdConfig . Conditions )  !=  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "threshold expression requires exactly one condition" ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									firstCondition  :=  cmdConfig . Conditions [ 0 ] 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									threshold ,  err  :=  NewThresholdCommand ( rn . RefID ,  referenceVar ,  firstCondition . Evaluator . Type ,  firstCondition . Evaluator . Params ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										return  nil ,  fmt . Errorf ( "invalid condition: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-11-15 04:50:27 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									if  firstCondition . UnloadEvaluator  !=  nil  &&  features . IsEnabledGlobally ( featuremgmt . FlagRecoveryThreshold )  { 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										unloading ,  err  :=  NewThresholdCommand ( rn . RefID ,  referenceVar ,  firstCondition . UnloadEvaluator . Type ,  firstCondition . UnloadEvaluator . Params ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										unloading . Invert  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  fmt . Errorf ( "invalid unloadCondition: %w" ,  err ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										var  d  Fingerprints 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  firstCondition . LoadedDimensions  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											d ,  err  =  FingerprintsFromFrame ( firstCondition . LoadedDimensions ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
												return  nil ,  fmt . Errorf ( "failed to parse loaded dimensions: %w" ,  err ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  NewHysteresisCommand ( rn . RefID ,  referenceVar ,  * threshold ,  * unloading ,  d ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  threshold ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// NeedsVars returns the variable names (refIds) that are dependencies
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// to execute the command and allows the command to fulfill the Command interface.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  ( tc  * ThresholdCommand )  NeedsVars ( )  [ ] string  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  [ ] string { tc . ReferenceVar } 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 20:04:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  ( tc  * ThresholdCommand )  Execute ( ctx  context . Context ,  now  time . Time ,  vars  mathexp . Vars ,  tracer  tracing . Tracer )  ( mathexp . Results ,  error )  {  
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									mathExpression ,  err  :=  createMathExpression ( tc . ReferenceVar ,  tc . ThresholdFunc ,  tc . Conditions ,  tc . Invert ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mathexp . Results { } ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									mathCommand ,  err  :=  NewMathCommand ( tc . ReferenceVar ,  mathExpression ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  mathexp . Results { } ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
									
										
										
										
											2023-04-18 20:04:51 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
									return  mathCommand . Execute ( ctx ,  now ,  vars ,  tracer ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// createMathExpression converts all the info we have about a "threshold" expression in to a Math expression
  
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								func  createMathExpression ( referenceVar  string ,  thresholdFunc  string ,  args  [ ] float64 ,  invert  bool )  ( string ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  exp  string 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									switch  thresholdFunc  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsAbove : 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exp  =  fmt . Sprintf ( "${%s} > %f" ,  referenceVar ,  args [ 0 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsBelow : 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exp  =  fmt . Sprintf ( "${%s} < %f" ,  referenceVar ,  args [ 0 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsWithinRange : 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exp  =  fmt . Sprintf ( "${%s} > %f && ${%s} < %f" ,  referenceVar ,  args [ 0 ] ,  referenceVar ,  args [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									case  ThresholdIsOutsideRange : 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
										exp  =  fmt . Sprintf ( "${%s} < %f || ${%s} > %f" ,  referenceVar ,  args [ 0 ] ,  referenceVar ,  args [ 1 ] ) 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  "" ,  fmt . Errorf ( "failed to evaluate threshold expression: no such threshold function %s" ,  thresholdFunc ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  invert  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  fmt . Sprintf ( "!(%s)" ,  exp ) ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  exp ,  nil 
							 
						 
					
						
							
								
									
										
										
										
											2022-09-26 22:05:44 +08:00 
										
									 
								 
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  IsSupportedThresholdFunc ( name  string )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									isSupported  :=  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									for  _ ,  funcName  :=  range  supportedThresholdFuncs  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  funcName  ==  name  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											isSupported  =  true 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  isSupported 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2023-10-10 22:51:50 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ThresholdCommandConfig  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Expression  string                    ` json:"expression" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Conditions  [ ] ThresholdConditionJSON  ` json:"conditions" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								type  ThresholdConditionJSON  struct  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									Evaluator         ConditionEvalJSON   ` json:"evaluator" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									UnloadEvaluator   * ConditionEvalJSON  ` json:"unloadEvaluator" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									LoadedDimensions  * data . Frame         ` json:"loadedDimensions" ` 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
									
										
										
										
											2023-12-12 04:40:31 +08:00 
										
									 
								 
							 
							
								
									
										 
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// IsHysteresisExpression returns true if the raw model describes a hysteresis command:
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - field 'type' has value "threshold",
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - field 'conditions' is array of objects and has exactly one element
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// - field 'conditions[0].unloadEvaluator is not nil
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  IsHysteresisExpression ( query  map [ string ] any )  bool  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c ,  err  :=  getConditionForHysteresisCommand ( query ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  false 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  c  !=  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								// SetLoadedDimensionsToHysteresisCommand mutates the input map and sets field "conditions[0].loadedMetrics" with the data frame created from the provided fingerprints.
  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  SetLoadedDimensionsToHysteresisCommand ( query  map [ string ] any ,  fingerprints  Fingerprints )  error  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									condition ,  err  :=  getConditionForHysteresisCommand ( query ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  condition  ==  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  errors . New ( "not a hysteresis command" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									fr  :=  FingerprintsToFrame ( fingerprints ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									condition [ "loadedDimensions" ]  =  fr 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								func  getConditionForHysteresisCommand ( query  map [ string ] any )  ( map [ string ] any ,  error )  {  
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									t ,  err  :=  GetExpressionCommandType ( query ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  err  !=  nil  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  err 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  t  !=  TypeThreshold  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "not a threshold command" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									c ,  ok  :=  query [ "conditions" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "invalid threshold command: expected field \"condition\"" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									var  condition  map [ string ] any 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									switch  arr  :=  c . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									case  [ ] any : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										if  len ( arr )  !=  1  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  errors . New ( "invalid threshold command: field \"condition\" expected to have exactly 1 field" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										switch  m  :=  arr [ 0 ] . ( type )  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										case  map [ string ] any : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											condition  =  m 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
											return  nil ,  errors . New ( "invalid threshold command: value of the first element of field \"condition\" expected to be an object" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									default : 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  errors . New ( "invalid threshold command: field \"condition\" expected to be an array of objects" ) 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									_ ,  ok  =  condition [ "unloadEvaluator" ] 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									if  ! ok  { 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
										return  nil ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									} 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
									return  condition ,  nil 
							 
						 
					
						
							
								
							 
							
								
							 
							
								 
							
							
								}