Éric Lemoine | 6a1abe9 | 2016-11-03 14:02:43 +0000 | [diff] [blame] | 1 | # -*- coding: utf-8 -*- |
| 2 | |
| 3 | import 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 | |
| 10 | def message_matcher(alarm, triggers): |
| 11 | """ |
| 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 | |
| 29 | def dimensions(alarm): |
| 30 | """ |
| 31 | Return a dict alarm dimensions. Each dimension is validated, and an |
| 32 | Exception is raised if a dimension is invalid. |
| 33 | |
| 34 | Valid characters are a-z, 0-9, _, - and /. |
| 35 | """ |
| 36 | dimensions = alarm.get('dimension', {}) |
| 37 | for name, value in dimensions.items(): |
| 38 | if name in _disallowed_dimensions: |
| 39 | raise Exception( |
| 40 | '{} is not allowed as a dimension name'.format(name)) |
| 41 | if not _valid_dimension_re.match(name): |
| 42 | raise Exception( |
| 43 | 'Dimension name {} includes disallowed chars'.format(name)) |
| 44 | if not _valid_dimension_re.match(value): |
| 45 | raise Exception( |
| 46 | 'Dimension value {} includes disallowed chars'.format(value)) |
| 47 | return dimensions |