From 1a0ac20b08425fafc92f9f10bb57e5c59caf0aac Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Fri, 23 Sep 2022 15:40:13 +0530 Subject: [PATCH 01/10] feat(alerts): add yhat to point models and update change percent calc --- chaos_genius/alerts/anomaly_alerts.py | 9 ++++++--- chaos_genius/alerts/utils.py | 24 ++++++++++++------------ 2 files changed, 18 insertions(+), 15 deletions(-) diff --git a/chaos_genius/alerts/anomaly_alerts.py b/chaos_genius/alerts/anomaly_alerts.py index cd28ef7a7..93e939a39 100644 --- a/chaos_genius/alerts/anomaly_alerts.py +++ b/chaos_genius/alerts/anomaly_alerts.py @@ -79,6 +79,8 @@ class AnomalyPointOriginal(BaseModel): # y-value of point y: float + # model prediction (expected value) + yhat: Optional[float] # lower bound of expected value yhat_lower: float # upper bound of expected value @@ -232,15 +234,14 @@ def _from_original_single( relevant_subdims: Optional[List["AnomalyPoint"]], ) -> "AnomalyPoint": y = round(point.y, 2) + yhat = round(point.yhat, 2) if point.yhat is not None else None yhat_lower = round(point.yhat_lower, 2) yhat_upper = round(point.yhat_upper, 2) severity = round(point.severity) series_type = point.series_type - percent_change = find_percentage_change( - point.y, previous_anomaly_point.y if previous_anomaly_point else None - ) + percent_change = find_percentage_change(point.y, point.yhat) change_message = change_message_from_percent(percent_change) previous_value = ( @@ -251,6 +252,7 @@ def _from_original_single( return AnomalyPoint( y=y, + yhat=yhat, yhat_lower=yhat_lower, yhat_upper=yhat_upper, severity=severity, @@ -1161,6 +1163,7 @@ def _format_anomaly_point_for_template( def top_anomalies(points: Iterable[TAnomalyPointOrig], n=10) -> List[TAnomalyPointOrig]: """Returns top n anomalies according to severity.""" + # TODO: how to incorporate impact here? return heapq.nlargest(n, points, key=lambda point: point.severity) diff --git a/chaos_genius/alerts/utils.py b/chaos_genius/alerts/utils.py index 2d56de045..ae4478911 100644 --- a/chaos_genius/alerts/utils.py +++ b/chaos_genius/alerts/utils.py @@ -67,22 +67,22 @@ def change_message_from_percent(percent_change: Union[str, int, float]) -> str: def find_percentage_change( - curr_val: Union[int, float], prev_val: Optional[Union[int, float]] + actual_val: Union[int, float], expected_val: Optional[Union[int, float]] ) -> Union[int, float, str]: - """Calculates percentage change between previous and current value.""" - if prev_val is None: - # previous point wasn't found - return "–" - elif curr_val == 0 and prev_val == curr_val: - # both current and previous value are 0 - return "–" - elif prev_val == 0: + """Calculates percentage change between expected and actual value.""" + if expected_val is None: + # expected value has not been calculated for this point + return "N/A" + elif actual_val == 0 and expected_val == actual_val: + # both current and expected value are 0 + return 0 + elif expected_val == 0: # previous value is 0, but current value isn't - sign_ = "+" if curr_val > 0 else "-" + sign_ = "+" if actual_val > 0 else "-" return sign_ + "inf" else: - change = curr_val - prev_val - percentage_change = (change / prev_val) * 100 + change = actual_val - expected_val + percentage_change = (change / expected_val) * 100 return round_number(percentage_change) From 250d9195801228e5b17c23f734996b08f8217d4e Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 09:50:07 +0530 Subject: [PATCH 02/10] feat(migration): remove old percent_change from triggered alerts --- ...remove_change_message_and_percent_from_.py | 73 +++++++++++++++++++ 1 file changed, 73 insertions(+) create mode 100644 migrations/versions/b176fdcdff99_remove_change_message_and_percent_from_.py diff --git a/migrations/versions/b176fdcdff99_remove_change_message_and_percent_from_.py b/migrations/versions/b176fdcdff99_remove_change_message_and_percent_from_.py new file mode 100644 index 000000000..0db44f6f1 --- /dev/null +++ b/migrations/versions/b176fdcdff99_remove_change_message_and_percent_from_.py @@ -0,0 +1,73 @@ +"""remove change message and percent from older triggered alerts + +Revision ID: b176fdcdff99 +Revises: 4dc7b0472e64 +Create Date: 2022-09-23 19:15:37.568437 + +""" +import sqlalchemy as sa +from alembic import op +from flask import json + +# revision identifiers, used by Alembic. +revision = "b176fdcdff99" +down_revision = "4dc7b0472e64" +branch_labels = None +depends_on = None + + +def upgrade(): + conn = op.get_bind() + + trig_alerts = conn.execute( + "SELECT * FROM triggered_alerts WHERE alert_type = 'KPI Alert';" + ) + + # rename "percent_change" to "_old_percent_change" + for trig_alert in trig_alerts: + alert_metadata = trig_alert["alert_metadata"] + + if "alert_data" in alert_metadata: + for data in alert_metadata["alert_data"]: + data["_old_percent_change"] = data.pop("percent_change") + + for subdim_data in data.get("relevant_subdims_", []) or []: + subdim_data["_old_percent_change"] = subdim_data.pop( + "percent_change" + ) + + conn.execute( + sa.text( + "UPDATE triggered_alerts SET alert_metadata = :metadata WHERE id = :id;" + ), + {"metadata": json.dumps(alert_metadata), "id": trig_alert["id"]}, + ) + + +def downgrade(): + # rename "_old_percent_change" to "percent_change" + conn = op.get_bind() + + trig_alerts = conn.execute( + "SELECT * FROM triggered_alerts WHERE alert_type = 'KPI Alert';" + ) + + # rename "percent_change" to "_old_percent_change" + for trig_alert in trig_alerts: + alert_metadata = trig_alert["alert_metadata"] + + if "alert_data" in alert_metadata: + for data in alert_metadata["alert_data"]: + data["percent_change"] = data.pop("_old_percent_change") + + for subdim_data in data.get("relevant_subdims_", []) or []: + subdim_data["percent_change"] = subdim_data.pop( + "_old_percent_change" + ) + + conn.execute( + sa.text( + "UPDATE triggered_alerts SET alert_metadata = :metadata WHERE id = :id;" + ), + {"metadata": json.dumps(alert_metadata), "id": trig_alert["id"]}, + ) From a5aac9ed3d1413c8933c6ca2dca1fb3a925c33bb Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 10:30:36 +0530 Subject: [PATCH 03/10] fix(alerts): update data structure and dashboard --- chaos_genius/alerts/anomaly_alerts.py | 49 ++++++++----------- chaos_genius/alerts/constants.py | 4 +- .../alerts/email_templates/common.html | 6 +-- chaos_genius/alerts/utils.py | 19 ------- chaos_genius/templates/alert_dashboard.html | 38 ++++++++------ 5 files changed, 49 insertions(+), 67 deletions(-) diff --git a/chaos_genius/alerts/anomaly_alerts.py b/chaos_genius/alerts/anomaly_alerts.py index 93e939a39..53f03946e 100644 --- a/chaos_genius/alerts/anomaly_alerts.py +++ b/chaos_genius/alerts/anomaly_alerts.py @@ -43,7 +43,6 @@ from chaos_genius.alerts.slack import anomaly_alert_slack from chaos_genius.alerts.utils import ( AlertException, - change_message_from_percent, find_percentage_change, human_readable, send_email_using_template, @@ -104,8 +103,8 @@ class AnomalyPointOriginal(BaseModel): data_datetime: datetime.datetime @property - def expected_value(self) -> str: - """Expected values represented in a string.""" + def expected_range(self) -> str: + """Expected values range represented in a string.""" return f"{self.yhat_lower} to {self.yhat_upper}" @property @@ -204,10 +203,6 @@ class AnomalyPoint(AnomalyPointOriginal): severity: int # previous data point (y-value) previous_value: Optional[float] - # percentage change from previous point - percent_change: Union[StrictFloat, StrictInt, str] - # human readable message describing the percent_change - change_message: str relevant_subdims_: Optional[List] @@ -241,9 +236,6 @@ def _from_original_single( series_type = point.series_type - percent_change = find_percentage_change(point.y, point.yhat) - change_message = change_message_from_percent(percent_change) - previous_value = ( round(previous_anomaly_point.y, 2) if previous_anomaly_point is not None @@ -262,8 +254,6 @@ def _from_original_single( created_at=point.created_at, data_datetime=point.data_datetime, previous_value=previous_value, - percent_change=percent_change, - change_message=change_message, relevant_subdims_=relevant_subdims, ) @@ -377,7 +367,8 @@ class AnomalyPointFormatted(AnomalyPoint): alert_channel_conf: Any formatted_date: str - formatted_change_percent: str + percent_change: Union[StrictFloat, StrictInt, str] + percent_change_formatted: str is_hourly: bool @@ -397,24 +388,25 @@ def _from_point_single( dt_format = ALERT_READABLE_DATE_FORMAT formatted_date = point.data_datetime.strftime(dt_format) - formatted_change_percent = point.percent_change - if isinstance(point.percent_change, (int, float)): + percent_change = find_percentage_change(point.y, point.yhat) + percent_change_formatted = percent_change + if isinstance(percent_change, (int, float)): # TODO: decide on this and simplify change_percent = ( - f"{point.percent_change:.0f}" - if abs(point.percent_change) < 10 - else f"{point.percent_change:.0f}" + f"{percent_change:.0f}" + if abs(percent_change) < 10 + else f"{percent_change:.0f}" ) - if point.percent_change > 0: - formatted_change_percent = f"{change_percent}%" + if percent_change > 0: + percent_change_formatted = f"{change_percent}%" else: - formatted_change_percent = f"{change_percent[1:]}%" + percent_change_formatted = f"{change_percent[1:]}%" if ( - isinstance(point.percent_change, str) - and point.percent_change.endswith("inf") - and point.previous_value is not None + isinstance(percent_change, str) + and percent_change.endswith("inf") + and point.yhat is not None ): - formatted_change_percent = f"{point.percent_change}%" + percent_change_formatted = f"{percent_change}%" is_hourly = time_series_frequency is not None and time_series_frequency == "H" @@ -444,7 +436,8 @@ def _from_point_single( alert_channel=alert_channel, alert_channel_conf=alert_channel_conf, formatted_date=formatted_date, - formatted_change_percent=str(formatted_change_percent), + percent_change=percent_change, + percent_change_formatted=str(percent_change_formatted), is_hourly=is_hourly, ) @@ -1122,8 +1115,8 @@ def make_anomaly_data_csv( anomaly_df.sort_values(by="severity", inplace=True, ascending=False) # this is a property that is calculated, so it needs to be assigned separately - anomaly_df["expected_value"] = [ - point.expected_value for point in all_anomaly_points + anomaly_df["expected_range"] = [ + point.expected_range for point in all_anomaly_points ] # this is a property that is calculated, so it needs to be assigned separately anomaly_df["series_type"] = [point.series_type_name for point in all_anomaly_points] diff --git a/chaos_genius/alerts/constants.py b/chaos_genius/alerts/constants.py index 74e9b7e33..97e965b14 100644 --- a/chaos_genius/alerts/constants.py +++ b/chaos_genius/alerts/constants.py @@ -27,7 +27,7 @@ "y": "Value", "severity": "Severity Score", "change_message": "Change", - "expected_value": "Expected Value", + "expected_range": "Expected Range", "previous_value": "Previous Value", } ANOMALY_REPORT_COLUMN_NAMES_MAPPER = dict( @@ -40,7 +40,7 @@ "previous_value", "change_message", "severity", - "expected_value", + "expected_range", ] ANOMALY_REPORT_COLUMN_NAMES_ORDERED = ["kpi_name"] + ANOMALY_TABLE_COLUMN_NAMES_ORDERED diff --git a/chaos_genius/alerts/email_templates/common.html b/chaos_genius/alerts/email_templates/common.html index 98402fc16..bb8bbf7b2 100644 --- a/chaos_genius/alerts/email_templates/common.html +++ b/chaos_genius/alerts/email_templates/common.html @@ -138,12 +138,12 @@ {% else -%} {% if point.y > point.previous_value %} - ↑ {{ point.formatted_change_percent }} + ↑ {{ point.percent_change_formatted }} Spike {% elif point.y < point.previous_value %} - ↓ {{ point.formatted_change_percent }} + ↓ {{ point.percent_change_formatted }} Drop {% endif %} @@ -201,7 +201,7 @@ {%- endif %} - {% if point.is_hourly -%} diff --git a/chaos_genius/alerts/utils.py b/chaos_genius/alerts/utils.py index ae4478911..84ea39055 100644 --- a/chaos_genius/alerts/utils.py +++ b/chaos_genius/alerts/utils.py @@ -47,25 +47,6 @@ def webapp_url_prefix(): return f"{CHAOSGENIUS_WEBAPP_URL}{forward_slash}" -def change_message_from_percent(percent_change: Union[str, int, float]) -> str: - """Creates a change message from given percentage change. - - percent_change will be: - - "–" in case the last data point was missing or both the points had values 0 - - 0 (int) in case there was no change - - positive value (int/float) in case there was an increase - - negative value (int/float) in case there was a decrease - """ - if isinstance(percent_change, str): - return percent_change - elif percent_change == 0: - return "No change (–)" - elif percent_change > 0: - return f"Increased by ({percent_change}%)" - else: - return f"Decreased by ({percent_change}%)" - - def find_percentage_change( actual_val: Union[int, float], expected_val: Optional[Union[int, float]] ) -> Union[int, float, str]: diff --git a/chaos_genius/templates/alert_dashboard.html b/chaos_genius/templates/alert_dashboard.html index d754c03bf..9c41d8769 100644 --- a/chaos_genius/templates/alert_dashboard.html +++ b/chaos_genius/templates/alert_dashboard.html @@ -90,11 +90,14 @@

