Not able to sent dynamic values as alertmanager_fields from custom ruletype
vicvinodvic opened this issue · 1 comments
I have created a custom rule which alerts when particular category ids' API status has more than 90% failure.
Below is the code,
I want to send categoryid as alertmanager_fields , but its going null, please help me in fixing the issue
Rule configuration
alert:
- "debug"
- "alertmanager"
alertmanager_alertname: "Test Custom rule"
alertmanager_annotations:
description: "Test Custom rule"
summary: "Test Custom rule"
alertmanager_hosts: - "https://"
alertmanager_fields:
categoryid: "{{ match[categoryid] }}"
I have tried below combination
categoryid: "{{ match.categoryid }}"
categoryid: "match.categoryid"
categoryid: "match[categoryid]"
Custom Rule code
from elastalert.ruletypes import RuleType
from datetime import datetime, timedelta
from jinja2 import Template
template_string = """
For Category {{ match['categoryid'] }}, more than {{ match['threshold'] }}% Rreq Failures
Total Txns : {{ match['total_transactions'] }}
Failed Txns : {{ match['failed_transactions'] }}
"""
class RreqRule(RuleType):
def __init__(self, rule_config, *args, **kwargs):
super(RreqRule, self).__init__(rule_config, *args, **kwargs)
self.alerted_category = []
self.rule_template = Template(template_string)
self.start_time = datetime.utcnow() - timedelta(minutes=10)
self.end_time = datetime.utcnow()
# Get the failure rate threshold from the rule configuration file
self.threshold = float(self.rules['threshold'])
# add_data will be called each time Elasticsearch is queried.
# data is a list of documents from Elasticsearch, sorted by timestamp,
# including all the fields that the config specifies with "include"
def add_data(self, data):
# Extract the categoryid and transaction result from the data
for document in data:
categoryid = document['categoryid']
api_status = document['business_context']['apistatus']
self.rules.setdefault(categoryid, {'total_transactions': 0, 'failed_transactions': 0 })
self.rules[categoryid]['total_transactions'] += 1
if api_status != 'Y':
self.rules[categoryid]['failed_transactions'] += 1
# Calculate the failure rate for this categoryid
total_transactions = self.rules[categoryid]['total_transactions']
failed_transactions = self.rules[categoryid]['failed_transactions']
failure_rate = float(failed_transactions) / float(total_transactions)
# If the failure rate exceeds the threshold, trigger an alert
if failure_rate >= self.threshold:
if categoryid not in self.alerted_category:
self.alerted_category.append(categoryid)
self.add_match({
'categoryid': categoryid,
'threshold': self.threshold,
'total_transactions': total_transactions,
'failed_transactions': failed_transactions
})
else:
print("------------Ignoring alert for categoryid : ", categoryid)
def get_match_str(self, match):
# Format the match string with the failure rate
alert_body = self.rule_template.render(match=match)
[match.pop(k) for k in list(match.keys()) if k != 'categoryid']
self.rules['alertmanager_fields'] = {
'categoryid': match['categoryid']
}
return alert_body
# garbage_collect is called indicating that ElastAlert 2 has already been run up to timestamp
# It is useful for knowing that there were no query results from Elasticsearch because
# add_data will not be called with an empty list
def garbage_collect(self, timestamp):
for categoryid in self.alerted_category:
self.alerted_category.remove(categoryid)
self.rules[categoryid] = {'total_transactions': 0, 'failed_transactions': 0}
Using below Code resolved the Issue
from elastalert.enhancements import BaseEnhancement
class PsdEnhancement(BaseEnhancement):
# The enhancement is run against every match
# The match is passed to the process function where it can be modified in any way
# ElastAlert 2 will do this for each enhancement linked to a rule
def process(self, match):
self.rule['alertmanager_labels']['categoryid'] = match['categoryid']