Events Data Model
Signals Events are stored in FireHydrant when a webhook is sent to FireHydrant that matches the correct data model. This guide will help you understand the data model that FireHydrant uses to define Events.
What makes a valid Signal Event object?
Signal Event object is a dictionary hashmap returned by transposer function that looks like the following:
{
"summary": "CPU usage too high",
"body": "VM CPU utilization is over 90%",
"status": "OPEN",
"idempotency_key": "18913k2b63ifs",
"tags": [
"name:myService",
"region:us-west2"
],
"annotations": {
"acme-inc/team": "sre"
},
"level": "ERROR",
"images": [
{
"src": "https://example.com/pic.png",
"alt": "Snapshot from [P2] [Triggered] [TEST] Signals Test Monitor"
}
],
"links": [
{
"href": "https://datadoghq.com/event/event?id=238472398472582",
"text": "Datadog Monitor"
}
]
}
Data Model
Field Name | Type | Example |
---|---|---|
summary | text | CPU Utilization Spiking |
body | text | The production server is experiencing greater than 99% utilizations of compute. |
status | enum | Either OPEN (0) or CLOSED (1) |
level | enum | Any of: - INFO (0)- WARN (1)- ERROR (2)- FATAL (3) |
annotations | object | { “randomNumber”: 1234 } |
images | array | [ { "src": "https://site.com/images/123.png', "alt": "A simple, sample image" } ] |
links | array | [ { "href": "https://site.com/monitors/123', "text": "Monitoring Source" } ] |
tags | array | ["tag1", "service:your-service-slug", "environment:production"] |
idempotency_key | text | A unique identifier used to group/deduplicate open alerts |
Understanding the Idempotency Key
The idempotency_key
is FireHydrant's way of identifying incoming events that need to be grouped together. For instance, if your monitoring tool sends two webhooks to FireHydrant with a matching idempotency_key
, Signals will not create a new alert if an alert is already Open. If an alert from an event with that idempotency_key
has been resolved or dismissed, Signals will create a new one.
Another use of the idempotency_key
grouping is to auto-resolve flappy alerts. If your monitoring tool sends an OPEN
and then CLOSED
event to FireHydrant, the system will auto-resolve any alerts that were generated from the original event.
Tags and the Service Catalog
Using the service-tagging convention, you can automatically associate any Service Catalog component with your alerts and the incidents that get opened from those alerts.
To reference a service, use the service:
prefix combined with the slug of your service in FireHydrant. These slugs can be found in your Service Catalog on each respective component's page in the Details section.
![Where to find the slug on a component's details page](https://files.readme.io/24057f5-CleanShot_2024-04-25_at_17.21.492x.png)
Where to find the slug on a component's details page
For example, let's take a service called API Gateway
with a slug of api-gateway
. It is in the Production
environment (slug production
) that has associated functionality called Public API
with a slug of public-api
.
The tags to automatically pull these components in would be: service:api-gateway
, environment:production
, and functionality:public-api
. When you include a catalog component in your payload, any incidents that are opened from Alerts created by that payload will automatically mark those catalog components as impacted when the incident is opened. Below is the example payload:
{
"summary": "CPU Utilization Spiking",
"body": "The production server is experiencing greater than 99% utilizations of compute.",
"level": "ERROR",
"status": "OPEN",
"idempotency_key": "ad98rb3b2b",
"images": [
{
"src": "https://site.com/images/123.png",
"alt": "A simple, sample image"
}
],
"links": [
{
"href": "https://site.com/monitors/123",
"text": "Monitoring Source"
}
],
"annotations": {
"policy": "escalatable"
},
"tags": ["service:api-gateway", "environment:production", "functionality:public-api", "random-tag"],
}
Provided input structure
Transpose function takes in input
argument, which consist of request payload and body in the following structure:
{
headers: {
"Content-Type": "application/json"
},
data: {
// The request JSON payload here
}
}
Debugging
To debug values use debug
function and validation errors will attach debug
information.
Examples
The following are examples of default transpose
functions for different types of monitoring providers.
Alertmanager
/*
* Transpose a payload from a webhook into a signal.
*
* @returns {{summary: string, body: string, level: number, links: string[], images: string[], tags: string[], idempotency_key: string, status: number}} Signal object.
*/
function transpose(input) {
const body = input.data;
const payload = body.jsonPayload;
const alerts = payload.alerts;
const commonAnnotations = payload.commonAnnotations;
const commonLabels = payload.commonLabels;
const groupLabels = payload.groupLabels;
const signal = {
summary: commonAnnotations.summary || "Alert from Alertmanager",
body: commonAnnotations.description || "No body provided",
links: alerts.map(a => ({href: a.generatorURL || payload.externalURL, text: a.labels.alertname})),
annotations: {
...(Object.keys(commonAnnotations).reduce((m, k) => {
m[`annotations-${k}`] = commonAnnotations[k];
return m;
}, {})),
...(Object.keys(commonLabels).reduce((m, k) => {
m[`labels-${k}`] = commonLabels[k];
return m;
}, {})),
...(Object.keys(groupLabels).reduce((m, k) => {
m[`group-by-${k}`] = groupLabels[k];
return m;
}, {})),
groupKey: payload.groupKey,
},
idempotency_key: md5(payload.groupKey),
}
return signal;
}
Datadog
const levelMap = {
"critical": 2,
"error": 1,
"warning": 1,
"info": 0,
"debug": 0
}
function payloadLevel(payload) {
if (!payload?.level) return 0;
return levelMap[payload.level.toLowerCase()] || 0;
}
function payloadStatus(s) {
if (!s) return 0;
return s === "Triggered" ? 0 : 1;
}
function payloadTags(tags) {
if (typeof tags === "string") {
return tags.split(",")
}
if (Array.isArray(tags)) {
return tags
}
return []
}
/*
* Transpose a payload from a webhook into a signal.
*
* @returns {{summary: string, body: string, level: number, links: string[], images: string[], tags: string[], idempotency_key: string, status: number}} Signal object.
*/
function transpose(input) {
const payload = input.data;
const signal = {
summary: payload?.summary || "Alert from Datadog",
body: payload?.body || "No body provided",
level: payloadLevel(payload?.level),
links: payload?.links || [],
images: (payload?.images || []).filter(i => !!i.src),
tags: payloadTags(payload?.tags),
idempotency_key: payload?.summary || "",
status: payloadStatus(payload?.status),
}
if (payload?.unique_key) {
signal.idempotency_key = payload?.unique_key;
}
return signal
}
Updated 4 days ago