def meter_sms_actions(self, project_id, receivers): ctxt = get_admin_context() local_receivers = [r for r in receivers if r.startswith("+82")] international_receivers = [ r for r in receivers if not r.startswith("+82") ] self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS", metric_name="LocalSMSActionCount", dimensions={}, value=len(local_receivers), unit="Count", timestamp=utils.strtime(utils.utcnow()), is_admin=True) self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS", metric_name="InternationalSMSActionCount", dimensions={}, value=len(international_receivers), unit="Count", timestamp=utils.strtime(utils.utcnow()), is_admin=True) LOG.audit("Meter SMS: %s %s %s", project_id, len(receivers), receivers)
def parse_metric_data(metric): try: dimensions_ = metric.get('dimensions', {}) dimensions = utils.extract_member_dict(dimensions_) except KeyError: err = "Unsuitable Dimensions Value - %s" % str(dimensions_) raise InvalidParameterValue(err) self.check_dimensions(dimensions) metric_name = metric.get('metric_name') unit = metric.get('unit', 'None') value = metric.get('value') req_timestamp = metric.get('timestamp') timestamp = req_timestamp if req_timestamp \ else utils.strtime(utils.utcnow()) timebound = (datetime.datetime.utcnow() - datetime.timedelta( seconds=FLAGS.get('statistics_ttl'))) if utils.parse_strtime(timestamp) < timebound: err = "Stale metric data - %s" % timestamp raise InvalidParameterValue(err) self.check_metric_name(metric_name) self.check_unit(unit) return metric_name, dimensions, value, unit, timestamp
def put_metric_data(self, context, project_id, namespace, metric_name, dimensions, value, unit, timestamp=None, is_admin=False): admin_namespace = FLAGS.get('admin_namespace') if namespace.startswith(admin_namespace) and not is_admin: raise AdminRequired() timestamp = timestamp or utils.strtime(utils.utcnow()) message = { 'project_id': project_id, 'namespace': namespace, 'metric_name': metric_name, 'dimensions': dimensions, 'value': value, 'unit': unit, 'timestamp': timestamp, 'context': context.to_dict() } self.rpc.send_msg(rpc.PUT_METRIC_DATA_MSG_ID, message) LOG.info("PUT_METRIC_DATA_MSG sent") return {}
def meter_instance_actions(self, project_id, receivers): ctxt = get_admin_context() self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS", metric_name="InstanceActionCount", dimensions={}, value=len(receivers), unit="Count", timestamp=utils.strtime(utils.utcnow()), is_admin=True) LOG.audit("Meter InstanceAction: %s %s %s", project_id, len(receivers), receivers)
def to_dict(self): return { "user_id": self.user_id, "project_id": self.project_id, "is_admin": self.is_admin, "read_deleted": self.read_deleted, "roles": self.roles, "remote_address": self.remote_address, "timestamp": utils.strtime(self.timestamp), "request_id": self.request_id, "auth_token": self.auth_token, "strategy": self.strategy, }
def to_dict(self): return { 'user_id': self.user_id, 'project_id': self.project_id, 'is_admin': self.is_admin, 'read_deleted': self.read_deleted, 'roles': self.roles, 'remote_address': self.remote_address, 'timestamp': utils.strtime(self.timestamp), 'request_id': self.request_id, 'auth_token': self.auth_token, 'strategy': self.strategy }
def meter_sms_actions(self, project_id, receivers): ctxt = get_admin_context() local_receivers = [r for r in receivers if r.startswith("+82")] international_receivers = [r for r in receivers if not r.startswith("+82")] self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS", metric_name="LocalSMSActionCount", dimensions={}, value=len(local_receivers), unit="Count", timestamp=utils.strtime(utils.utcnow()), is_admin=True) self.api.put_metric_data(ctxt, project_id, namespace="SPCS/SYNAPS", metric_name="InternationalSMSActionCount", dimensions={}, value=len(international_receivers), unit="Count", timestamp=utils.strtime(utils.utcnow()), is_admin=True) LOG.audit("Meter SMS: %s %s %s", project_id, len(receivers), receivers)
def put_metric_data(self, context, project_id, namespace, metric_name, dimensions, value, unit, timestamp=None, is_admin=False): admin_namespace = FLAGS.get('admin_namespace') if namespace.startswith(admin_namespace) and not is_admin: raise AdminRequired() timestamp = timestamp or utils.strtime(utils.utcnow()) message = {'project_id': project_id, 'namespace':namespace, 'metric_name': metric_name, 'dimensions': dimensions, 'value':value, 'unit':unit, 'timestamp':timestamp, 'context': context.to_dict()} self.rpc.send_msg(rpc.PUT_METRIC_DATA_MSG_ID, message) LOG.info("PUT_METRIC_DATA_MSG sent") return {}
def parse_metric_data(metric): try: dimensions_ = metric.get('dimensions', {}) dimensions = utils.extract_member_dict(dimensions_) except KeyError: err = "Unsuitable Dimensions Value - %s" % str(dimensions_) raise InvalidParameterValue(err) metric_name = metric.get('metric_name') unit = metric.get('unit', 'None') value = metric.get('value') req_timestamp = metric.get('timestamp') timestamp = req_timestamp if req_timestamp \ else utils.strtime(utils.utcnow()) self.check_metric_name(metric_name) self.check_unit(unit) return metric_name, dimensions, value, unit, timestamp
def metricalarm_for_json(metricalarm): cut = metricalarm.get('alarm_configuration_updated_timestamp') alarm_for_json = { 'actionEnabled': metricalarm.get('actions_enabled', False), 'alarmActions': metricalarm.get('alarm_actions', []), 'alarmArn': metricalarm.get('alarm_arn'), 'alarmConfigurationUpdatedTimestamp': utils.strtime(cut), 'alarmDescription': metricalarm.get('alarm_description'), 'alarmName': metricalarm.get('alarm_name'), 'comparisonOperator': metricalarm.get('comparison_operator'), 'dimensions': metricalarm.get('dimensions'), 'evaluationPeriods': metricalarm.get('evaluation_periods'), 'insufficientDataActions': metricalarm.get('insufficient_data_actions', []), 'metricName': metricalarm.get('metric_name'), 'namespace': metricalarm.get('namespace'), 'okactions': metricalarm.get('ok_actions', []), 'statistic': metricalarm.get('statistic'), 'threshold': metricalarm.get('threshold'), 'unit': metricalarm.get('unit'), } return alarm_for_json
def metricalarm_for_json(metricalarm): cut = metricalarm.get('alarm_configuration_updated_timestamp') alarm_for_json = { 'actionEnabled': metricalarm.get('actions_enabled', False), 'alarmActions': metricalarm.get('alarm_actions', []), 'alarmArn': metricalarm.get('alarm_arn'), 'alarmConfigurationUpdatedTimestamp': utils.strtime(cut), 'alarmDescription': metricalarm.get('alarm_description'), 'alarmName': metricalarm.get('alarm_name'), 'comparisonOperator': metricalarm.get('comparison_operator'), 'dimensions': metricalarm.get('dimensions'), 'evaluationPeriods': metricalarm.get('evaluation_periods'), 'insufficientDataActions': metricalarm.get('insufficient_data_actions', []), 'metricName':metricalarm.get('metric_name'), 'namespace':metricalarm.get('namespace'), 'okactions':metricalarm.get('ok_actions', []), 'statistic':metricalarm.get('statistic'), 'threshold':metricalarm.get('threshold'), 'unit':metricalarm.get('unit'), } return alarm_for_json
def _check_alarm(self, alarmkey, alarm): period = int(alarm["period"] / 60) evaluation_periods = alarm["evaluation_periods"] statistic = alarm["statistic"] threshold = alarm["threshold"] cmp_op = self.CMP_MAP[alarm["comparison_operator"]] unit = alarm["unit"] state_value = alarm["state_value"] now = utils.utcnow() end_idx = now.replace(second=0, microsecond=0) - datetools.Minute() start_idx = end_idx - (evaluation_periods - 1) * datetools.Minute() start_ana_idx = start_idx - datetools.Minute() * period func = self.ROLLING_FUNC_MAP[statistic] data = func(self.df[statistic].ix[start_ana_idx:end_idx], period, min_periods=0).ix[start_idx:end_idx] if statistic == "SampleCount": data = data.fillna(0) else: if unit: data = data / utils.UNIT_CONV_MAP[unit] threshold = threshold / utils.UNIT_CONV_MAP[unit] data = data.dropna() query_date = utils.strtime(now) reason_data = { "period": alarm["period"], "queryDate": query_date, "recentDatapoints": list(data), "startDate": utils.strtime(start_idx), "statistic": statistic, "threshold": threshold, "version": "1.0", } old_state = { "stateReason": alarm.get("reason", ""), "stateValue": alarm.get("state_value", "INSUFFICIENT_DATA"), "stateReasonData": json.loads(alarm.get("reason_data", "{}")), } json_reason_data = json.dumps(reason_data) if len(data) < evaluation_periods: if state_value != "INSUFFICIENT_DATA": template = _("Insufficient Data: %d datapoints were unknown.") reason = template % (evaluation_periods - len(data)) new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "INSUFFICIENT_DATA"} self.update_alarm_state(alarmkey, "INSUFFICIENT_DATA", reason, json_reason_data, now) self.cass.update_alarm_state(alarmkey, "INSUFFICIENT_DATA", reason, json_reason_data, now) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) storm.log("INSUFFICIENT_DATA alarm") else: crossed = reduce(operator.and_, cmp_op(data, threshold)) com_op = alarm["comparison_operator"] if crossed: template = _( "Threshold Crossed: %d datapoints were %s " + "the threshold(%f). " + "The most recent datapoints: %s." ) reason = template % (len(data), self.CMP_STR_MAP[com_op], threshold, str(list(data))) if state_value != "ALARM": new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "ALARM"} self.update_alarm_state(alarmkey, "ALARM", reason, json_reason_data, now) self.cass.update_alarm_state(alarmkey, "ALARM", reason, json_reason_data, now) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) storm.log("ALARM alarm") else: template = _( "Threshold Crossed: %d datapoints were not %s " + "the threshold(%f). " + "The most recent datapoints: %s." ) reason = template % (len(data), self.CMP_STR_MAP[com_op], threshold, str(list(data))) if state_value != "OK": new_state = {"stateReason": reason, "stateReasonData": reason_data, "stateValue": "OK"} self.update_alarm_state(alarmkey, "OK", reason, json_reason_data, now) self.cass.update_alarm_state(alarmkey, "OK", reason, json_reason_data, now) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) storm.log("OK alarm")
def _check_alarm(self, alarmkey, alarm, query_time=None): period = int(alarm['period'] / 60) evaluation_periods = alarm['evaluation_periods'] statistic = alarm['statistic'] threshold = alarm['threshold'] alarm_name = alarm['alarm_name'] cmp_op = self.CMP_MAP[alarm['comparison_operator']] unit = alarm['unit'] state_value = alarm['state_value'] query_time = query_time if query_time else utils.utcnow() for i in range(self.insufficient_buffer): end_idx = (query_time.replace(second=0, microsecond=0) - (i + 1) * datetools.Minute()) try: end_datapoint = self.df[statistic].ix[end_idx] except KeyError: end_datapoint = None if not isnull(end_datapoint): break start_idx = (end_idx - (period * evaluation_periods) * datetools.Minute()) start_ana_idx = start_idx - datetools.Minute() * period func = self.ROLLING_FUNC_MAP[statistic] data = func(self.df[statistic].ix[start_ana_idx:end_idx], period, min_periods=0).ix[start_idx:end_idx:period][1:] recent_datapoints = list(data) if unit and statistic is not 'SampleCount': data = data / utils.UNIT_CONV_MAP[unit] threshold = threshold / utils.UNIT_CONV_MAP[unit] data = data.dropna() query_date = utils.strtime(query_time) reason_data = { "period":alarm['period'], "queryDate":query_date, "recentDatapoints": recent_datapoints, "startDate": utils.strtime(start_idx), "statistic":statistic, "threshold": threshold, "version":"1.0", } old_state = {'stateReason':alarm.get('reason', ""), 'stateValue':alarm.get('state_value', "INSUFFICIENT_DATA"), 'stateReasonData': json.loads(alarm.get('reason_data', "{}"))} json_reason_data = json.dumps(reason_data) if len(data) == 0: if state_value != 'INSUFFICIENT_DATA': template = _("Insufficient Data: %d datapoints were unknown.") reason = template % (evaluation_periods - len(data)) new_state = {'stateReason':reason, 'stateReasonData':reason_data, 'stateValue':'INSUFFICIENT_DATA'} self.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to INSUFFICIENT_DATA", alarm_name) else: sufficient = len(data) >= evaluation_periods crossed = (sufficient and reduce(operator.and_, cmp_op(data, threshold))) com_op = alarm['comparison_operator'] if crossed: template = _("Threshold Crossed: %d datapoints were %s " + "the threshold(%f). " + "The most recent datapoints: %s.") reason = template % (evaluation_periods, self.CMP_STR_MAP[com_op], threshold, recent_datapoints) if state_value != 'ALARM': new_state = {'stateReason':reason, 'stateReasonData':reason_data, 'stateValue':'ALARM'} self.update_alarm_state(alarmkey, 'ALARM', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'ALARM', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to ALARM", alarm_name) else: template = _("Threshold Crossed: %d datapoints were not %s " + "the threshold(%f). " + "The most recent datapoints: %s.") reason = template % (evaluation_periods, self.CMP_STR_MAP[com_op], threshold, recent_datapoints) if state_value != 'OK': new_state = {'stateReason':reason, 'stateReasonData':reason_data, 'stateValue':'OK'} self.update_alarm_state(alarmkey, 'OK', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'OK', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to OK", alarm_name)
def put_metric_alarm(self, project_id, metricalarm): """ 알람을 DB에 넣고 값이 빈 dictionary 를 반환한다. 메트릭 유무 확인 알람 히스토리 발생. """ def metricalarm_for_json(metricalarm): alarm_for_json = { 'actionEnabled': metricalarm.get('actions_enabled', False), 'alarmActions': metricalarm.get('alarm_actions', []), 'alarmArn': metricalarm.get('alarm_arn'), 'alarmConfigurationUpdatedTimestamp': metricalarm.get('alarm_configuration_updated_timestamp'), 'alarmDescription': metricalarm.get('alarm_description'), 'alarmName': metricalarm.get('alarm_name'), 'comparisonOperator': metricalarm.get('comparison_operator'), 'dimensions': metricalarm.get('dimensions'), 'evaluationPeriods': metricalarm.get('evaluation_periods'), 'insufficientDataActions': metricalarm.get('insufficient_data_actions', []), 'metricName':metricalarm.get('metric_name'), 'namespace':metricalarm.get('namespace'), 'okactions':metricalarm.get('ok_actions', []), 'statistic':metricalarm.get('statistic'), 'threshold':metricalarm.get('threshold'), 'unit':metricalarm.get('unit'), } return alarm_for_json now = utils.utcnow() metricalarm = metricalarm.to_columns() # 메트릭 유무 확인 metric_key = self.cass.get_metric_key_or_create( project_id=project_id, namespace=metricalarm['namespace'], metric_name=metricalarm['metric_name'], dimensions=json.loads(metricalarm['dimensions']), unit=metricalarm['unit'], ) metricalarm['project_id'] = project_id metricalarm['metric_key'] = metric_key metricalarm['alarm_arn'] = "arn:spcs:synaps:%s:alarm:%s" % ( project_id, metricalarm['alarm_name'] ) metricalarm['alarm_configuration_updated_timestamp'] = now # 알람 유무 확인 alarm_key = self.cass.get_metric_alarm_key( project_id=project_id, alarm_name=metricalarm['alarm_name'] ) if alarm_key: history_type = 'Update' before_alarm = self.cass.get_metric_alarm(alarm_key) if before_alarm['metric_key'] != metricalarm['metric_key']: raise InvalidRequest("Metric cannot be changed.") metricalarm['state_updated_timestamp'] = \ before_alarm['state_updated_timestamp'] metricalarm['state_reason'] = before_alarm['state_reason'] metricalarm['state_reason_data'] = \ before_alarm['state_reason_data'] metricalarm['state_value'] = before_alarm['state_value'] else: history_type = "Create" alarm_key = uuid.uuid4() metricalarm['state_updated_timestamp'] = utils.utcnow() metricalarm['state_reason'] = "Unchecked: Initial alarm creation" metricalarm['state_reason_data'] = json.dumps({}) metricalarm['state_value'] = "INSUFFICIENT_DATA" # insert alarm into database self.cass.put_metric_alarm(alarm_key, metricalarm) LOG.debug("metric alarm inserted alarm key: %s" % (alarm_key)) # to make json, convert datetime type into str metricalarm['state_updated_timestamp'] = utils.strtime( metricalarm['state_updated_timestamp'] ) metricalarm['alarm_configuration_updated_timestamp'] = utils.strtime( metricalarm['alarm_configuration_updated_timestamp'] ) metricalarm['metric_key'] = str(metric_key) if history_type == "Update": history_data = json.dumps({ 'updatedAlarm':metricalarm_for_json(metricalarm), 'type':history_type, 'version': '1.0' }) summary = "Alarm %s updated" % metricalarm['alarm_name'] else: history_data = json.dumps({ 'createdAlarm': metricalarm_for_json(metricalarm), 'type':history_type, 'version': '1.0' }) summary = "Alarm %s created" % metricalarm['alarm_name'] history_key = uuid.uuid4() history_column = { 'project_id': project_id, 'alarm_key': alarm_key, 'alarm_name': metricalarm['alarm_name'], 'history_data': history_data, 'history_item_type': 'ConfigurationUpdate', 'history_summary':summary, 'timestamp': utils.utcnow() } self.cass.insert_alarm_history(history_key, history_column) message = {'project_id': project_id, 'metric_key': str(metric_key), 'metricalarm': metricalarm} self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message) LOG.info("PUT_METRIC_ALARM_MSG sent") return {}
def put_metric_alarm(self, context, project_id, metricalarm): """ Send put metric alarm message to Storm """ def _validate_actions(alarm): for actions in (alarm.ok_actions, alarm.insufficient_data_actions, alarm.alarm_actions): for action in actions: if utils.validate_groupnotification_action(action): group = utils.parse_groupnotification_action(action) if not self.cass.get_notification_group(group): raise InvalidNotificationGroup() now = utils.utcnow() _validate_actions(metricalarm) metricalarm = metricalarm.to_columns() alarm_name = metricalarm['alarm_name'] namespace = metricalarm['namespace'] metric_name = metricalarm['metric_name'] dimensions = json.loads(metricalarm['dimensions']) # check if we have metric in database metric_key = self.cass.get_metric_key_or_create( project_id=project_id, namespace=namespace, metric_name=metric_name, dimensions=dimensions, unit=metricalarm['unit']) update_data = { 'project_id': project_id, 'metric_key': str(metric_key), 'alarm_arn': "arn:spcs:synaps:%s:alarm:%s" % (project_id, alarm_name), 'alarm_configuration_updated_timestamp': utils.strtime(now) } metricalarm.update(update_data) # check if metric is changed alarm_key = self.cass.get_metric_alarm_key(project_id=project_id, alarm_name=alarm_name) if alarm_key: original_alarm = self.cass.get_metric_alarm(alarm_key) if (str(original_alarm['metric_key']) != str( metricalarm['metric_key'])): raise InvalidRequest("Metric cannot be changed. " "Delete alarm and retry.") else: # If alarm is newly added, check quotas # check alarm quota per project project_quota = FLAGS.get('alarm_quota_per_project') alarms_in_project = self.cass.get_alarm_count(project_id) if alarms_in_project >= project_quota: LOG.info("Too many alarms(%d) in the project %s", alarms_in_project, project_id) raise ProjectAlarmQuotaExceeded() # check alarm quota per metric metric_quota = FLAGS.get('alarm_quota_per_metric') alarms_per_metric = self.cass.get_alarms_per_metric_count( project_id, namespace, metric_name, dimensions) if alarms_per_metric >= metric_quota: LOG.info("Too many alarms(%d) for this metric", alarms_per_metric) raise MetricAlarmQuotaExceeded() message = { 'project_id': project_id, 'metric_key': str(metric_key), 'metricalarm': metricalarm, 'context': context.to_dict() } self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message) LOG.info("PUT_METRIC_ALARM_MSG sent") return {}
def _check_alarm(self, alarmkey, alarm, query_time=None): period = int(alarm['period'] / 60) evaluation_periods = alarm['evaluation_periods'] statistic = alarm['statistic'] threshold = alarm['threshold'] alarm_name = alarm['alarm_name'] cmp_op = self.CMP_MAP[alarm['comparison_operator']] unit = alarm['unit'] state_value = alarm['state_value'] query_time = query_time if query_time else utils.utcnow() for i in range(self.insufficient_buffer): end_idx = (query_time.replace(second=0, microsecond=0) - (i + 1) * datetools.Minute()) try: end_datapoint = self.df[statistic].ix[end_idx] except KeyError: end_datapoint = None if not isnull(end_datapoint): break start_idx = (end_idx - (period * evaluation_periods) * datetools.Minute()) start_ana_idx = start_idx - datetools.Minute() * period func = self.ROLLING_FUNC_MAP[statistic] data = func(self.df[statistic].ix[start_ana_idx:end_idx], period, min_periods=0).ix[start_idx:end_idx:period][1:] recent_datapoints = list(data) if unit and statistic is not 'SampleCount': data = data / utils.UNIT_CONV_MAP[unit] threshold = threshold / utils.UNIT_CONV_MAP[unit] data = data.dropna() query_date = utils.strtime(query_time) reason_data = { "period": alarm['period'], "queryDate": query_date, "recentDatapoints": recent_datapoints, "startDate": utils.strtime(start_idx), "statistic": statistic, "threshold": threshold, "version": "1.0", } old_state = { 'stateReason': alarm.get('reason', ""), 'stateValue': alarm.get('state_value', "INSUFFICIENT_DATA"), 'stateReasonData': json.loads(alarm.get('reason_data', "{}")) } json_reason_data = json.dumps(reason_data) if len(data) == 0: if state_value != 'INSUFFICIENT_DATA': template = _("Insufficient Data: %d datapoints were unknown.") reason = template % (evaluation_periods - len(data)) new_state = { 'stateReason': reason, 'stateReasonData': reason_data, 'stateValue': 'INSUFFICIENT_DATA' } self.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'INSUFFICIENT_DATA', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to INSUFFICIENT_DATA", alarm_name) else: sufficient = len(data) >= evaluation_periods crossed = (sufficient and reduce(operator.and_, cmp_op(data, threshold))) com_op = alarm['comparison_operator'] if crossed: template = _("Threshold Crossed: %d datapoints were %s " + "the threshold(%f). " + "The most recent datapoints: %s.") reason = template % (evaluation_periods, self.CMP_STR_MAP[com_op], threshold, recent_datapoints) if state_value != 'ALARM': new_state = { 'stateReason': reason, 'stateReasonData': reason_data, 'stateValue': 'ALARM' } self.update_alarm_state(alarmkey, 'ALARM', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'ALARM', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to ALARM", alarm_name) else: template = _("Threshold Crossed: %d datapoints were not %s " + "the threshold(%f). " + "The most recent datapoints: %s.") reason = template % (evaluation_periods, self.CMP_STR_MAP[com_op], threshold, recent_datapoints) if state_value != 'OK': new_state = { 'stateReason': reason, 'stateReasonData': reason_data, 'stateValue': 'OK' } self.update_alarm_state(alarmkey, 'OK', reason, json_reason_data, query_time) self.cass.update_alarm_state(alarmkey, 'OK', reason, json_reason_data, query_time) self.alarm_history_state_update(alarmkey, alarm, new_state, old_state) self.do_alarm_action(alarmkey, alarm, new_state, old_state, query_date) LOG.audit("Alarm %s status changed to OK", alarm_name)
def put_metric_alarm(self, context, project_id, metricalarm): """ Send put metric alarm message to Storm """ def _validate_actions(alarm): for actions in (alarm.ok_actions, alarm.insufficient_data_actions, alarm.alarm_actions): for action in actions: if utils.validate_groupnotification_action(action): group = utils.parse_groupnotification_action(action) if not self.cass.get_notification_group(group): raise InvalidNotificationGroup() now = utils.utcnow() _validate_actions(metricalarm) metricalarm = metricalarm.to_columns() alarm_name = metricalarm['alarm_name'] namespace = metricalarm['namespace'] metric_name = metricalarm['metric_name'] dimensions = json.loads(metricalarm['dimensions']) # check if we have metric in database metric_key = self.cass.get_metric_key_or_create(project_id=project_id, namespace=namespace, metric_name=metric_name, dimensions=dimensions, unit=metricalarm['unit']) update_data = { 'project_id': project_id, 'metric_key': str(metric_key), 'alarm_arn': "arn:spcs:synaps:%s:alarm:%s" % (project_id, alarm_name), 'alarm_configuration_updated_timestamp': utils.strtime(now) } metricalarm.update(update_data) # check if metric is changed alarm_key = self.cass.get_metric_alarm_key(project_id=project_id, alarm_name=alarm_name) if alarm_key: original_alarm = self.cass.get_metric_alarm(alarm_key) if (str(original_alarm['metric_key']) != str(metricalarm['metric_key'])): raise InvalidRequest("Metric cannot be changed. " "Delete alarm and retry.") else: # If alarm is newly added, check quotas # check alarm quota per project project_quota = FLAGS.get('alarm_quota_per_project') alarms_in_project = self.cass.get_alarm_count(project_id) if alarms_in_project >= project_quota: LOG.info("Too many alarms(%d) in the project %s", alarms_in_project, project_id) raise ProjectAlarmQuotaExceeded() # check alarm quota per metric metric_quota = FLAGS.get('alarm_quota_per_metric') alarms_per_metric = self.cass.get_alarms_per_metric_count( project_id, namespace, metric_name, dimensions) if alarms_per_metric >= metric_quota: LOG.info("Too many alarms(%d) for this metric", alarms_per_metric) raise MetricAlarmQuotaExceeded() message = {'project_id': project_id, 'metric_key': str(metric_key), 'metricalarm': metricalarm, 'context': context.to_dict()} self.rpc.send_msg(rpc.PUT_METRIC_ALARM_MSG_ID, message) LOG.info("PUT_METRIC_ALARM_MSG sent") return {}