# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
)
return modified_count
+ def update_alarm_extra_labels(self, alarm_labels: dict, uuid):
+ modified_count = self.common_db.set_one(
+ "alarms", {"uuid": uuid}, {"extra_labels": alarm_labels}
+ )
+ return modified_count
+
def get_alarm_by_uuid(self, uuid: str):
return self.common_db.get_one("alarms", {"uuid": uuid})
action: str = None,
tags: dict = {},
alarm_status: str = "ok",
+ extra_labels: dict = {},
):
self.uuid = str(uuid.uuid4())
self.name = name
self.action = action
self.tags = tags
self.alarm_status = alarm_status
+ self.extra_labels = extra_labels
def to_dict(self) -> dict:
alarm = {
"tags": self.tags,
"operation": self.operation,
"alarm_status": self.alarm_status,
+ "extra_labels": self.extra_labels,
}
return alarm
alarm.tags = data.get("tags")
alarm.operation = data.get("operation")
alarm.alarm_status = data.get("alarm_status")
+ alarm.extra_labels = data.get("extra_labels")
return alarm
"status": kwargs["status"],
"start_date": kwargs["date"],
"tags": kwargs["tags"],
+ "extra_labels": kwargs["extra_labels"],
},
}
return notify_alarm_resp
+# -*- coding: utf-8 -*-
+
# Copyright 2018 Whitestack, LLC
# *************************************************************
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
-
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
def __init__(self, config: Config):
pass
- def get_metric_value(self, metric_name: str, tags: dict):
+ def get_metric_data(self, metric_name: str, tags: dict):
pass
##
import base64
import logging
-from typing import Dict
+from typing import Dict, List
import requests
OSM_METRIC_PREFIX = "osm_"
+DEFAULT_QUERY_METRICS = ["ns_id", "vnf_member_index", "vdu_name"]
+
class PrometheusBackend(BaseBackend):
def __init__(self, config: Config):
super().__init__(config)
self.conf = config
- def get_metric_value(self, metric_name: str, tags: dict):
+ def get_metric_data(self, metric_name: str, tags: dict):
query = self._build_query(metric_name, tags)
request_url = self._build_url(query)
request_headers = self._build_headers()
if r.status_code == 200:
json_response = r.json()
if json_response["status"] == "success":
- return self._get_metric_value_from_response(json_response)
+ return self._get_metric_data_from_response(json_response)
else:
log.warning(
"Prometheus response is not success. Got status %s",
headers["Authorization"] = f"Basic {token}"
return headers
- def _get_metric_value_from_response(self, json_response):
+ def _get_metric_data_from_response(self, json_response) -> List[Dict[str, str]]:
result = json_response["data"]["result"]
+ metrics_data = []
if len(result):
- metric_value = float(result[0]["value"][1])
- log.info("Metric value: %s", metric_value)
- return metric_value
+ for metric in result:
+ metrics_labels = metric["metric"]
+ metric_value = float(metric["value"][1])
+ log.info("Metric value: %s", metric_value)
+ metrics_data.append({"labels": metrics_labels, "value": metric_value})
+ return metrics_data
else:
return None
-# -*- coding: utf-8 -*-
-
# Copyright 2018 Whitestack, LLC
# *************************************************************
)
evaluator_service = EvaluatorService(self.conf)
evaluator_service.update_alarm_status(status.value, alarm.uuid)
+ evaluator_service.update_alarm_extra_labels(alarm.extra_labels, alarm.uuid)
return
def _build_alarm_response(self, alarm: Alarm, status: AlarmStatus):
status=status.value,
date=now,
tags=tags,
+ extra_tabels=alarm.extra_labels,
)
self.common_db = CommonDbClient(self.conf)
self.queue = multiprocessing.Queue()
- def _get_metric_value(self, metric_name: str, tags: dict):
+ def _get_metric_data(self, metric_name: str, tags: dict):
return BACKENDS[self.conf.get("evaluator", "backend")](
self.conf
- ).get_metric_value(metric_name, tags)
+ ).get_metric_data(metric_name, tags)
def _evaluate_metric(self, alarm: Alarm):
"""Method to evaluate a metric value comparing it against an alarm threshold.
"""
log.debug("_evaluate_metric")
- metric_value = self._get_metric_value(alarm.metric, alarm.tags)
- if alarm.alarm_status.upper() != AlarmStatus.DISABLED.value.upper():
- if metric_value is None:
- log.warning("No metric result for alarm %s", alarm.uuid)
- self.queue.put((alarm, AlarmStatus.INSUFFICIENT))
- else:
- if (
- (alarm.operation.upper() == "GT" and metric_value > alarm.threshold)
- or (
- alarm.operation.upper() == "LT"
- and metric_value < alarm.threshold
- )
- or (
- alarm.operation.upper() == "GE"
- and metric_value >= alarm.threshold
- )
- or (
- alarm.operation.upper() == "LE"
- and metric_value <= alarm.threshold
- )
- or (
- alarm.operation.upper() == "EQ"
- and metric_value == alarm.threshold
- )
- or (
- alarm.operation.upper() == "NE"
- and metric_value != alarm.threshold
- )
- ):
- self.queue.put((alarm, AlarmStatus.ALARM))
- elif alarm.operation.upper() in ("GT", "LT", "GE", "LE", "EQ", "NE"):
- self.queue.put((alarm, AlarmStatus.OK))
+ metric_data = self._get_metric_data(alarm.metric, alarm.tags)
+ if metric_data is None:
+ log.warning("No metric result for alarm %s", alarm.uuid)
+ self.queue.put((alarm, AlarmStatus.INSUFFICIENT))
+ else:
+ for metric in metric_data:
+ metric_value = metric["value"]
+ metric_labels = metric["labels"]
+ alarm.extra_labels.update(metric_labels)
+ if alarm.alarm_status.upper() != AlarmStatus.DISABLED.value.upper():
+ if (
+ (
+ alarm.operation.upper() == "GT"
+ and metric_value > alarm.threshold
+ )
+ or (
+ alarm.operation.upper() == "LT"
+ and metric_value < alarm.threshold
+ )
+ or (
+ alarm.operation.upper() == "GE"
+ and metric_value >= alarm.threshold
+ )
+ or (
+ alarm.operation.upper() == "LE"
+ and metric_value <= alarm.threshold
+ )
+ or (
+ alarm.operation.upper() == "EQ"
+ and metric_value == alarm.threshold
+ )
+ or (
+ alarm.operation.upper() == "NE"
+ and metric_value != alarm.threshold
+ )
+ ):
+ self.queue.put((alarm, AlarmStatus.ALARM))
+ elif alarm.operation.upper() in (
+ "GT",
+ "LT",
+ "GE",
+ "LE",
+ "EQ",
+ "NE",
+ ):
+ self.queue.put((alarm, AlarmStatus.OK))
def update_alarm_status(self, alarm_state, uuid):
alarm_data = self.common_db.get_alarm_by_uuid(uuid)
self.common_db.update_alarm_status(alarm_state, uuid)
return
+ def update_alarm_extra_labels(self, alarm_labels, uuid):
+ self.common_db.update_alarm_extra_labels(alarm_labels, uuid)
+ return
+
def evaluate_alarms(self) -> List[Tuple[Alarm, AlarmStatus]]:
log.debug("evaluate_alarms")
processes = []
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
+
import unittest
from unittest import mock
"operation": "operation",
"uuid": "1",
"alarm_status": "ok",
+ "extra_labels": {},
},
)
# For those usages not covered by the Apache License, Version 2.0 please
# contact: bdiaz@whitestack.com or glavado@whitestack.com
##
+
from unittest import TestCase, mock
from osm_mon.core.common_db import CommonDbClient
super().setUp()
self.config = Config()
- @mock.patch.object(EvaluatorService, "_get_metric_value")
- def test_evaluate_metric(self, get_metric_value):
+ @mock.patch.object(EvaluatorService, "_get_metric_data")
+ def test_evaluate_metric(self, get_metric_data):
mock_alarm = mock.Mock()
mock_alarm.operation = "gt"
mock_alarm.threshold = 50.0
mock_alarm.metric = "metric_name"
- get_metric_value.return_value = 100.0
+ get_metric_data.return_value = [
+ {
+ "labels": {
+ "vdu_name": "cirros_vnfd-VM",
+ "ns_id": "87776f33-b67c-417a-8119-cb08e4098951",
+ "vnf_member_index": "1",
+ "extra_label": "run_time_added_label",
+ },
+ "value": 100.0,
+ }
+ ]
service = EvaluatorService(self.config)
service.queue = mock.Mock()
service.queue.put.assert_called_with((mock_alarm, AlarmStatus.OK))
service.queue.reset_mock()
- get_metric_value.return_value = None
+ get_metric_data.return_value = None
service._evaluate_metric(mock_alarm)
service.queue.put.assert_called_with((mock_alarm, AlarmStatus.INSUFFICIENT))
process.assert_called_with(target=evaluate_metric, args=(mock_alarm,))
- @mock.patch.object(PrometheusBackend, "get_metric_value")
- def test_get_metric_value_prometheus(self, get_metric_value):
+ @mock.patch.object(PrometheusBackend, "get_metric_data")
+ def test_get_metric_data_prometheus(self, get_metric_data):
self.config.set("evaluator", "backend", "prometheus")
evaluator = EvaluatorService(self.config)
- evaluator._get_metric_value("test", {})
+ evaluator._get_metric_data("test", {})
- get_metric_value.assert_called_with("test", {})
+ get_metric_data.assert_called_with("test", {})