def test_macro(self, mock_signals): self.project = models.Project.objects.create(name='Project 1', service=self.service) clause = 'up{%s}' % macro.EXCLUSION_MACRO rules = { 'common': { 'assert': 'up{service!~"Service 1"}' }, 'service': { 'assert': 'up{service="Service 1",project!~"Project 1"}' }, 'project': { 'assert': 'up{service="Service 1",project="Project 1",}' }, } common_rule = models.Rule.create(name='Common', clause=clause, duration='1s', obj=self.service.default()) rules['common']['model'] = models.Rule.objects.get(pk=common_rule.pk) service_rule = common_rule.copy_to('service', self.service.id) rules['service']['model'] = models.Rule.objects.get(pk=service_rule.pk) project_rule = service_rule.copy_to('project', self.project.id) rules['project']['model'] = models.Rule.objects.get(pk=project_rule.pk) for k, r in rules.items(): self.assertEquals(macro.rulemacro(r['model'].clause, r['model']), r['assert'], 'Expansion wrong for %s' % k)
def to_representation(self, obj): return { "alert": obj.name, "expr": macro.rulemacro(obj), "for": obj.duration, "labels": obj.labels, "annotations": obj.annotations, }
def post(self, request, pk): if pk == 0: rule = models.Rule() rule.set_object(request.POST['content_type'], request.POST['object_id']) else: rule = get_object_or_404(models.Rule, id=pk) query = macro.rulemacro(rule, request.POST['query']) # Since our rules affect all servers we use Promgen's proxy-query to test our rule # against all the servers at once url = resolve_domain('proxy-query') logger.debug('Querying %s with %s', url, query) start = time.time() result = util.get(url, {'query': query}).json() duration = datetime.timedelta(seconds=(time.time() - start)) context = { 'status': result['status'], 'duration': duration, 'query': query } context['data'] = result.get('data', {}) context['errors'] = {} metrics = context['data'].get('result', []) if metrics: context['collapse'] = len(metrics) > 5 for row in metrics: if 'service' not in row['metric'] and \ 'project' not in row['metric']: context['errors'][ 'routing'] = 'Some metrics are missing service and project labels so Promgen will be unable to route message' context['status'] = 'warning' else: context['status'] = 'info' context['errors'][ 'no_results'] = 'No Results. May need to remove conditional check (> < ==) to verity' # Place this at the bottom to have a query error show up as danger if result['status'] != 'success': context['status'] = 'danger' context['errors']['Query'] = result['error'] return JsonResponse({ request.POST['target']: render_to_string('promgen/ajax_clause_check.html', context) })
def render_rules(rules=None, version=None): ''' Render rules in a format that Prometheus understands :param rules: List of rules :type rules: list(Rule) :param int version: Prometheus rule format (1 or 2) :return: Returns rules in yaml or Prometheus v1 format :rtype: bytes This function can render in either v1 or v2 format We call prefetch_related_objects within this function to populate the other related objects that are mostly used for the sub lookups. ''' if rules is None: rules = models.Rule.objects.filter(enabled=True) if version is None: version = settings.PROMGEN['prometheus'].get('version', 1) prefetch_related_objects( rules, 'content_object', 'content_type', 'overrides__content_object', 'overrides__content_type', 'ruleannotation_set', 'rulelabel_set', ) # V1 format is a custom format which we render through django templates # See promgen/tests/examples/import.rule if version == 1: return render_to_string('promgen/prometheus.rule', {'rules': rules}).encode('utf-8') # V2 format is a yaml dictionary which we build and then render # See promgen/tests/examples/import.rule.yml rule_list = collections.defaultdict(list) for r in rules: rule_list[str(r.content_object)].append({ 'alert': r.name, 'expr': macro.rulemacro(r.clause, r), 'for': r.duration, 'labels': r.labels, 'annotations': r.annotations, }) return yaml.safe_dump({'groups': [ {'name': name, 'rules': rule_list[name]} for name in rule_list ]}, default_flow_style=False, allow_unicode=True, encoding='utf-8')