towerops/lib/towerops/pagerduty/client.ex

112 lines
3 KiB
Elixir

defmodule Towerops.PagerDuty.Client do
@moduledoc "PagerDuty Events API v2 client."
require Logger
@events_url "https://events.pagerduty.com/v2/enqueue"
def trigger(routing_key, alert, device, site_name, towerops_url) do
send_event(%{
routing_key: routing_key,
event_action: "trigger",
dedup_key: dedup_key(alert),
payload: %{
summary: alert_summary(alert, device),
source: "towerops",
severity: severity(alert.alert_type),
timestamp: DateTime.to_iso8601(alert.triggered_at),
component: device.hostname || device.ip_address,
group: site_name,
class: to_string(alert.alert_type),
custom_details: %{
device_id: device.id,
device_name: device.hostname || device.ip_address,
ip_address: device.ip_address,
site_name: site_name,
alert_type: to_string(alert.alert_type),
message: alert.message,
towerops_url: towerops_url
}
},
links: [%{href: towerops_url, text: "View in TowerOps"}]
})
end
def acknowledge(routing_key, alert) do
send_event(%{
routing_key: routing_key,
event_action: "acknowledge",
dedup_key: dedup_key(alert)
})
end
def resolve(routing_key, alert) do
send_event(%{
routing_key: routing_key,
event_action: "resolve",
dedup_key: dedup_key(alert)
})
end
def test_connection(routing_key) do
test_dedup = "towerops-test-#{System.unique_integer([:positive])}"
case send_event(%{
routing_key: routing_key,
event_action: "trigger",
dedup_key: test_dedup,
payload: %{
summary: "TowerOps integration test",
source: "towerops",
severity: "info",
timestamp: DateTime.to_iso8601(DateTime.utc_now())
}
}) do
{:ok, _} ->
send_event(%{
routing_key: routing_key,
event_action: "resolve",
dedup_key: test_dedup
})
error ->
error
end
end
defp send_event(body) do
case Req.post(@events_url, json: body) do
{:ok, %{status: status, body: resp_body}} when status in [200, 202] ->
{:ok, resp_body}
{:ok, %{status: 400, body: resp_body}} ->
{:error, {:bad_request, resp_body["message"] || "Invalid event"}}
{:ok, %{status: 429}} ->
{:error, :rate_limited}
{:ok, %{status: status}} ->
{:error, {:unexpected_status, status}}
{:error, error} ->
Logger.warning("PagerDuty API error: #{inspect(error)}")
{:error, error}
end
end
defp dedup_key(alert), do: "towerops-alert-#{alert.id}"
defp alert_summary(alert, device) do
name = device.hostname || device.ip_address
case alert.alert_type do
:device_down -> "Device down: #{name}"
:device_up -> "Device recovered: #{name}"
other -> "Alert: #{other} on #{name}"
end
end
defp severity(:device_down), do: "critical"
defp severity(:device_up), do: "info"
defp severity(_), do: "warning"
end