webhooks: Update Librato integration to AppOptics.

This commit is contained in:
Niloth P 2024-11-20 11:46:43 +05:30
parent 81b8a60297
commit 4b5bafc43c
19 changed files with 75 additions and 68 deletions

Binary file not shown.

After

Width:  |  Height:  |  Size: 106 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 96 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 576 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 548 B

View File

@ -358,6 +358,9 @@ WEBHOOK_INTEGRATIONS: list[WebhookIntegration] = [
), ),
WebhookIntegration("ansibletower", ["deployment"], display_name="Ansible Tower"), WebhookIntegration("ansibletower", ["deployment"], display_name="Ansible Tower"),
WebhookIntegration("appfollow", ["customer-support"], display_name="AppFollow"), WebhookIntegration("appfollow", ["customer-support"], display_name="AppFollow"),
WebhookIntegration(
"appoptics", ["monitoring"], display_name="AppOptics", legacy_names=["librato"]
),
WebhookIntegration("appveyor", ["continuous-integration"], display_name="AppVeyor"), WebhookIntegration("appveyor", ["continuous-integration"], display_name="AppVeyor"),
WebhookIntegration("azuredevops", ["version-control"], display_name="AzureDevOps"), WebhookIntegration("azuredevops", ["version-control"], display_name="AzureDevOps"),
WebhookIntegration("beanstalk", ["version-control"], stream_name="commits"), WebhookIntegration("beanstalk", ["version-control"], stream_name="commits"),
@ -467,7 +470,6 @@ WEBHOOK_INTEGRATIONS: list[WebhookIntegration] = [
WebhookIntegration("jira", ["project-management"], display_name="Jira"), WebhookIntegration("jira", ["project-management"], display_name="Jira"),
WebhookIntegration("jotform", ["misc"], display_name="Jotform"), WebhookIntegration("jotform", ["misc"], display_name="Jotform"),
WebhookIntegration("json", ["misc"], display_name="JSON formatter"), WebhookIntegration("json", ["misc"], display_name="JSON formatter"),
WebhookIntegration("librato", ["monitoring"]),
WebhookIntegration("lidarr", ["entertainment"]), WebhookIntegration("lidarr", ["entertainment"]),
WebhookIntegration("linear", ["project-management"], display_name="Linear"), WebhookIntegration("linear", ["project-management"], display_name="Linear"),
WebhookIntegration("mention", ["marketing"], display_name="Mention"), WebhookIntegration("mention", ["marketing"], display_name="Mention"),
@ -730,6 +732,7 @@ DOC_SCREENSHOT_CONFIG: dict[str, list[BaseScreenshotConfig]] = {
], ],
"ansibletower": [ScreenshotConfig("job_successful_multiple_hosts.json")], "ansibletower": [ScreenshotConfig("job_successful_multiple_hosts.json")],
"appfollow": [ScreenshotConfig("review.json")], "appfollow": [ScreenshotConfig("review.json")],
"appoptics": [ScreenshotConfig("three_conditions_alert.json", payload_as_query_param=True)],
"appveyor": [ScreenshotConfig("appveyor_build_success.json")], "appveyor": [ScreenshotConfig("appveyor_build_success.json")],
"azuredevops": [ScreenshotConfig("code_push.json")], "azuredevops": [ScreenshotConfig("code_push.json")],
"basecamp": [ScreenshotConfig("doc_active.json")], "basecamp": [ScreenshotConfig("doc_active.json")],
@ -797,7 +800,6 @@ DOC_SCREENSHOT_CONFIG: dict[str, list[BaseScreenshotConfig]] = {
"jira": [ScreenshotConfig("created_v1.json")], "jira": [ScreenshotConfig("created_v1.json")],
"jotform": [ScreenshotConfig("response.json")], "jotform": [ScreenshotConfig("response.json")],
"json": [ScreenshotConfig("json_github_push__1_commit.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")], "lidarr": [ScreenshotConfig("lidarr_album_grabbed.json")],
"linear": [ScreenshotConfig("issue_create_complex.json")], "linear": [ScreenshotConfig("issue_create_complex.json")],
"mention": [ScreenshotConfig("webfeeds.json")], "mention": [ScreenshotConfig("webfeeds.json")],

View File

@ -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!}

View File

