From 66ad59ab4484083a4a05e30829960a74d521233f Mon Sep 17 00:00:00 2001 From: Nikolay Stanchev <ns17@it-innovation.soton.ac.uk> Date: Thu, 4 Oct 2018 11:45:32 +0100 Subject: [PATCH] Updates tick script templates and alerts API to include sfc,sfci,policy in JSON body --- .../alertsapi/alerts_specification_schema.py | 2 +- .../clmcservice/alertsapi/utilities.py | 56 +++++++++++++++++-- src/service/clmcservice/alertsapi/views.py | 6 +- .../TICKscript/deadman-template.tick | 2 +- .../TICKscript/relative-stream-template.tick | 46 --------------- .../TICKscript/relative-template.tick | 2 +- .../TICKscript/threshold-batch-template.tick | 2 +- .../TICKscript/threshold-stream-template.tick | 2 +- src/test/clmctest/alerts/test_alerts.py | 6 +- 9 files changed, 65 insertions(+), 59 deletions(-) delete mode 100644 src/service/resources/TICKscript/relative-stream-template.tick diff --git a/src/service/clmcservice/alertsapi/alerts_specification_schema.py b/src/service/clmcservice/alertsapi/alerts_specification_schema.py index bc3a985..8eaa2d7 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 eba22f2..55470c1 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 ba07e26..5c586e3 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 1b03fdb..730a461 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 0a90f3d..0000000 --- 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 9fb0daa..669954b 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 f33f850..f5f7a64 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 fb85aba..9eb8865 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 ceb844e..a8679b3 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({ -- GitLab