1# Copyright 2015 The Chromium Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5"""The database models for anomaly alerting threshold configs.""" 6 7import logging 8 9from google.appengine.ext import ndb 10 11# The parameters to use from anomaly threshold config dict. 12# Any parameters in such a dict that aren't in this list will be ignored. 13_VALID_ANOMALY_CONFIG_PARAMETERS = { 14 'max_window_size', 15 'min_segment_size', 16 'min_absolute_change', 17 'min_relative_change', 18 'min_steppiness', 19 'multiple_of_std_dev', 20} 21 22 23class AnomalyConfig(ndb.Model): 24 """Represents a set of parameters for the anomaly detection function. 25 26 The anomaly detection module uses set of parameters to determine the 27 thresholds for what is considered an anomaly. 28 """ 29 # A dictionary mapping parameter names to values. 30 config = ndb.JsonProperty(required=True, indexed=False) 31 32 # A list of test path patterns. Each pattern is a string which can match parts 33 # of the test path either exactly, or use * as a wildcard. 34 # Note: TestMetadata entities contain a key property called 35 # overridden_anomaly_config, which is set in the pre-put hook for TestMetadata 36 # in graph_data.py. 37 patterns = ndb.StringProperty(repeated=True, indexed=False) 38 39 40def CleanConfigDict(config_dict): 41 """Removes invalid parameters from a config dictionary. 42 43 In the config dict there may be extra "comment" parameters which 44 should be ignored. These are removed so that the parameters can 45 be passed to FindChangePoints using ** notation. 46 """ 47 return {key: value for key, value in config_dict.iteritems() 48 if key in _VALID_ANOMALY_CONFIG_PARAMETERS} 49 50 51def GetAnomalyConfigDict(test): 52 """Gets the anomaly threshold config for the given test. 53 54 Args: 55 test: TestMetadata entity to get the config for. 56 57 Returns: 58 A dictionary with threshold parameters for the given test. 59 """ 60 if not test.overridden_anomaly_config: 61 return {} 62 anomaly_config = test.overridden_anomaly_config.get() 63 if not anomaly_config: 64 logging.warning('No AnomalyConfig fetched from key %s for test %s', 65 test.overridden_anomaly_config, test.test_path) 66 # The the overridden_anomaly_config property should be reset 67 # in the pre-put hook of the TestMetadata entity. 68 test.put() 69 return {} 70 return CleanConfigDict(anomaly_config.config) 71