Prometheus get_all support
Change-Id: I991951c150b369266fc1fa5a5811b28ab54ac7b0 Story: 2004988 Task: 29457
This commit is contained in:
parent
dd79ed9d52
commit
2b1f91d45d
@ -46,6 +46,16 @@ In ``/etc/vitrage/vitrage.conf`` add ``prometheus`` to the list of active dataso
|
||||
types = nova.host,nova.instance,nova.zone,aodh,static,cinder.volume,neutron.network,neutron.port,prometheus
|
||||
|
||||
|
||||
Add the http url of Prometheus Alertmanager api for alerts and the receiver name
|
||||
from the previous step under ``[prometheus]`` section::
|
||||
|
||||
[prometheus]
|
||||
alertmanager_url = http://localhost:9093/api/v2/alerts
|
||||
receiver = vitrage
|
||||
|
||||
|
||||
Note: Both v1 and v2 Alertmanager apis are supported
|
||||
|
||||
|
||||
Step 3 - Map Prometheus alerts to Vitrage resources
|
||||
---------------------------------------------------
|
||||
@ -53,7 +63,8 @@ Step 3 - Map Prometheus alerts to Vitrage resources
|
||||
A configuration file that maps the Prometheus alert labels to a corresponding
|
||||
Vitrage resource with specific properties (id or other unique properties).
|
||||
The mapping will most likely be defined by the alert name and other fields.
|
||||
Set the location of the alerts mapping in ``/etc/vitrage/vitrage.conf`` ::
|
||||
Set the location of the alerts mapping in ``/etc/vitrage/vitrage.conf``
|
||||
under ``[prometheus]`` section::
|
||||
|
||||
[prometheus]
|
||||
config_file = /path/to/alert/mapping
|
||||
|
@ -3,3 +3,4 @@ features:
|
||||
- Added support for a yaml configuration file that maps the Prometheus
|
||||
alert labels to a corresponding Vitrage resource with specific
|
||||
properties (id or other unique properties).
|
||||
- Added support for get_all alerts from Prometheus Alertmanager.
|
@ -15,6 +15,8 @@
|
||||
from oslo_config import cfg
|
||||
from vitrage.common.constants import DatasourceOpts as DSOpts
|
||||
from vitrage.common.constants import UpdateMethod
|
||||
from vitrage.datasources.prometheus.properties \
|
||||
import PrometheusGetAllProperties as PGAProps
|
||||
|
||||
PROMETHEUS_DATASOURCE = 'prometheus'
|
||||
|
||||
@ -38,4 +40,9 @@ OPTS = [
|
||||
required=True),
|
||||
cfg.StrOpt(DSOpts.CONFIG_FILE, default='/etc/vitrage/prometheus_conf.yaml',
|
||||
help='Prometheus configuration file'),
|
||||
cfg.StrOpt(PGAProps.ALERTMANAGER_URL,
|
||||
help='Prometheus Alertmanager http api url to get alerts'),
|
||||
cfg.StrOpt(PGAProps.RECEIVER,
|
||||
help='Receiver configured in Prometheus Alertmanager to send '
|
||||
'alerts to Vitrage'),
|
||||
]
|
||||
|
@ -11,11 +11,13 @@
|
||||
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
|
||||
# License for the specific language governing permissions and limitations
|
||||
# under the License.
|
||||
import json
|
||||
import socket
|
||||
|
||||
from collections import namedtuple
|
||||
from ipaddress import ip_address
|
||||
from oslo_log import log
|
||||
import requests
|
||||
import six
|
||||
import six.moves.urllib.parse as urlparse
|
||||
|
||||
@ -37,6 +39,8 @@ from vitrage.datasources.prometheus.properties \
|
||||
import PrometheusConfigFileProperties as PCFProps
|
||||
from vitrage.datasources.prometheus.properties \
|
||||
import PrometheusDatasourceProperties as PDProps
|
||||
from vitrage.datasources.prometheus.properties \
|
||||
import PrometheusGetAllProperties as PGAProps
|
||||
from vitrage.datasources.prometheus.properties \
|
||||
import PrometheusProperties as PProps
|
||||
from vitrage import os_clients
|
||||
@ -163,8 +167,44 @@ class PrometheusDriver(AlarmDriverBase):
|
||||
old_alarm.get(PAlertProps.STATUS)
|
||||
|
||||
def _get_all_alarms(self):
|
||||
alertmanager_url = self.conf.prometheus.alertmanager_url
|
||||
receiver = self.conf.prometheus.receiver
|
||||
if not alertmanager_url:
|
||||
LOG.warning('Alertmanager url is not defined')
|
||||
return []
|
||||
|
||||
if not receiver:
|
||||
LOG.warning('Receiver is not defined')
|
||||
return []
|
||||
|
||||
payload = {PGAProps.ACTIVE: 'true',
|
||||
PGAProps.RECEIVER: receiver}
|
||||
|
||||
session = requests.Session()
|
||||
|
||||
response = session.get(alertmanager_url,
|
||||
params=payload)
|
||||
|
||||
if response.status_code == requests.codes.ok:
|
||||
if 'v1' in alertmanager_url:
|
||||
alerts = json.loads(response.text)[PGAProps.DATA]
|
||||
else:
|
||||
alerts = json.loads(response.text)
|
||||
self._modify_alert_status(alerts)
|
||||
alarms = self._enrich_alerts(alerts, PROMETHEUS_EVENT_TYPE)
|
||||
return alarms
|
||||
else:
|
||||
LOG.error('Failed to get Alertmanager data. Response code: %s',
|
||||
response.status_code)
|
||||
return []
|
||||
|
||||
@staticmethod
|
||||
def _modify_alert_status(alerts):
|
||||
for alert in alerts:
|
||||
if alert.get(PAlertProps.STATUS).get(PGAProps.STATE) == \
|
||||
PGAProps.ACTIVE:
|
||||
alert[PAlertProps.STATUS] = PAlertStatus.FIRING
|
||||
|
||||
def _get_changed_alarms(self):
|
||||
return []
|
||||
|
||||
@ -222,27 +262,38 @@ class PrometheusDriver(AlarmDriverBase):
|
||||
alarms = []
|
||||
details = event.get(EProps.DETAILS)
|
||||
if details:
|
||||
for alert in details.get(PProps.ALERTS, []):
|
||||
alert[DSProps.EVENT_TYPE] = event_type
|
||||
vitrage_entity_unique_props = \
|
||||
self._calculate_vitrage_entity_unique_props(alert)
|
||||
|
||||
alert[PDProps.ENTITY_UNIQUE_PROPS] = \
|
||||
vitrage_entity_unique_props
|
||||
old_alarm = self._old_alarm(alert)
|
||||
alert = self._filter_and_cache_alarm(
|
||||
alert, old_alarm,
|
||||
self._filter_get_erroneous,
|
||||
get_alarm_update_time(alert))
|
||||
|
||||
if alert:
|
||||
alarms.append(alert)
|
||||
alarms = self._enrich_alerts(details.get(PProps.ALERTS, []),
|
||||
event_type)
|
||||
|
||||
LOG.debug('Enriched event. Created alert events: %s', str(alarms))
|
||||
|
||||
return self.make_pickleable(alarms, PROMETHEUS_DATASOURCE,
|
||||
DatasourceAction.UPDATE)
|
||||
|
||||
def _enrich_alerts(self, alerts, event_type):
|
||||
return [self._enrich_alert(alert, event_type) for alert in alerts]
|
||||
|
||||
def _enrich_alert(self, alert, event_type):
|
||||
"""Enrich prometheus alert.
|
||||
|
||||
Adding fields to prometheus alert in order to map it to vitrage entity.
|
||||
|
||||
:param alert: Prometheus alert
|
||||
:param event_type: The type of the event. Always 'prometheus.alert'.
|
||||
:return: Enriched prometheus alert
|
||||
"""
|
||||
alert[DSProps.EVENT_TYPE] = event_type
|
||||
vitrage_entity_unique_props = \
|
||||
self._calculate_vitrage_entity_unique_props(alert)
|
||||
alert[PDProps.ENTITY_UNIQUE_PROPS] = \
|
||||
vitrage_entity_unique_props
|
||||
old_alarm = self._old_alarm(alert)
|
||||
alert = self._filter_and_cache_alarm(
|
||||
alert, old_alarm,
|
||||
self._filter_get_erroneous,
|
||||
get_alarm_update_time(alert))
|
||||
return alert
|
||||
|
||||
def _calculate_vitrage_entity_unique_props(self, alert):
|
||||
"""Build a vitrage entity unique props.
|
||||
|
||||
|
@ -47,6 +47,14 @@ class PrometheusDatasourceProperties(object):
|
||||
ENTITY_UNIQUE_PROPS = 'vitrage_entity_unique_props'
|
||||
|
||||
|
||||
class PrometheusGetAllProperties(object):
|
||||
ALERTMANAGER_URL = 'alertmanager_url'
|
||||
RECEIVER = 'receiver'
|
||||
STATE = 'state'
|
||||
ACTIVE = 'active'
|
||||
DATA = 'data'
|
||||
|
||||
|
||||
def get_alarm_update_time(alarm):
|
||||
if PrometheusAlertStatus.FIRING == \
|
||||
alarm.get(PrometheusAlertProperties.STATUS):
|
||||
|
@ -42,16 +42,17 @@ class PrometheusTransformer(AlarmTransformerBase):
|
||||
super(PrometheusTransformer, self).__init__(transformers, conf)
|
||||
|
||||
def _create_snapshot_entity_vertex(self, entity_event):
|
||||
# TODO(iafek): should be implemented
|
||||
return None
|
||||
return self._create_vertex(entity_event)
|
||||
|
||||
def _create_update_entity_vertex(self, entity_event):
|
||||
return self._create_vertex(entity_event)
|
||||
|
||||
def _create_vertex(self, entity_event):
|
||||
metadata = {
|
||||
VProps.NAME: get_label(entity_event, PAlertLabels.ALERT_NAME),
|
||||
VProps.SEVERITY: get_label(entity_event, PAlertLabels.SEVERITY),
|
||||
PProps.STATUS: entity_event.get(PProps.STATUS),
|
||||
}
|
||||
|
||||
return graph_utils.create_vertex(
|
||||
self._create_entity_key(entity_event),
|
||||
vitrage_category=ECategory.ALARM,
|
||||
@ -62,7 +63,13 @@ class PrometheusTransformer(AlarmTransformerBase):
|
||||
metadata=metadata
|
||||
)
|
||||
|
||||
def _create_snapshot_neighbors(self, entity_event):
|
||||
return self._create_prometheus_neighbors(entity_event)
|
||||
|
||||
def _create_update_neighbors(self, entity_event):
|
||||
return self._create_prometheus_neighbors(entity_event)
|
||||
|
||||
def _create_prometheus_neighbors(self, entity_event):
|
||||
graph_neighbors = entity_event.get(self.QUERY_RESULT, [])
|
||||
return [self._create_neighbor(entity_event,
|
||||
graph_neighbor[VProps.ID],
|
||||
|
@ -201,13 +201,6 @@ class PrometheusDriverTest(base.BaseTest):
|
||||
# Test assertions
|
||||
self._assert_event_equal(created_events, PROMETHEUS_EVENT_TYPE)
|
||||
|
||||
@staticmethod
|
||||
def _generate_event(update_vals=None):
|
||||
generators = mock_driver.simple_prometheus_alarm_generators(
|
||||
update_vals=update_vals)
|
||||
|
||||
return mock_driver.generate_sequential_events_list(generators)[0]
|
||||
|
||||
def _assert_event_equal(self,
|
||||
created_events,
|
||||
expected_event_type):
|
||||
@ -223,3 +216,10 @@ class PrometheusDriverTest(base.BaseTest):
|
||||
event = self._generate_event()
|
||||
details = event[EProps.DETAILS]
|
||||
return details[PProps.ALERTS]
|
||||
|
||||
@staticmethod
|
||||
def _generate_event(update_vals=None):
|
||||
generators = mock_driver.simple_prometheus_alarm_generators(
|
||||
update_vals=update_vals)
|
||||
|
||||
return mock_driver.generate_sequential_events_list(generators)[0]
|
||||
|
Loading…
Reference in New Issue
Block a user