From c8850d4358c511d320c3edffe341e9d3dc3cea1e Mon Sep 17 00:00:00 2001 From: Guido Trucco Date: Fri, 17 Sep 2021 19:35:59 +0000 Subject: [PATCH] RFC: Add slack anomaly detection step --- .bumpversion.cfg | 2 +- CHANGELOG.md | 6 ++++ soam/__init__.py | 2 +- soam/reporting/slack_report.py | 48 ++++++++++++++++++++++++++++ tests/reporting/test_slack_report.py | 23 ++++++++++++- 5 files changed, 78 insertions(+), 3 deletions(-) diff --git a/.bumpversion.cfg b/.bumpversion.cfg index f7ee71b..1a7065a 100644 --- a/.bumpversion.cfg +++ b/.bumpversion.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 0.9.6 +current_version = 0.10.0 tag = False [bumpversion:file:soam/__init__.py] diff --git a/CHANGELOG.md b/CHANGELOG.md index 73b97d4..447c199 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.10.0- 2021-09-10] + +### Added +- Slack Anomaly Report Task + ## [0.9.6- 2021-09-10] ### Fixed @@ -12,6 +17,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Added - Add client_token to SlackReport init. +>>>>>>> ec8276626b283e1773b31457e4c84dd2c28b4306 ## [0.9.4- 2021-08-17] diff --git a/soam/__init__.py b/soam/__init__.py index bcbe201..a80da97 100644 --- a/soam/__init__.py +++ b/soam/__init__.py @@ -1,3 +1,3 @@ """Version.""" -__version__ = '0.9.6' +__version__ = '0.10.0' diff --git a/soam/reporting/slack_report.py b/soam/reporting/slack_report.py index 1e0bc6a..154af72 100644 --- a/soam/reporting/slack_report.py +++ b/soam/reporting/slack_report.py @@ -195,6 +195,54 @@ def run( # type: ignore ) +class SlackAnomalyReportTask(Step): + """ + Builds up the task of the anomaly report designed for Slack. + """ + + def __init__(self, **kwargs: Any): + """ + Parameters + ---------- + channel_id: str + Slack channel id where the report will be sent. + metric_name: str + Performance metric being measured. + setting_path: str + Setting path. + kwargs: + Extra args to pass. + """ + Step.__init__(self, **kwargs) # type: ignore + + def run( # type: ignore + self, + slack_client: slack.WebClient, + channel_id: str, + plot: Union[Path, IO], + metric_name: str, + anomaly_df: pd.DataFrame, + date_col: str, + ): + """ + Parameters + ---------- + channel_id: str + Slack channel id where the report will be sent. + plot: str, pathlib.Path or buffer + Anomaly plot + metric_name: str + Metric to report. + anomaly_df: pd.DataFrame + DataFrame with anomalous values. Must have the following columns: ['y','yhat','yhat_lower','yhat_upper'] + date_col: str + Name of the date column + """ + return send_anomaly_report( + slack_client, channel_id, plot, metric_name, anomaly_df, date_col + ) + + class SlackMessage: def __init__( self, diff --git a/tests/reporting/test_slack_report.py b/tests/reporting/test_slack_report.py index d28f15c..64edd1f 100644 --- a/tests/reporting/test_slack_report.py +++ b/tests/reporting/test_slack_report.py @@ -3,13 +3,14 @@ from datetime import date from io import BytesIO from pathlib import Path, PosixPath -from unittest.mock import MagicMock +from unittest.mock import MagicMock, patch from jinja2 import Template import pandas as pd import pytest from soam.reporting.slack_report import ( + SlackAnomalyReportTask, SlackMessage, send_anomaly_report, send_multiple_slack_messages, @@ -219,3 +220,23 @@ def test_send_no_anomaly_report(): initial_comment=expected_message, thread_ts=None, ) + + +def test_slack_anomaly_report_task(): + with patch("soam.reporting.slack_report.send_anomaly_report") as send_report_mock: + task = SlackAnomalyReportTask() + client_mock = MagicMock() + plot_file = BytesIO(b"abcdef") + anomaly_df = pd.DataFrame( + [ + [date(2021, 1, 1), 1.5, 1.01, 2.2, 0.5], + [date(2021, 1, 2), 4.01, 4.02, 4.7, 3.9], + ], + columns=["date", "y", "yhat", "yhat_upper", "yhat_lower"], + ) + metric_name = "test" + test_channel = "test" + task.run(client_mock, test_channel, plot_file, metric_name, anomaly_df, "date") + send_report_mock.assert_called_once_with( + client_mock, test_channel, plot_file, metric_name, anomaly_df, "date" + )