Created
November 13, 2024 17:11
-
-
Save i5okie/e4fc821db95ec253ddf691e3c5bd5e0a to your computer and use it in GitHub Desktop.
SysDig custom webhook for RocketChat
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
class Script { | |
process_incoming_request({ request }) { | |
const data = request.content; | |
// Helper function to format timestamp | |
const formatTimestamp = (timestamp) => { | |
if (!timestamp || timestamp === "null") return "N/A"; | |
const date = new Date(parseInt(timestamp) / 1000); | |
return date.toISOString().replace("T", " ").replace("Z", " UTC"); | |
}; | |
// Helper function to extract metric value from metadata | |
const extractMetricValue = (metadata) => { | |
if (!metadata || !Array.isArray(metadata) || metadata.length === 0) | |
return null; | |
const firstEntry = metadata[0]; | |
if (!firstEntry.metricValues || !firstEntry.metricValues.length) | |
return null; | |
const metricValue = firstEntry.metricValues[0]; | |
return { | |
value: | |
typeof metricValue.value === "number" | |
? metricValue.value.toFixed(2) | |
: metricValue.value, | |
metric: metricValue.metric, | |
aggregation: metricValue.aggregation, | |
groupAggregation: metricValue.groupAggregation, | |
}; | |
}; | |
// Determine colour and emoji based on severity and state | |
const getAlertStyle = (severity, state) => { | |
if (state === "OK") { | |
return { color: "#2ECC40", emoji: "✅" }; // green | |
} | |
switch (severity.toUpperCase()) { | |
case "HIGH": | |
return { color: "#FF4136", emoji: "🔥" }; // red | |
case "MEDIUM": | |
return { color: "#FF851B", emoji: "⚠️" }; // orange | |
case "LOW": | |
return { color: "#FFDC00", emoji: "⚡" }; // yellow | |
default: | |
return { color: "#AAAAAA", emoji: "ℹ️" }; // grey | |
} | |
}; | |
// Extract key info from labels | |
const labels = data.labels || {}; | |
const cluster = | |
labels.kube_cluster_name || labels.agent_tag_cluster || "N/A"; | |
const namespace = labels.kube_namespace_name || "N/A"; | |
// Get alert style | |
const { color, emoji } = getAlertStyle(data.severity, data.state); | |
// Extract metric values | |
const triggerMetricInfo = extractMetricValue(data.trigger_metadata); | |
const resolvedMetricInfo = extractMetricValue(data.resolved_metadata); | |
// Prepare main text content | |
const mainTextLines = [ | |
`${emoji} - *${data.labels.alertname || data.title}*`, | |
`_${data.description}_`, | |
"```", | |
`Status | ${data.state} (${data.severity})`, | |
`============| - - - - - - - - - - - - - - - - - - - -`, | |
`Cluster | ${cluster}`, | |
`Namespace | ${namespace}`, | |
]; | |
// Add pertinent information if available | |
if (labels.kube_pod_name) { | |
mainTextLines.push(`Pod | ${labels.kube_pod_name}`); | |
} | |
if (labels.kube_pod_container_name) { | |
mainTextLines.push(`Container | ${labels.kube_pod_container_name}`); | |
} | |
if (labels.kube_workload_type && labels.kube_workload_name) { | |
mainTextLines.push(`Workload | ${labels.kube_workload_type}/${labels.kube_workload_name}`); | |
} | |
if (labels.persistentvolumeclaim) { | |
mainTextLines.push(`PVC | ${labels.persistentvolumeclaim}`); | |
} | |
mainTextLines.push("============| - - - - - - - - - - - - - - - - - - - -"); | |
mainTextLines.push(`Triggered | ${formatTimestamp(data.triggered_at)}`); | |
if (data.resolved_at && data.resolved_at !== "null") { | |
mainTextLines.push(`Resolved | ${formatTimestamp(data.resolved_at)}`); | |
} | |
mainTextLines.push("```"); | |
const mainText = mainTextLines.join("\n"); | |
// Prepare fields with optional information | |
const fields = [ | |
{ | |
title: "Metric", | |
value: triggerMetricInfo.metric, | |
short: false, | |
}, | |
{ | |
title: "Value", | |
value: triggerMetricInfo.value, | |
short: true, | |
} | |
]; | |
if (resolvedMetricInfo) { | |
fields.push({ | |
title: "End Value", | |
value: resolvedMetricInfo.value, | |
short: true, | |
}); | |
} | |
if (labels.reason || labels.kube_pod_container_reason) { | |
fields.push({ | |
title: "Reason", | |
value: labels.reason || labels.kube_pod_container_reason, | |
short: true, | |
}); | |
} | |
// Add SysDig link as the last field | |
fields.push({ | |
title: "Details", | |
value: `[View in SysDig](${data.alert_link})`, | |
short: true, | |
}); | |
// Construct the message | |
const attachment = { | |
color: color, | |
title: `Alert details`, | |
fields: fields, | |
}; | |
return { | |
content: { | |
text: mainText, | |
attachments: [attachment], | |
}, | |
}; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
{ | |
"alert_link": "{{@event_url}}", | |
"description": "{{@alert_description}}", | |
"resolved_at": "{{@event_resolved_timestamp}}", | |
"severity": "{{@alert_severity}}", | |
"state": "{{@event_state}}", | |
"title": "{{@event_title}}", | |
"triggered_at": "{{@event_trigger_timestamp}}", | |
"trigger_metadata": {{@event_trigger_metadata}}, | |
"resolved_metadata": {{@event_resolved_metadata}}, | |
"labels": {{@event_labels}} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Formatting example:


Depending on your alerts, you may have to customize the label-matching section to suit your needs.