blob: d87ed735db343029d0ed23304849405f3ce4ab6e [file] [log] [blame]
Éric Lemoine6a1abe92016-11-03 14:02:43 +00001# -*- coding: utf-8 -*-
2
3import re
4
5_valid_dimension_re = re.compile(r'^[a-z0-9_/-]+$')
6_disallowed_dimensions = ('name', 'value', 'hostname', 'member',
7 'no_alerting', 'tag_fields')
8
9
Éric Lemoine7dc12132016-11-07 16:25:09 +000010def alarm_message_matcher(alarm, triggers):
Éric Lemoine6a1abe92016-11-03 14:02:43 +000011 """
12 Return an Heka message matcher expression for a given alarm and a
13 dict of triggers.
14
15 For example the function may return this:
16
17 Fields[name] == 'cpu_idle' || Fields[name] = 'cpu_wait'
18 """
19 matchers = set()
20 for trigger_name in alarm.get('triggers', []):
21 trigger = triggers.get(trigger_name)
22 if trigger and trigger.get('enabled', True):
23 for rule in trigger.get('rules', []):
24 matcher = "Fields[name] == '{}'".format(rule['metric'])
25 matchers.add(matcher)
26 return ' || '.join(matchers)
27
28
Éric Lemoine7dc12132016-11-07 16:25:09 +000029def alarm_cluster_message_matcher(alarm_cluster):
30 """
31 Return an Heka message matcher expression for a given alarm cluster.
32
33 For example the function may return this:
34
35 Fields[service] == 'rabbitmq-cluster'
36 """
37 matchers = set()
38 match_items = alarm_cluster.get('match', {}).items()
39 for match_name, match_value in match_items:
40 matcher = "Fields[{}] == '{}'".format(match_name, match_value)
41 matchers.add(matcher)
42 match_items = alarm_cluster.get('match_re', {}).items()
43 for match_name, match_value in match_items:
44 matcher = "Fields[{}] =~ /{}/".format(match_name, match_value)
45 matchers.add(matcher)
46 return ' && '.join(matchers)
47
48
Éric Lemoinefc2ae372016-11-08 13:55:03 +000049def dimensions(alarm_or_alarm_cluster):
Éric Lemoine6a1abe92016-11-03 14:02:43 +000050 """
51 Return a dict alarm dimensions. Each dimension is validated, and an
52 Exception is raised if a dimension is invalid.
53
54 Valid characters are a-z, 0-9, _, - and /.
55 """
Éric Lemoinefc2ae372016-11-08 13:55:03 +000056 dimensions = alarm_or_alarm_cluster.get('dimension', {})
Éric Lemoine6a1abe92016-11-03 14:02:43 +000057 for name, value in dimensions.items():
58 if name in _disallowed_dimensions:
59 raise Exception(
60 '{} is not allowed as a dimension name'.format(name))
61 if not _valid_dimension_re.match(name):
62 raise Exception(
63 'Dimension name {} includes disallowed chars'.format(name))
64 if not _valid_dimension_re.match(value):
65 raise Exception(
66 'Dimension value {} includes disallowed chars'.format(value))
67 return dimensions