@ -33,19 +33,19 @@
"violations": { "violations": {
"test-source": [ "test-source": [
{ {
"metric": "librato.cpu.percent.idle", "metric": "system.cpu.percent.idle",
"value": 2, "value": 2,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3543146 "condition_violated": 3543146
}, },
{ {
"metric": "librato.swap.swap.cached", "metric": "system.swap.swap.cached",
"value": 42, "value": 42,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3651148 "condition_violated": 3651148
}, },
{ {
"metric": "librato.swap.swap.cached", "metric": "system.swap.swap.cached",
"value": 51, "value": 51,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3651902 "condition_violated": 3651902

View File

@ -33,19 +33,19 @@
"violations2": { "violations2": {
"test-source": [ "test-source": [
{ {
"metric": "librato.cpu.percent.idle", "metric": "system.cpu.percent.idle",
"value": 2, "value": 2,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3543146 "condition_violated": 3543146
}, },
{ {
"metric": "librato.swap.swap.cached", "metric": "system.swap.swap.cached",
"value": 42, "value": 42,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3651148 "condition_violated": 3651148
}, },
{ {
"metric": "librato.swap.swap.cached", "metric": "system.swap.swap.cached",
"value": 51, "value": 51,
"recorded_at": 1459415502, "recorded_at": 1459415502,
"condition_violated": 3651902 "condition_violated": 3651902

View File

@ -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"
}
]
}

View File

@ -44,7 +44,7 @@
"condition_violated": 4299396 "condition_violated": 4299396
}, },
{ {
"metric": "librato.swap.swap.cached", "metric": "system.swap.swap.cached",
"value": 42, "value": 42,
"recorded_at": 1460407214, "recorded_at": 1460407214,
"condition_violated": 3651148 "condition_violated": 3651148

View File

@ -5,23 +5,24 @@ from typing_extensions import override
from zerver.lib.test_classes import WebhookTestCase from zerver.lib.test_classes import WebhookTestCase
class LibratoHookTests(WebhookTestCase): class AppOpticsHookTests(WebhookTestCase):
CHANNEL_NAME = "librato" CHANNEL_NAME = "appoptics"
URL_TEMPLATE = "/api/v1/external/librato?api_key={api_key}&stream={stream}" URL_TEMPLATE = "/api/v1/external/appoptics?api_key={api_key}&stream={stream}"
WEBHOOK_DIR_NAME = "librato" LEGACY_URL_TEMPLATES = ["/api/v1/external/librato?stream={stream}&api_key={api_key}"]
WEBHOOK_DIR_NAME = "appoptics"
IS_ATTACHMENT = False IS_ATTACHMENT = False
@override @override
def get_body(self, fixture_name: str) -> str: def get_body(self, fixture_name: str) -> str:
if self.IS_ATTACHMENT: 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( 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: def test_alert_message_with_default_topic(self) -> None:
expected_topic_name = "Alert alert.name" 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( self.check_webhook(
"alert", "alert",
expected_topic_name, expected_topic_name,
@ -32,7 +33,7 @@ class LibratoHookTests(WebhookTestCase):
def test_alert_message_with_custom_topic(self) -> None: def test_alert_message_with_custom_topic(self) -> None:
custom_topic_name = "custom_name" custom_topic_name = "custom_name"
self.url = self.build_webhook_url(topic=custom_topic_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( self.check_webhook(
"alert", "alert",
custom_topic_name, custom_topic_name,
@ -41,7 +42,7 @@ class LibratoHookTests(WebhookTestCase):
) )
def test_three_conditions_alert_message(self) -> None: 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" expected_topic_name = "Alert TooHighTemperature"
self.check_webhook( self.check_webhook(
"three_conditions_alert", "three_conditions_alert",
@ -52,7 +53,7 @@ class LibratoHookTests(WebhookTestCase):
def test_alert_clear(self) -> None: def test_alert_clear(self) -> None:
expected_topic_name = "Alert Alert_name" 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( self.check_webhook(
"alert_cleared", "alert_cleared",
expected_topic_name, expected_topic_name,
@ -63,7 +64,7 @@ class LibratoHookTests(WebhookTestCase):
def test_snapshot(self) -> None: def test_snapshot(self) -> None:
self.IS_ATTACHMENT = True self.IS_ATTACHMENT = True
expected_topic_name = "Snapshots" 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( self.check_webhook(
"snapshot", "snapshot",
expected_topic_name, expected_topic_name,

View File

@ -19,8 +19,8 @@ ALERT_VIOLATION = "violations"
SNAPSHOT = "image_url" SNAPSHOT = "image_url"
class LibratoWebhookParser: class AppOpticsWebhookParser:
ALERT_URL_TEMPLATE = "https://metrics.librato.com/alerts#/{alert_id}" ALERT_URL_TEMPLATE = "https://my.appoptics.com/alerts#/{alert_id}"
def __init__(self, payload: Mapping[str, Any], attachments: list[dict[str, Any]]) -> None: def __init__(self, payload: Mapping[str, Any], attachments: list[dict[str, Any]]) -> None:
self.payload = payload self.payload = payload
@ -65,7 +65,7 @@ class LibratoWebhookParser:
return author_name, image_url, title 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: def __init__(self, payload: Mapping[str, Any], attachments: list[dict[str, Any]]) -> None:
super().__init__(payload, attachments) super().__init__(payload, attachments)
self.payload_available_types = { self.payload_available_types = {
@ -159,9 +159,9 @@ class LibratoWebhookHandler(LibratoWebhookParser):
return content return content
@webhook_view("Librato") @webhook_view("AppOptics")
@typed_endpoint @typed_endpoint
def api_librato_webhook( def api_appoptics_webhook(
request: HttpRequest, request: HttpRequest,
user_profile: UserProfile, user_profile: UserProfile,
*, *,
@ -175,7 +175,7 @@ def api_librato_webhook(
if not attachments and not payload: if not attachments and not payload:
raise JsonableError(_("Malformed JSON input")) raise JsonableError(_("Malformed JSON input"))
message_handler = LibratoWebhookHandler(payload, attachments) message_handler = AppOpticsWebhookHandler(payload, attachments)
topic_name = message_handler.generate_topic() topic_name = message_handler.generate_topic()
try: try:

View File

@ -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!}

View File

@ -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"
}
]
}