Alerts Dashboard

Timestamp - Value + Actual Value Previous Value + + Expected Value + Users @@ -108,7 +111,7 @@

Alerts Dashboard

Date - Expected Value + Expected Range Severity Score @@ -352,21 +355,24 @@

Alerts Dashboard

"{{ point.readable_data_timestamp }}", "{{ point.y }}", "{{ point.previous_value if point.previous_value is not none else "-" }}", + "{{ point.yhat if point.yhat is not none else "N/A" }}", [ {% for email in (point.alert_channel_conf or []) %} "{{ email }}", {% endfor %} ], "{{ point.alert_channel }}", - {% if point.change_message.startswith("Increased") %} - "{{ point.change_message[:len('Increased by')] }} {{point.change_message[len('Increased by'):]}}", - {% elif point.change_message.startswith("Decreased") %} - "{{ point.change_message[:len('Decreased by')] }} {{point.change_message[len('Decreased by'):]}}", - {% else %} - "{{ point.change_message }}", - {% endif %} + {% if point.percent_change is string %} + "{{ point.percent_change_formatted }}", + {% else %} + {% if point.percent_change >= 0 %} + "{{ point.percent_change_formatted }} higher than expected", + {% else %} + "{{ point.percent_change_formatted }} lower than expected", + {% endif %} + {% endif %} "{{ point.date_only }}", - "{{ point.expected_value }}", + "{{ point.expected_range }}", `{% if point.severity >= 65 %} @@ -398,19 +404,21 @@

Alerts Dashboard

dataTableAnomaly.kpiColIndex = 1; dataTableAnomaly.alertIdColIndex = 2; dataTableAnomaly.kpiIdColIndex = 3; - dataTableAnomaly.emailColIndex = 8; - dataTableAnomaly.channelColIndex = 9; - dataTableAnomaly.dateOnlyColIndex = 11; + dataTableAnomaly.emailColIndex = 9; + dataTableAnomaly.channelColIndex = 10; + dataTableAnomaly.dateOnlyColIndex = 12; dataTableAnomaly.valueColIndex = 6; dataTableAnomaly.previousValueColIndex = 7; + dataTableAnomaly.expectedValueColIndex = 8; dataTableAnomaly.dimensionColIndex = 4; dataTableAnomaly.timeStampColIndex = 5; - dataTableAnomaly.expectedValueColIndex = 12; - dataTableAnomaly.severityColIndex = 13; + dataTableAnomaly.expectedRangeColIndex = 13; + dataTableAnomaly.severityColIndex = 14; dataTableAnomaly.on('datatable.init', function(args) { dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.valueColIndex].getElementsByTagName('a')[0].classList.add('desc'); dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.previousValueColIndex].getElementsByTagName('a')[0].classList.add('desc'); + dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.expectedValueColIndex].getElementsByTagName('a')[0].classList.add('desc'); dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.severityColIndex].getElementsByTagName('a')[0].classList.add('desc'); dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.timeStampColIndex].getElementsByTagName('a')[0].classList.add('desc'); From a3fd4e593e51972edcdba976feaf17ef12fc4740 Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 11:02:51 +0530 Subject: [PATCH 04/10] fix(alerts): change CSV headers according to new structure --- chaos_genius/alerts/constants.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chaos_genius/alerts/constants.py b/chaos_genius/alerts/constants.py index 97e965b14..d587bf275 100644 --- a/chaos_genius/alerts/constants.py +++ b/chaos_genius/alerts/constants.py @@ -25,8 +25,8 @@ "series_type": "Dimension", "data_datetime": "Time of Occurrence", "y": "Value", + "yhat": "Expected Value", "severity": "Severity Score", - "change_message": "Change", "expected_range": "Expected Range", "previous_value": "Previous Value", } @@ -38,7 +38,7 @@ "data_datetime", "y", "previous_value", - "change_message", + "yhat", "severity", "expected_range", ] From 80773e4d77ce3618ea6f1819afb907bf47dd56bc Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 11:07:37 +0530 Subject: [PATCH 05/10] fix(alert-dashboard): move change last and name it "Alert Description" --- chaos_genius/templates/alert_dashboard.html | 33 +++++++++++---------- 1 file changed, 17 insertions(+), 16 deletions(-) diff --git a/chaos_genius/templates/alert_dashboard.html b/chaos_genius/templates/alert_dashboard.html index 9c41d8769..3b492364b 100644 --- a/chaos_genius/templates/alert_dashboard.html +++ b/chaos_genius/templates/alert_dashboard.html @@ -104,9 +104,6 @@

Alerts Dashboard

Channel - - Change - Date @@ -116,6 +113,9 @@

Alerts Dashboard

Severity Score + + Alert Description + @@ -362,15 +362,6 @@

Alerts Dashboard

{% endfor %} ], "{{ point.alert_channel }}", - {% if point.percent_change is string %} - "{{ point.percent_change_formatted }}", - {% else %} - {% if point.percent_change >= 0 %} - "{{ point.percent_change_formatted }} higher than expected", - {% else %} - "{{ point.percent_change_formatted }} lower than expected", - {% endif %} - {% endif %} "{{ point.date_only }}", "{{ point.expected_range }}", `{% if point.severity >= 65 %} @@ -386,7 +377,16 @@

