diff --git a/src/service/clmcservice/alertsapi/alerts_specification_schema.py b/src/service/clmcservice/alertsapi/alerts_specification_schema.py index bc3a985e7130ab713df9789d9d6ac8d57e045e43..8eaa2d78cdae65a22b1796d2ba44d7e2c2e2d5a5 100644 --- a/src/service/clmcservice/alertsapi/alerts_specification_schema.py +++ b/src/service/clmcservice/alertsapi/alerts_specification_schema.py @@ -78,7 +78,7 @@ ALERTS_SPECIFICATION_SCHEMA = Schema({ "policies": [ { str: { - "type": Or("eu.ict-flame.policies.StateChange", "eu.ict-flame.policies.Alert"), + "type": "eu.ict-flame.policies.StateChange", "triggers": And({ str: { Optional("description"): str, diff --git a/src/service/clmcservice/alertsapi/utilities.py b/src/service/clmcservice/alertsapi/utilities.py index eba22f2c3e631b8548ed4d3c79dcff591d302187..55470c1251509fda261d5c0f7238ded3cdf224f0 100644 --- a/src/service/clmcservice/alertsapi/utilities.py +++ b/src/service/clmcservice/alertsapi/utilities.py @@ -152,7 +152,7 @@ class TICKScriptTemplateFiller: return fill_function(**kwargs) @staticmethod - def _fill_threshold_batch_template_vars(db=None, measurement=None, field=None, influx_function=None, critical_value=None, + def _fill_threshold_batch_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, influx_function=None, critical_value=None, comparison_operator=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): """ Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template. @@ -174,6 +174,18 @@ class TICKScriptTemplateFiller: comparison_lambda = '"real_value" {0} {1}'.format(comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10 template_vars = { + "sfc": { + "type": "string", + "value": sfc + }, + "sfci": { + "type": "string", + "value": sfci + }, + "policy": { + "type": "string", + "value": policy + }, "db": { "type": "string", "value": db @@ -217,7 +229,7 @@ class TICKScriptTemplateFiller: return template_vars @staticmethod - def _fill_threshold_stream_template_vars(db=None, measurement=None, field=None, critical_value=None, + def _fill_threshold_stream_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, critical_value=None, comparison_operator=None, topic_id=None, event_id=None, where_clause=None, **kwargs): """ Creates a dictionary object ready to be posted to kapacitor to create a "threshold" task from template. @@ -239,6 +251,18 @@ class TICKScriptTemplateFiller: comparison_lambda = '"{0}" {1} {2}'.format(field, comparison_operator, critical_value) # build up lambda string, e.g. "real_value" >= 10 template_vars = { + "sfc": { + "type": "string", + "value": sfc + }, + "sfci": { + "type": "string", + "value": sfci + }, + "policy": { + "type": "string", + "value": policy + }, "db": { "type": "string", "value": db @@ -271,7 +295,7 @@ class TICKScriptTemplateFiller: return template_vars @staticmethod - def _fill_relative_template_vars(db=None, measurement=None, field=None, influx_function=None, critical_value=None, comparison_operator=None, + def _fill_relative_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, field=None, influx_function=None, critical_value=None, comparison_operator=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): """ Creates a dictionary object ready to be posted to kapacitor to create a "relative" task from template. @@ -293,6 +317,18 @@ class TICKScriptTemplateFiller: comparison_lambda = '"diff" {0} {1}'.format(comparison_operator, critical_value) template_vars = { + "sfc": { + "type": "string", + "value": sfc + }, + "sfci": { + "type": "string", + "value": sfci + }, + "policy": { + "type": "string", + "value": policy + }, "db": { "type": "string", "value": db @@ -336,7 +372,7 @@ class TICKScriptTemplateFiller: return template_vars @staticmethod - def _fill_deadman_template_vars(db=None, measurement=None, critical_value=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): + def _fill_deadman_template_vars(sfc=None, sfci=None, policy=None, db=None, measurement=None, critical_value=None, alert_period=None, topic_id=None, event_id=None, where_clause=None, **kwargs): """ Creates a dictionary object ready to be posted to kapacitor to create a "deadman" task from template. @@ -352,6 +388,18 @@ class TICKScriptTemplateFiller: """ template_vars = { + "sfc": { + "type": "string", + "value": sfc + }, + "sfci": { + "type": "string", + "value": sfci + }, + "policy": { + "type": "string", + "value": policy + }, "db": { "type": "string", "value": db diff --git a/src/service/clmcservice/alertsapi/views.py b/src/service/clmcservice/alertsapi/views.py index ba07e26911289976f0faa5bb655339350c300bbc..5c586e34375cdf4d4429eca755552535eda661ab 100644 --- a/src/service/clmcservice/alertsapi/views.py +++ b/src/service/clmcservice/alertsapi/views.py @@ -251,9 +251,9 @@ class AlertsConfigurationAPI(object): # built up the template vars dictionary depending on the event type (threshold, relative, etc.) # all extracted properties from the trigger are passed, the TICKScriptTemplateFiller entry point then forwards those to the appropriate function for template filling - template_vars = TICKScriptTemplateFiller.fill_template_vars(event_type, db=db, measurement=measurement, field=field, influx_function=influx_function, - critical_value=critical_value, comparison_operator=comparison_operator, alert_period=alert_period, - topic_id=topic_id, event_id=event_id, where_clause=where_clause) + template_vars = TICKScriptTemplateFiller.fill_template_vars(event_type, sfc=sfc, sfci=sfc_instance, policy=policy_id, db=db, measurement=measurement, + field=field, influx_function=influx_function, critical_value=critical_value, comparison_operator=comparison_operator, + alert_period=alert_period, topic_id=topic_id, event_id=event_id, where_clause=where_clause) # create and activate alert task through the kapacitor HTTP API kapacitor_api_tasks_url = "http://{0}:{1}/kapacitor/v1/tasks".format(kapacitor_host, kapacitor_port) diff --git a/src/service/resources/TICKscript/deadman-template.tick b/src/service/resources/TICKscript/deadman-template.tick index 1b03fdb08b0ec1b8cb6b4dc9cf68c347bca6a16b..730a4610b0d8bdf97164db121ed67fa7a3e2c95e 100644 --- a/src/service/resources/TICKscript/deadman-template.tick +++ b/src/service/resources/TICKscript/deadman-template.tick @@ -31,7 +31,7 @@ stream .where(whereClause) | deadman(throughputThreshold, alertPeriod) .id(eventID) - .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy + ',trigger=' + eventID) + .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy) .message(messageValue) .topic(topicID) .noRecoveries() \ No newline at end of file diff --git a/src/service/resources/TICKscript/relative-stream-template.tick b/src/service/resources/TICKscript/relative-stream-template.tick deleted file mode 100644 index 0a90f3d5dff8e7ecb327d22a6b07e7d26d9b5a57..0000000000000000000000000000000000000000 --- a/src/service/resources/TICKscript/relative-stream-template.tick +++ /dev/null @@ -1,46 +0,0 @@ -var db string // database per service function chain, so db is named after sfc - -var rp = 'autogen' // default value for the retention policy - -var measurement string - -var selectLambda lambda // must be a lambda specifying the field to select e.g. "requests" - -var whereClause = lambda: True // default value is a function which returns TRUE, hence no filtering of the query result - -var messageValue = 'TRUE' // default value is TRUE, as this is what SFEMC expects as a notification for an event rule - -var comparisonLambda lambda // comparison function e.g. "diff" > 40 - -var alertPeriod duration - -var topicID string - - -var data = stream - | from() - .database(db) - .retentionPolicy(rp) - .measurement(measurement) - .where(whereClause) - | eval(selectLambda) - .as('value') - -var past = data - | shift(alertPeriod) - -var current = data - -past - | join(current) // NOTE: join buffers a given data point until a point with the correct timestamp to join on arrives - .as('past', 'current') - | eval(lambda: float("current.value" - "past.value")) - .keep() - .as('diff') - | alert() - .id(topicID) - .details('db=' + db + ',measurement=' + measurement) - .crit(comparisonLambda) - .message(messageValue) - .topic(topicID) - .noRecoveries() diff --git a/src/service/resources/TICKscript/relative-template.tick b/src/service/resources/TICKscript/relative-template.tick index 9fb0daabbc297cea78838051f49ca716a057f7ea..669954bfd91b8ee6aad243a1fba01e9a54ab4bb9 100644 --- a/src/service/resources/TICKscript/relative-template.tick +++ b/src/service/resources/TICKscript/relative-template.tick @@ -48,7 +48,7 @@ past .as('diff') | alert() .id(eventID) - .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy + ',trigger=' + eventID) + .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy) .crit(comparisonLambda) .message(messageValue) .topic(topicID) diff --git a/src/service/resources/TICKscript/threshold-batch-template.tick b/src/service/resources/TICKscript/threshold-batch-template.tick index f33f850a4155ff007d41b91342fef3ac55f9925f..f5f7a64b91006de1420b2a65232bc2ba55d8e44c 100644 --- a/src/service/resources/TICKscript/threshold-batch-template.tick +++ b/src/service/resources/TICKscript/threshold-batch-template.tick @@ -32,7 +32,7 @@ batch .every(alertPeriod) |alert() .id(eventID) - .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy + ',trigger=' + eventID) + .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy) .crit(comparisonLambda) .message(messageValue) .topic(topicID) diff --git a/src/service/resources/TICKscript/threshold-stream-template.tick b/src/service/resources/TICKscript/threshold-stream-template.tick index fb85abac7048f1558446b7035889aa64c249a4b0..9eb886589943d4da76a1ea8699f1efe7afb365a6 100644 --- a/src/service/resources/TICKscript/threshold-stream-template.tick +++ b/src/service/resources/TICKscript/threshold-stream-template.tick @@ -29,7 +29,7 @@ stream .where(whereClause) | alert() .id(eventID) - .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy + ',trigger=' + eventID) + .details('db=' + db + ',sfc=' + sfc + ',sfci=' + sfci + ',policy=' + policy) .crit(comparisonLambda) .message(messageValue) .topic(topicID) diff --git a/src/test/clmctest/alerts/test_alerts.py b/src/test/clmctest/alerts/test_alerts.py index ceb844efdc55ee4ef0040207189cfa0cedac43ee..a8679b37fcbeb9aa51fda7c7af2e6671b1bb6605 100644 --- a/src/test/clmctest/alerts/test_alerts.py +++ b/src/test/clmctest/alerts/test_alerts.py @@ -44,7 +44,11 @@ def is_valid_timestamp(str_timestamp): def is_valid_details_string(details): - return "db=" in details and "sfc=" in details and "sfci=" in details and "policy" in details + try: + details_dict = {key.strip(): value.strip() for key,value in [item.split("=") for item in details.split(",")]} + return len(details_dict) == 4 and "db" in details_dict and "sfc" in details_dict and "sfci" in details_dict and "policy" in details_dict + except Exception: + return False JSON_BODY_SCHEMA = Schema({