Validate ensures a threshold definition is consistent with the metric it applies to. Given a metric registry and a metric name to apply the expressions too, Validate will assert that each threshold expression uses an aggregation method that's supported by the provided metric. It returns an error oth
(metricName string, r *Registry)
| 238 | // Note that this function expects the passed in thresholds to have been parsed already, and |
| 239 | // have their Parsed (ThresholdExpression) field already filled. |
| 240 | func (ts *Thresholds) Validate(metricName string, r *Registry) error { |
| 241 | parsedMetricName, _, err := ParseMetricName(metricName) |
| 242 | if err != nil { |
| 243 | parseErr := fmt.Errorf("unable to validate threshold expressions; reason: %w", err) |
| 244 | return errext.WithExitCodeIfNone(parseErr, exitcodes.InvalidConfig) |
| 245 | } |
| 246 | |
| 247 | // Obtain the metric the thresholds apply to from the registry. |
| 248 | // if the metric doesn't exist, then we return an error indicating |
| 249 | // the InvalidConfig exitcode should be used. |
| 250 | metric := r.Get(parsedMetricName) |
| 251 | if metric == nil { |
| 252 | err := fmt.Errorf("%w defined on %s; reason: no metric name %q found", ErrInvalidThreshold, metricName, metricName) |
| 253 | return errext.WithExitCodeIfNone(err, exitcodes.InvalidConfig) |
| 254 | } |
| 255 | |
| 256 | for _, threshold := range ts.Thresholds { |
| 257 | // Return a digestable error if we attempt to validate a threshold |
| 258 | // that hasn't been parsed yet. |
| 259 | if threshold.parsed == nil { |
| 260 | thresholdExpression, err := parseThresholdExpression(threshold.Source) |
| 261 | if err != nil { |
| 262 | return fmt.Errorf("unable to validate threshold %q on metric %s; reason: "+ |
| 263 | "parsing threshold failed %w", threshold.Source, metricName, err) |
| 264 | } |
| 265 | |
| 266 | threshold.parsed = thresholdExpression |
| 267 | } |
| 268 | |
| 269 | // If the threshold's expression aggregation method is not |
| 270 | // supported for the metric we validate against, then we return |
| 271 | // an error indicating the InvalidConfig exitcode should be used. |
| 272 | if !metric.Type.supportsAggregationMethod(threshold.parsed.AggregationMethod) { |
| 273 | err := fmt.Errorf( |
| 274 | "%w %q applied on metric %s; reason: "+ |
| 275 | "unsupported aggregation method %s on metric of type %s. "+ |
| 276 | "supported aggregation methods for this metric are: %s", |
| 277 | ErrInvalidThreshold, threshold.Source, metricName, |
| 278 | threshold.parsed.AggregationMethod, metric.Type, |
| 279 | strings.Join(metric.Type.supportedAggregationMethods(), ", "), |
| 280 | ) |
| 281 | return errext.WithExitCodeIfNone(err, exitcodes.InvalidConfig) |
| 282 | } |
| 283 | } |
| 284 | |
| 285 | return nil |
| 286 | } |
| 287 | |
| 288 | // UnmarshalJSON is implementation of json.Unmarshaler |
| 289 | func (ts *Thresholds) UnmarshalJSON(data []byte) error { |