Alerts Dashboard

{% endif %} - {{ point.severity }}
`, + {{ point.severity }}
`, + {% if point.percent_change is string %} + "{{ point.percent_change_formatted }}", + {% else %} + {% if point.percent_change >= 0 %} + "{{ point.percent_change_formatted }} higher than expected", + {% else %} + "{{ point.percent_change_formatted }} lower than expected", + {% endif %} + {% endif %} ], {% endfor %} ]; @@ -406,14 +406,15 @@

Alerts Dashboard

dataTableAnomaly.kpiIdColIndex = 3; dataTableAnomaly.emailColIndex = 9; dataTableAnomaly.channelColIndex = 10; - dataTableAnomaly.dateOnlyColIndex = 12; + dataTableAnomaly.dateOnlyColIndex = 11; dataTableAnomaly.valueColIndex = 6; dataTableAnomaly.previousValueColIndex = 7; dataTableAnomaly.expectedValueColIndex = 8; dataTableAnomaly.dimensionColIndex = 4; dataTableAnomaly.timeStampColIndex = 5; - dataTableAnomaly.expectedRangeColIndex = 13; - dataTableAnomaly.severityColIndex = 14; + dataTableAnomaly.expectedRangeColIndex = 12; + dataTableAnomaly.severityColIndex = 13; + dataTableAnomaly.alertDescColIndex = 14; dataTableAnomaly.on('datatable.init', function(args) { dataTableAnomaly.head.getElementsByTagName('th')[dataTableAnomaly.valueColIndex].getElementsByTagName('a')[0].classList.add('desc'); From 0bf49efd09f12c1b16296a90c14152b6e88df2cb Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 11:08:10 +0530 Subject: [PATCH 06/10] feat(email-alerts): update to use new percent change (from expected) --- .../alerts/email_templates/common.html | 177 +++--------------- 1 file changed, 23 insertions(+), 154 deletions(-) diff --git a/chaos_genius/alerts/email_templates/common.html b/chaos_genius/alerts/email_templates/common.html index bb8bbf7b2..1eb0e403a 100644 --- a/chaos_genius/alerts/email_templates/common.html +++ b/chaos_genius/alerts/email_templates/common.html @@ -54,169 +54,38 @@ {% macro anomaly_point_formatting(point, kpi_link_prefix=none) -%} {% set include_kpi_name = kpi_link_prefix is not none %} - {% if point.previous_value is none or point.y == point.previous_value -%} - - ∿ Anomalous behavior - + {% if point.percent_change is string %} + Anomaly detected + {% elif point.percent_change >= 0 %} + ↑ {{ point.percent_change_formatted }} higher than expected + {% else %} + ↓ {{ point.percent_change_formatted }} lower than expected + {% endif %} - {% if include_kpi_name -%} - + - - in + {% if include_kpi_name -%} + {{ kpi_name_link(kpi_link_prefix, point) }} + {% endif %} - + {% if point.is_subdim %} + {{ subdim_name_link(point) }} + {% endif %} - {{ kpi_name_link(kpi_link_prefix, point) }} + + changed to + - {% if point.is_subdim %} - {{ subdim_name_link(point) }} - {% endif %} - {% else -%} - - - detected - - - - {% if point.is_subdim -%} - - - in - - - - {{ subdim_name_link(point) }} - {%- endif %} - {%- endif %} - - - - - {% if point.previous_value is none -%} - - - changed to - - - {{point.y_readable}} - - {% if point.is_hourly -%} - - at - - {{ point.anomaly_time_only }} - {%- endif %} - {% else -%} - {% if point.is_hourly %} - - with constant value - - - {{point.y_readable}} - - - from - - {{ point.previous_point_time_only }} - - - to - - {{ point.anomaly_time_only }} - {% else %} - - with same value - - - {{point.y_readable}} - - - as previous day - - {% endif %} - {%- endif %} - - {% else -%} - {% if point.y > point.previous_value %} - - ↑ {{ point.percent_change_formatted }} - Spike - - {% elif point.y < point.previous_value %} - - ↓ {{ point.percent_change_formatted }} - Drop - - {% endif %} - - {% if include_kpi_name %} - - - in - - - - {{ kpi_name_link(kpi_link_prefix, point) }} - - {% if point.is_subdim %} - {{ subdim_name_link(point) }} - {% endif %} - {% else %} - - - detected - - - - {% if point.is_subdim %} - - - in - - - - {{ subdim_name_link(point) }} - {% endif %} - {% endif %} + {{point.y_readable}} + {% if point.is_hourly -%} - - - - - changed - + at + {{ point.anomaly_time_only }} + {%- endif %} - - to - - - {{point.y_readable}} - - {% if point.previous_value_readable is not none -%} - - - from - - {{point.previous_value_readable}} - - {%- endif %} - - {% if point.is_hourly -%} - - from - - {{ point.previous_point_time_only }} - - - to - - {{ point.anomaly_time_only }} - {%- endif %} - {%- endif %}{% if point.relevant_subdims -%} + {% if point.relevant_subdims -%}
  • Reasons for change: From 6cf67d5c8015cdaeb0c88f0d76c054365fe47800 Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 11:27:25 +0530 Subject: [PATCH 07/10] feat(slack-alerts): update to use new percent change (from expected) --- .../alerts/email_templates/common.html | 2 +- chaos_genius/alerts/slack.py | 61 +++++-------------- 2 files changed, 16 insertions(+), 47 deletions(-) diff --git a/chaos_genius/alerts/email_templates/common.html b/chaos_genius/alerts/email_templates/common.html index 1eb0e403a..036c7586c 100644 --- a/chaos_genius/alerts/email_templates/common.html +++ b/chaos_genius/alerts/email_templates/common.html @@ -55,7 +55,7 @@ {% set include_kpi_name = kpi_link_prefix is not none %} {% if point.percent_change is string %} - Anomaly detected + ∿ Anomaly detected {% elif point.percent_change >= 0 %} ↑ {{ point.percent_change_formatted }} higher than expected {% else %} diff --git a/chaos_genius/alerts/slack.py b/chaos_genius/alerts/slack.py index 150a93f35..10950d9bb 100644 --- a/chaos_genius/alerts/slack.py +++ b/chaos_genius/alerts/slack.py @@ -268,57 +268,26 @@ def anomaly_point_formatting( include_kpi_name = kpi_link_prefix is not None - if point.previous_value is None or point.y == point.previous_value: + if isinstance(point.percent_change, str): out += "- :black_circle_for_record: Anomalous behavior" - - if include_kpi_name: - out += f" in *{kpi_name_link(kpi_link_prefix, point)}* " - if point.is_subdim: - out += f"{subdim_name_link(point)} " - else: - out += " detected " - if point.is_subdim: - out += f"in {subdim_name_link(point)} " - - if point.previous_value is None: - out += f"- changed to *{point.y_readable}*" - if point.is_hourly: - out += f" at {point.anomaly_time_only}" - else: - if point.is_hourly: - out += ( - f"- with constant value *{point.y_readable}*" - + f" from {point.previous_point_time_only}" - + f" to {point.anomaly_time_only}" - ) - else: - out += f"- with same value *{point.y_readable}* as previous day" - + elif point.percent_change >= 0: + out += f"- :arrow_up: {point.percent_change_formatted} higher than expected" else: - if point.y > point.previous_value: - out += f"- :arrow_up: {point.formatted_change_percent} Spike" - elif point.y < point.previous_value: - out += f"- :arrow_down_small: {point.formatted_change_percent} Drop" - - if include_kpi_name: - out += f" in *{kpi_name_link(kpi_link_prefix, point)}* " - if point.is_subdim: - out += f"{subdim_name_link(point)} " - else: - out += " detected " - if point.is_subdim: - out += f"in {subdim_name_link(point)} " + out += ( + f"- :arrow_down_small: {point.percent_change_formatted} lower than expected" + ) + + out += " - " - out += f"- changed to *{point.y_readable}*" + if include_kpi_name: + out += f"*{kpi_name_link(kpi_link_prefix, point)}* " - if point.previous_value_readable is not None: - out += f" from {point.previous_value_readable}" + if point.is_subdim: + out += f"{subdim_name_link(point)} " - if point.is_hourly: - out += ( - f" from {point.previous_point_time_only}" - + f" to {point.anomaly_time_only}" - ) + out += f"changed to *{point.y_readable}*" + if point.is_hourly: + out += f" at {point.anomaly_time_only}" if point.relevant_subdims: out += "\n - Reasons for change: " From 5b7f6fa7f42a2709df5dae6b10842af13696a9d2 Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Mon, 26 Sep 2022 11:43:44 +0530 Subject: [PATCH 08/10] fix(alerts): move previous value col before actual value --- chaos_genius/alerts/constants.py | 4 ++-- chaos_genius/templates/alert_dashboard.html | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chaos_genius/alerts/constants.py b/chaos_genius/alerts/constants.py index d587bf275..189f099c6 100644 --- a/chaos_genius/alerts/constants.py +++ b/chaos_genius/alerts/constants.py @@ -24,7 +24,7 @@ ANOMALY_TABLE_COLUMN_NAMES_MAPPER = { "series_type": "Dimension", "data_datetime": "Time of Occurrence", - "y": "Value", + "y": "Actual Value", "yhat": "Expected Value", "severity": "Severity Score", "expected_range": "Expected Range", @@ -36,8 +36,8 @@ ANOMALY_TABLE_COLUMN_NAMES_ORDERED = [ "series_type", "data_datetime", - "y", "previous_value", + "y", "yhat", "severity", "expected_range", diff --git a/chaos_genius/templates/alert_dashboard.html b/chaos_genius/templates/alert_dashboard.html index 3b492364b..146dd9bd1 100644 --- a/chaos_genius/templates/alert_dashboard.html +++ b/chaos_genius/templates/alert_dashboard.html @@ -89,12 +89,12 @@

    Alerts Dashboard

    Timestamp - - Actual Value - Previous Value + + Actual Value + Expected Value @@ -353,8 +353,8 @@

    Alerts Dashboard

    "{{ point.kpi_id }}", "{{ point.series_type_name }}", "{{ point.readable_data_timestamp }}", - "{{ point.y }}", "{{ point.previous_value if point.previous_value is not none else "-" }}", + "{{ point.y }}", "{{ point.yhat if point.yhat is not none else "N/A" }}", [ {% for email in (point.alert_channel_conf or []) %} @@ -407,8 +407,8 @@

    Alerts Dashboard

    dataTableAnomaly.emailColIndex = 9; dataTableAnomaly.channelColIndex = 10; dataTableAnomaly.dateOnlyColIndex = 11; - dataTableAnomaly.valueColIndex = 6; - dataTableAnomaly.previousValueColIndex = 7; + dataTableAnomaly.valueColIndex = 7; + dataTableAnomaly.previousValueColIndex = 6; dataTableAnomaly.expectedValueColIndex = 8; dataTableAnomaly.dimensionColIndex = 4; dataTableAnomaly.timeStampColIndex = 5; From 305a8039875f0102266060bf477ff74ead3cb683 Mon Sep 17 00:00:00 2001 From: Amatullah Date: Mon, 26 Sep 2022 11:50:18 +0400 Subject: [PATCH 09/10] fix(format): add expected range --- chaos_genius/alerts/email_templates/common.html | 4 ++++ chaos_genius/alerts/slack.py | 1 + 2 files changed, 5 insertions(+) diff --git a/chaos_genius/alerts/email_templates/common.html b/chaos_genius/alerts/email_templates/common.html index 036c7586c..c905230ee 100644 --- a/chaos_genius/alerts/email_templates/common.html +++ b/chaos_genius/alerts/email_templates/common.html @@ -85,6 +85,10 @@ {{ point.anomaly_time_only }} {%- endif %} + + . Expected: {{ point.yhat_lower_readable }} - {{ point.yhat_upper_readable }}. + + {% if point.relevant_subdims -%}
    • diff --git a/chaos_genius/alerts/slack.py b/chaos_genius/alerts/slack.py index 10950d9bb..673ef72cd 100644 --- a/chaos_genius/alerts/slack.py +++ b/chaos_genius/alerts/slack.py @@ -288,6 +288,7 @@ def anomaly_point_formatting( out += f"changed to *{point.y_readable}*" if point.is_hourly: out += f" at {point.anomaly_time_only}" + out += f". Expected: {point.yhat_lower_readable} - {point.yhat_upper_readable}." if point.relevant_subdims: out += "\n - Reasons for change: " From 296262dead0ddebf756108090dd68659714303de Mon Sep 17 00:00:00 2001 From: Samyak S Sarnayak Date: Tue, 27 Sep 2022 15:00:05 +0530 Subject: [PATCH 10/10] fix(alerts): remove extra space, add parens for expected range --- chaos_genius/alerts/email_templates/common.html | 14 +++++++------- chaos_genius/alerts/slack.py | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/chaos_genius/alerts/email_templates/common.html b/chaos_genius/alerts/email_templates/common.html index c905230ee..c1304551f 100644 --- a/chaos_genius/alerts/email_templates/common.html +++ b/chaos_genius/alerts/email_templates/common.html @@ -76,17 +76,17 @@ changed to - {{point.y_readable}} + {{point.y_readable}}{% if point.is_hourly -%} at - {{ point.anomaly_time_only }} - {%- endif %} + {{ point.anomaly_time_only }}{%- endif %}. (Expected range: {{ point.yhat_lower_readable }} - {{ point.yhat_upper_readable }}). {% if point.relevant_subdims -%} diff --git a/chaos_genius/alerts/slack.py b/chaos_genius/alerts/slack.py index 673ef72cd..00b7b4ce6 100644 --- a/chaos_genius/alerts/slack.py +++ b/chaos_genius/alerts/slack.py @@ -288,7 +288,7 @@ def anomaly_point_formatting( out += f"changed to *{point.y_readable}*" if point.is_hourly: out += f" at {point.anomaly_time_only}" - out += f". Expected: {point.yhat_lower_readable} - {point.yhat_upper_readable}." + out += f". (Expected range: {point.yhat_lower_readable} - {point.yhat_upper_readable})." if point.relevant_subdims: out += "\n - Reasons for change: "