diff --git a/static/images/integrations/appoptics/001.png b/static/images/integrations/appoptics/001.png new file mode 100644 index 0000000000..ba1e9bb0ca Binary files /dev/null and b/static/images/integrations/appoptics/001.png differ diff --git a/static/images/integrations/bot_avatars/appoptics.png b/static/images/integrations/bot_avatars/appoptics.png new file mode 100644 index 0000000000..17e3ea79e3 Binary files /dev/null and b/static/images/integrations/bot_avatars/appoptics.png differ diff --git a/static/images/integrations/bot_avatars/librato.png b/static/images/integrations/bot_avatars/librato.png deleted file mode 100644 index 3df6d91e0c..0000000000 Binary files a/static/images/integrations/bot_avatars/librato.png and /dev/null differ diff --git a/static/images/integrations/librato/001.png b/static/images/integrations/librato/001.png deleted file mode 100644 index 4ff5e73f88..0000000000 Binary files a/static/images/integrations/librato/001.png and /dev/null differ diff --git a/static/images/integrations/logos/appoptics.svg b/static/images/integrations/logos/appoptics.svg new file mode 100644 index 0000000000..c8d418a132 Binary files /dev/null and b/static/images/integrations/logos/appoptics.svg differ diff --git a/static/images/integrations/logos/librato.svg b/static/images/integrations/logos/librato.svg deleted file mode 100644 index 191672bc9f..0000000000 Binary files a/static/images/integrations/logos/librato.svg and /dev/null differ diff --git a/zerver/lib/integrations.py b/zerver/lib/integrations.py index 743671814b..b52e2c2d26 100644 --- a/zerver/lib/integrations.py +++ b/zerver/lib/integrations.py @@ -358,6 +358,9 @@ WEBHOOK_INTEGRATIONS: list[WebhookIntegration] = [ ), WebhookIntegration("ansibletower", ["deployment"], display_name="Ansible Tower"), WebhookIntegration("appfollow", ["customer-support"], display_name="AppFollow"), + WebhookIntegration( + "appoptics", ["monitoring"], display_name="AppOptics", legacy_names=["librato"] + ), WebhookIntegration("appveyor", ["continuous-integration"], display_name="AppVeyor"), WebhookIntegration("azuredevops", ["version-control"], display_name="AzureDevOps"), WebhookIntegration("beanstalk", ["version-control"], stream_name="commits"), @@ -467,7 +470,6 @@ WEBHOOK_INTEGRATIONS: list[WebhookIntegration] = [ WebhookIntegration("jira", ["project-management"], display_name="Jira"), WebhookIntegration("jotform", ["misc"], display_name="Jotform"), WebhookIntegration("json", ["misc"], display_name="JSON formatter"), - WebhookIntegration("librato", ["monitoring"]), WebhookIntegration("lidarr", ["entertainment"]), WebhookIntegration("linear", ["project-management"], display_name="Linear"), WebhookIntegration("mention", ["marketing"], display_name="Mention"), @@ -730,6 +732,7 @@ DOC_SCREENSHOT_CONFIG: dict[str, list[BaseScreenshotConfig]] = { ], "ansibletower": [ScreenshotConfig("job_successful_multiple_hosts.json")], "appfollow": [ScreenshotConfig("review.json")], + "appoptics": [ScreenshotConfig("three_conditions_alert.json", payload_as_query_param=True)], "appveyor": [ScreenshotConfig("appveyor_build_success.json")], "azuredevops": [ScreenshotConfig("code_push.json")], "basecamp": [ScreenshotConfig("doc_active.json")], @@ -797,7 +800,6 @@ DOC_SCREENSHOT_CONFIG: dict[str, list[BaseScreenshotConfig]] = { "jira": [ScreenshotConfig("created_v1.json")], "jotform": [ScreenshotConfig("response.json")], "json": [ScreenshotConfig("json_github_push__1_commit.json")], - "librato": [ScreenshotConfig("three_conditions_alert.json", payload_as_query_param=True)], "lidarr": [ScreenshotConfig("lidarr_album_grabbed.json")], "linear": [ScreenshotConfig("issue_create_complex.json")], "mention": [ScreenshotConfig("webfeeds.json")], diff --git a/zerver/webhooks/librato/__init__.py b/zerver/webhooks/appoptics/__init__.py similarity index 100% rename from zerver/webhooks/librato/__init__.py rename to zerver/webhooks/appoptics/__init__.py diff --git a/zerver/webhooks/appoptics/doc.md b/zerver/webhooks/appoptics/doc.md new file mode 100644 index 0000000000..058bf5cbee --- /dev/null +++ b/zerver/webhooks/appoptics/doc.md @@ -0,0 +1,31 @@ +# Zulip AppOptics integration + +Get Zulip notifications for your SolarWinds AppOptics (formerly Librato) alerts! + +{start_tabs} + +1. {!create-an-incoming-webhook.md!} + +1. {!generate-webhook-url-basic.md!} + +1. Go to your AppOptics homepage, and click on **Settings**. Select + **Metric Settings**, click **Notification Services**, and select + **Webhooks**. + +1. Set **Title** to a title of your choice, such as `Zulip`. Set **URL** + to the URL generated above, and click **Add**. + +!!! tip "" + + When you create a new **Alert**, you can enable this webhook from the + **Notification Services** tab. + +{end_tabs} + +{!congrats.md!} + +![](/static/images/integrations/appoptics/001.png) + +### Related documentation + +{!webhooks-url-specification.md!} diff --git a/zerver/webhooks/librato/fixtures/alert.json b/zerver/webhooks/appoptics/fixtures/alert.json similarity index 88% rename from zerver/webhooks/librato/fixtures/alert.json rename to zerver/webhooks/appoptics/fixtures/alert.json index 99fb698070..cb90c2b828 100644 --- a/zerver/webhooks/librato/fixtures/alert.json +++ b/zerver/webhooks/appoptics/fixtures/alert.json @@ -33,19 +33,19 @@ "violations": { "test-source": [ { - "metric": "librato.cpu.percent.idle", + "metric": "system.cpu.percent.idle", "value": 2, "recorded_at": 1459415502, "condition_violated": 3543146 }, { - "metric": "librato.swap.swap.cached", + "metric": "system.swap.swap.cached", "value": 42, "recorded_at": 1459415502, "condition_violated": 3651148 }, { - "metric": "librato.swap.swap.cached", + "metric": "system.swap.swap.cached", "value": 51, "recorded_at": 1459415502, "condition_violated": 3651902 diff --git a/zerver/webhooks/librato/fixtures/alert_cleared.json b/zerver/webhooks/appoptics/fixtures/alert_cleared.json similarity index 100% rename from zerver/webhooks/librato/fixtures/alert_cleared.json rename to zerver/webhooks/appoptics/fixtures/alert_cleared.json diff --git a/zerver/webhooks/librato/fixtures/bad.json b/zerver/webhooks/appoptics/fixtures/bad.json similarity index 100% rename from zerver/webhooks/librato/fixtures/bad.json rename to zerver/webhooks/appoptics/fixtures/bad.json diff --git a/zerver/webhooks/librato/fixtures/bad_msg_type.json b/zerver/webhooks/appoptics/fixtures/bad_msg_type.json similarity index 88% rename from zerver/webhooks/librato/fixtures/bad_msg_type.json rename to zerver/webhooks/appoptics/fixtures/bad_msg_type.json index eb84b6ea17..af2b15df06 100644 --- a/zerver/webhooks/librato/fixtures/bad_msg_type.json +++ b/zerver/webhooks/appoptics/fixtures/bad_msg_type.json @@ -33,19 +33,19 @@ "violations2": { "test-source": [ { - "metric": "librato.cpu.percent.idle", + "metric": "system.cpu.percent.idle", "value": 2, "recorded_at": 1459415502, "condition_violated": 3543146 }, { - "metric": "librato.swap.swap.cached", + "metric": "system.swap.swap.cached", "value": 42, "recorded_at": 1459415502, "condition_violated": 3651148 }, { - "metric": "librato.swap.swap.cached", + "metric": "system.swap.swap.cached", "value": 51, "recorded_at": 1459415502, "condition_violated": 3651902 diff --git a/zerver/webhooks/appoptics/fixtures/snapshot.json b/zerver/webhooks/appoptics/fixtures/snapshot.json new file mode 100644 index 0000000000..8e36aec75d --- /dev/null +++ b/zerver/webhooks/appoptics/fixtures/snapshot.json @@ -0,0 +1,15 @@ +{ + "attachments": [ + { + "author_name": "Hamlet", + "author_link": "mailto:hamlet@zulip .com", + "author_icon": "https://secure.gravatar.com/avatar/99ca91cc7c0d8ef72fbd69a03a871a12?s=32&d=mm", + "title": "https://my.appoptics.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409", + "title_link": "https://my.appoptics.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409", + "fallback": "https://my.appoptics.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409 by Rafal: http://snapshots.appoptics.com/chart/nr5l3n0c-82162.png", + "image_url": "http://snapshots.appoptics.com/chart/nr5l3n0c-82162.png", + "text": null, + "color": "#0881AE" + } + ] +} diff --git a/zerver/webhooks/librato/fixtures/three_conditions_alert.json b/zerver/webhooks/appoptics/fixtures/three_conditions_alert.json similarity index 96% rename from zerver/webhooks/librato/fixtures/three_conditions_alert.json rename to zerver/webhooks/appoptics/fixtures/three_conditions_alert.json index 9be772cd9f..463a611c71 100644 --- a/zerver/webhooks/librato/fixtures/three_conditions_alert.json +++ b/zerver/webhooks/appoptics/fixtures/three_conditions_alert.json @@ -44,7 +44,7 @@ "condition_violated": 4299396 }, { - "metric": "librato.swap.swap.cached", + "metric": "system.swap.swap.cached", "value": 42, "recorded_at": 1460407214, "condition_violated": 3651148 diff --git a/zerver/webhooks/librato/tests.py b/zerver/webhooks/appoptics/tests.py similarity index 54% rename from zerver/webhooks/librato/tests.py rename to zerver/webhooks/appoptics/tests.py index af4ba26aba..d8df50ddf2 100644 --- a/zerver/webhooks/librato/tests.py +++ b/zerver/webhooks/appoptics/tests.py @@ -5,23 +5,24 @@ from typing_extensions import override from zerver.lib.test_classes import WebhookTestCase -class LibratoHookTests(WebhookTestCase): - CHANNEL_NAME = "librato" - URL_TEMPLATE = "/api/v1/external/librato?api_key={api_key}&stream={stream}" - WEBHOOK_DIR_NAME = "librato" +class AppOpticsHookTests(WebhookTestCase): + CHANNEL_NAME = "appoptics" + URL_TEMPLATE = "/api/v1/external/appoptics?api_key={api_key}&stream={stream}" + LEGACY_URL_TEMPLATES = ["/api/v1/external/librato?stream={stream}&api_key={api_key}"] + WEBHOOK_DIR_NAME = "appoptics" IS_ATTACHMENT = False @override def get_body(self, fixture_name: str) -> str: if self.IS_ATTACHMENT: - return self.webhook_fixture_data("librato", fixture_name, file_type="json") + return self.webhook_fixture_data("appoptics", fixture_name, file_type="json") return urlencode( - {"payload": self.webhook_fixture_data("librato", fixture_name, file_type="json")} + {"payload": self.webhook_fixture_data("appoptics", fixture_name, file_type="json")} ) def test_alert_message_with_default_topic(self) -> None: expected_topic_name = "Alert alert.name" - expected_message = "Alert [alert_name](https://metrics.librato.com/alerts#/6294535) has triggered! [Reaction steps](http://www.google.pl):\n * Metric `librato.cpu.percent.idle`, sum was below 44 by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `librato.swap.swap.cached`, average was absent by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `librato.swap.swap.cached`, derivative was above 9 by 300s, recorded at 2016-03-31 09:11:42 UTC." + expected_message = "Alert [alert_name](https://my.appoptics.com/alerts#/6294535) has triggered! [Reaction steps](http://www.google.pl):\n * Metric `system.cpu.percent.idle`, sum was below 44 by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `system.swap.swap.cached`, average was absent by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `system.swap.swap.cached`, derivative was above 9 by 300s, recorded at 2016-03-31 09:11:42 UTC." self.check_webhook( "alert", expected_topic_name, @@ -32,7 +33,7 @@ class LibratoHookTests(WebhookTestCase): def test_alert_message_with_custom_topic(self) -> None: custom_topic_name = "custom_name" self.url = self.build_webhook_url(topic=custom_topic_name) - expected_message = "Alert [alert_name](https://metrics.librato.com/alerts#/6294535) has triggered! [Reaction steps](http://www.google.pl):\n * Metric `librato.cpu.percent.idle`, sum was below 44 by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `librato.swap.swap.cached`, average was absent by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `librato.swap.swap.cached`, derivative was above 9 by 300s, recorded at 2016-03-31 09:11:42 UTC." + expected_message = "Alert [alert_name](https://my.appoptics.com/alerts#/6294535) has triggered! [Reaction steps](http://www.google.pl):\n * Metric `system.cpu.percent.idle`, sum was below 44 by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `system.swap.swap.cached`, average was absent by 300s, recorded at 2016-03-31 09:11:42 UTC.\n * Metric `system.swap.swap.cached`, derivative was above 9 by 300s, recorded at 2016-03-31 09:11:42 UTC." self.check_webhook( "alert", custom_topic_name, @@ -41,7 +42,7 @@ class LibratoHookTests(WebhookTestCase): ) def test_three_conditions_alert_message(self) -> None: - expected_message = "Alert [alert_name](https://metrics.librato.com/alerts#/6294535) has triggered! [Reaction steps](http://www.use.water.pl):\n * Metric `collectd.interface.eth0.if_octets.tx`, absolute_value was above 4 by 300s, recorded at 2016-04-11 20:40:14 UTC.\n * Metric `collectd.load.load.longterm`, max was above 99, recorded at 2016-04-11 20:40:14 UTC.\n * Metric `librato.swap.swap.cached`, average was absent by 60s, recorded at 2016-04-11 20:40:14 UTC." + expected_message = "Alert [alert_name](https://my.appoptics.com/alerts#/6294535) has triggered! [Reaction steps](http://www.use.water.pl):\n * Metric `collectd.interface.eth0.if_octets.tx`, absolute_value was above 4 by 300s, recorded at 2016-04-11 20:40:14 UTC.\n * Metric `collectd.load.load.longterm`, max was above 99, recorded at 2016-04-11 20:40:14 UTC.\n * Metric `system.swap.swap.cached`, average was absent by 60s, recorded at 2016-04-11 20:40:14 UTC." expected_topic_name = "Alert TooHighTemperature" self.check_webhook( "three_conditions_alert", @@ -52,7 +53,7 @@ class LibratoHookTests(WebhookTestCase): def test_alert_clear(self) -> None: expected_topic_name = "Alert Alert_name" - expected_message = "Alert [alert_name](https://metrics.librato.com/alerts#/6309313) has cleared at 2016-04-12 13:11:44 UTC!" + expected_message = "Alert [alert_name](https://my.appoptics.com/alerts#/6309313) has cleared at 2016-04-12 13:11:44 UTC!" self.check_webhook( "alert_cleared", expected_topic_name, @@ -63,7 +64,7 @@ class LibratoHookTests(WebhookTestCase): def test_snapshot(self) -> None: self.IS_ATTACHMENT = True expected_topic_name = "Snapshots" - expected_message = "**Hamlet** sent a [snapshot](http://snapshots.librato.com/chart/nr5l3n0c-82162.png) of [metric](https://metrics.librato.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409)." + expected_message = "**Hamlet** sent a [snapshot](http://snapshots.appoptics.com/chart/nr5l3n0c-82162.png) of [metric](https://my.appoptics.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409)." self.check_webhook( "snapshot", expected_topic_name, diff --git a/zerver/webhooks/librato/view.py b/zerver/webhooks/appoptics/view.py similarity index 96% rename from zerver/webhooks/librato/view.py rename to zerver/webhooks/appoptics/view.py index e89d048534..47dce05483 100644 --- a/zerver/webhooks/librato/view.py +++ b/zerver/webhooks/appoptics/view.py @@ -19,8 +19,8 @@ ALERT_VIOLATION = "violations" SNAPSHOT = "image_url" -class LibratoWebhookParser: - ALERT_URL_TEMPLATE = "https://metrics.librato.com/alerts#/{alert_id}" +class AppOpticsWebhookParser: + ALERT_URL_TEMPLATE = "https://my.appoptics.com/alerts#/{alert_id}" def __init__(self, payload: Mapping[str, Any], attachments: list[dict[str, Any]]) -> None: self.payload = payload @@ -65,7 +65,7 @@ class LibratoWebhookParser: return author_name, image_url, title -class LibratoWebhookHandler(LibratoWebhookParser): +class AppOpticsWebhookHandler(AppOpticsWebhookParser): def __init__(self, payload: Mapping[str, Any], attachments: list[dict[str, Any]]) -> None: super().__init__(payload, attachments) self.payload_available_types = { @@ -159,9 +159,9 @@ class LibratoWebhookHandler(LibratoWebhookParser): return content -@webhook_view("Librato") +@webhook_view("AppOptics") @typed_endpoint -def api_librato_webhook( +def api_appoptics_webhook( request: HttpRequest, user_profile: UserProfile, *, @@ -175,7 +175,7 @@ def api_librato_webhook( if not attachments and not payload: raise JsonableError(_("Malformed JSON input")) - message_handler = LibratoWebhookHandler(payload, attachments) + message_handler = AppOpticsWebhookHandler(payload, attachments) topic_name = message_handler.generate_topic() try: diff --git a/zerver/webhooks/librato/doc.md b/zerver/webhooks/librato/doc.md deleted file mode 100644 index 2d11abeec5..0000000000 --- a/zerver/webhooks/librato/doc.md +++ /dev/null @@ -1,27 +0,0 @@ -# Zulip AppOptics/Librato integration - -Get Zulip notifications for your AppOptics/Librato alerts! - -{start_tabs} - -1. {!create-an-incoming-webhook.md!} - -1. {!generate-webhook-url-basic.md!} - -1. Go to your AppOptics/Librato homepage, and click on **Settings**. - Select **Notification Services**, and click **Webhooks**. - -1. Set **Title** to a title of your choice, such as `Zulip`. Set **URL** - to the URL generated above, and click **Add**. When you create a - new **Alert**, you can enable this webhook under the **Notification - Services** tab. - -{end_tabs} - -{!congrats.md!} - -![](/static/images/integrations/librato/001.png) - -### Related documentation - -{!webhooks-url-specification.md!} diff --git a/zerver/webhooks/librato/fixtures/snapshot.json b/zerver/webhooks/librato/fixtures/snapshot.json deleted file mode 100644 index 543c55242f..0000000000 --- a/zerver/webhooks/librato/fixtures/snapshot.json +++ /dev/null @@ -1,15 +0,0 @@ -{ - "attachments": [ - { - "author_name": "Hamlet", - "author_link": "mailto:hamlet@zulip .com", - "author_icon": "https://secure.gravatar.com/avatar/99ca91cc7c0d8ef72fbd69a03a871a12?s=32&d=mm", - "title": "https://metrics.librato.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409", - "title_link": "https://metrics.librato.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409", - "fallback": "https://metrics.librato.com/s/spaces/167315/explore/1731491?duration=72039&end_time=1460569409 by Rafal: http://snapshots.librato.com/chart/nr5l3n0c-82162.png", - "image_url": "http://snapshots.librato.com/chart/nr5l3n0c-82162.png", - "text": null, - "color": "#0881AE" - } - ] -}