Azure Function 应用程序接收 Azure Monitor 警报并发布到 Slack webhook

问题描述 投票:0回答:1

我一直在尝试让我的函数应用程序正常工作。我想做的是将 Azure Monitor 警报集成到 Slack 频道中发布。这是通过 Slack 中的 Webhook 完成的。

当我将 x-www-form-urlencoded POST 发布到函数应用程序时,我可以让它在本地环境中工作。

我现在想要实现的是以正确的格式接收Azure Monitor警报,解析并调整格式以发送到Webhook。

我在接收警报和解析方面遇到了很大的问题。有人能指出如何正确解析对象吗?

我开始使用一些代码来接收 POST,这工作正常。

import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

import java.util.Map;
import java.util.HashMap;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;

public class AzureMonitorAlertFunction {
    @FunctionName("AzureMonitorAlertFunction")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {

        context.getLogger().info("Java HTTP trigger processed an Azure Monitor alert.");

        try {
            // Get the alert payload from Azure Monitor
            String alertPayload = request.getBody().orElse("");

            // Format the alert payload into a Slack message
            String slackMessage = "{ \"text\": \"New Azure Monitor Alert: " + alertPayload + "\" }";

            // Send the message to Slack using the incoming webhook
            String slackWebhookUrl = System.getenv("SLACK_WEBHOOK_URL");
            sendSlackMessage(slackWebhookUrl, slackMessage);

            return request.createResponseBuilder(HttpStatus.OK).body("Alert sent to Slack successfully!").build();
        } catch (Exception e) {
            // Log the error
            context.getLogger().severe("Error processing Azure Monitor alert: " + e.getMessage());

            // Return an error response
            return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).body("Error processing alert.").build();
        }
    }

    private void sendSlackMessage(String webhookUrl, String message) throws Exception {
        try {
            URL url = new URL(webhookUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);

            try (OutputStream os = conn.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8))) {
                writer.write(message);
                writer.flush();
            }

            int responseCode = conn.getResponseCode();
            if (responseCode != 200) {
                throw new RuntimeException("Failed to send alert to Slack. Response code: " + responseCode);
            }

            conn.disconnect();
        } catch (Exception e) {
            throw new RuntimeException("Error sending alert to Slack: " + e.getMessage());
        }
    }
}

然后,当我添加解析以接收 Azure Monitor 警报时,我遇到了问题...... 这是代码


import com.fasterxml.jackson.databind.ObjectMapper;
import com.microsoft.azure.functions.annotation.*;
import com.microsoft.azure.functions.*;

import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.StandardCharsets;
import java.util.Optional;
import com.fasterxml.jackson.annotation.JsonProperty;

public class AlertToSlack {
    @FunctionName("AzureMonitorAlertFunction")
    public HttpResponseMessage run(
            @HttpTrigger(name = "req", methods = {HttpMethod.POST}, authLevel = AuthorizationLevel.ANONYMOUS) HttpRequestMessage<Optional<String>> request,
            final ExecutionContext context) {

        context.getLogger().info("Java HTTP trigger processed an Azure Monitor alert.");

        try {
            // Get the alert payload from Azure Monitor
            String alertPayload = request.getBody().orElse("");

            // Parse the JSON payload into an AzureMonitorAlert object
            ObjectMapper objectMapper = new ObjectMapper();
            AzureMonitorAlert alert = objectMapper.readValue(alertPayload, AzureMonitorAlert.class);

            // Format the alert details into a Slack message
            String slackMessage = "{ \"text\": \"New Azure Monitor Alert: " +
                    "Rule: " + alert.getData().getEssentials().getAlertRule() + ", " +
                    "Severity: " + alert.getData().getEssentials().getSeverity() + "\" }";

            // Send the message to Slack using the incoming webhook
            String slackWebhookUrl = System.getenv("SLACK_WEBHOOK_URL");
            sendSlackMessage(slackWebhookUrl, slackMessage);

            return request.createResponseBuilder(HttpStatus.OK).body("Alert sent to Slack successfully!").build();
        } catch (Exception e) {
            // Log the error
            context.getLogger().severe("Error processing Azure Monitor alert: " + e.getMessage());

            // Return an error response
            return request.createResponseBuilder(HttpStatus.INTERNAL_SERVER_ERROR).body("Error processing alert.").build();
        }
    }


    private void sendSlackMessage(String webhookUrl, String message) throws Exception {
        try {
            URL url = new URL(webhookUrl);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "application/json");
            conn.setDoOutput(true);

            try (OutputStream os = conn.getOutputStream(); PrintWriter writer = new PrintWriter(new OutputStreamWriter(os, StandardCharsets.UTF_8))) {
                writer.write(message);
                writer.flush();
            }

            int responseCode = conn.getResponseCode();
            if (responseCode != 200) {
                throw new RuntimeException("Failed to send alert to Slack. Response code: " + responseCode);
            }

            conn.disconnect();
        } catch (Exception e) {
            throw new RuntimeException("Error sending alert to Slack: " + e.getMessage());
        }
    }
}


class AzureMonitorAlert {
    @JsonProperty("schemaId")
    private String schemaId;

    @JsonProperty("data")
    private AlertData data;

    @JsonProperty("alertId")
    private String alertId;

    // Getters and setters for schemaId and data

    public String getSchemaId() {
        return schemaId;
    }

    public void setSchemaId(String schemaId) {
        this.schemaId = schemaId;
    }

    public AlertData getData() {
        return data;
    }

    public void setData(AlertData data) {
        this.data = data;
    }

    public String getAlertId() {
        return alertId;
    }

    public void setAlertId(String alertId) {
        this.alertId = alertId;
    }
}

class AlertData {
    @JsonProperty("essentials")
    private AlertEssentials essentials;

    // Getters and setters for essentials

    public AlertEssentials getEssentials() {
        return essentials;
    }

    public void setEssentials(AlertEssentials essentials) {
        this.essentials = essentials;
    }
}

class AlertEssentials {
    @JsonProperty("alertRule")
    private String alertRule;

    @JsonProperty("severity")
    private String severity;

    // Getters and setters for alertRule and severity

    public String getAlertRule() {
        return alertRule;
    }

    public void setAlertRule(String alertRule) {
        this.alertRule = alertRule;
    }

    public String getSeverity() {
        return severity;
    }

    public void setSeverity(String severity) {
        this.severity = severity;
    }
}

这是我尝试以原始格式发布的示例:

{
  "schemaId": "AzureMonitorMetricAlert",
  "data": {
    "essentials": {
      "alertId": "/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/microsoft.insights/metricAlerts/{alert-name}",
      "alertRule": "alert-name",
      "severity": "Sev1",
      "signalType": "Metric",
      "monitorCondition": "Fired",
      "monitoringService": "Platform",
      "targetResource": {
        "resourceId": "/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/{resource-provider}/{resource-type}/{resource-name}",
        "resourceName": "resource-name",
        "resourceType": "resource-type"
      },
      "timestamp": "2023-09-13T12:34:56.789Z"
    },
    "result": {
      "baseline": 100,
      "currentValue": 120,
      "dynamicThresholds": {
        "lower": 80,
        "upper": 150
      },
      "firedDateTime": "2023-09-13T12:34:56.789Z"
    }
  },
  "context": {
    "timestamp": "2023-09-13T12:34:56.789Z",
    "id": "unique-id",
    "name": "alert-name",
    "description": "This is a sample alert description.",
    "type": "Microsoft.Insights/metricAlerts",
    "conditionType": "SingleResourceMultipleMetricCriteria",
    "condition": {
      "windowSize": "PT5M",
      "allOf": [
        {
          "metricName": "metric-name",
          "aggregation": "Average",
          "operator": "GreaterThan",
          "threshold": 100
        }
      ]
    },
    "subscriptionId": "subscription-id",
    "resourceGroupName": "resource-group"
  }
}


这是我收到的错误消息:

[2023-09-13T09:26:43.816Z] Java HTTP trigger processed an Azure Monitor alert.
[2023-09-13T09:26:43.818Z] Error processing Azure Monitor alert: Unrecognized field "alertId" (class com.example.azurealerts.AlertEssentials), not marked as ignorable (2 known properties: "alertRule", "severity"])
 at [Source: (String)"{
[2023-09-13T09:26:43.818Z]   "schemaId": "AzureMonitorMetricAlert",
[2023-09-13T09:26:43.818Z] Function "AzureMonitorAlertFunction" (Id: 7c667744-9513-4cae-83aa-c24a485b9d6f) invoked by Java Worker
[2023-09-13T09:26:43.818Z]   "data": {
[2023-09-13T09:26:43.818Z]     "essentials": {
[2023-09-13T09:26:43.819Z]       "alertId": "/subscriptions/{subscription-id}/resourceGroups/{resource-group}/providers/microsoft.insights/metricAlerts/{alert-name",
[2023-09-13T09:26:43.819Z]       "alertRule": "alert-name",
[2023-09-13T09:26:43.819Z] Executed 'Functions.AzureMonitorAlertFunction' (Succeeded, Id=7c667744-9513-4cae-83aa-c24a485b9d6f, Duration=10ms)
[2023-09-13T09:26:43.819Z]       "severity": "Sev1",
[2023-09-13T09:26:43.819Z]       "signalType": "Metric",
[2023-09-13T09:26:43.819Z]       "monitorCondition": "Fired",
[2023-09-13T09:26:43.819Z]       "monitoringService": "Platform",
[2023-09-13T09:26:43.819Z]       "targetResource": {
[2023-09-13T09:26:43.820Z]         "resourceId": "/subscriptions/{subscription-id}/resourceGroups/{resource-group"[truncated 1055 chars]; line: 5, column: 19] (through reference chain: com.example.azurealerts.AzureMonitorAlert["data"]->com.example.azurealerts.AlertData["essentials"]->com.example.azurealerts.AlertEssentials["alertId"])

我添加了所有 JSON 对象属性,即:


import com.fasterxml.jackson.annotation.JsonProperty;

public class AlertEssentials {
    @JsonProperty("alertId")
    private String alertId;

    @JsonProperty("alertRule")
    private String alertRule;

    @JsonProperty("severity")
    private String severity;

    @JsonProperty("signalType")
    private String signalType;

    @JsonProperty("monitorCondition")
    private String monitorCondition;

    @JsonProperty("monitoringService")
    private String monitoringService;

    @JsonProperty("alertTargetIDs")
    private String[] alertTargetIDs;

    @JsonProperty("configurationItems")
    private String[] configurationItems;

    @JsonProperty("originAlertId")
    private String originAlertId;

    @JsonProperty("firedDateTime")
    private String firedDateTime;

    @JsonProperty("description")
    private String description;

    @JsonProperty("essentialsVersion")
    private String essentialsVersion;

    @JsonProperty("alertContextVersion")
    private String alertContextVersion;

    // Getters and setters for all fields

    public String getAlertId() {
        return alertId;
    }

    public void setAlertId(String alertId) {
        this.alertId = alertId;
    }

    public String getAlertRule() {
        return alertRule;
    }

    public void setAlertRule(String alertRule) {
        this.alertRule = alertRule;
    }

    public String getSeverity() {
        return severity;
    }

    public void setSeverity(String severity) {
        this.severity = severity;
    }

    public String getSignalType() {
        return signalType;
    }

    public void setSignalType(String signalType) {
        this.signalType = signalType;
    }

    public String getMonitorCondition() {
        return monitorCondition;
    }

    public void setMonitorCondition(String monitorCondition) {
        this.monitorCondition = monitorCondition;
    }

    public String getMonitoringService() {
        return monitoringService;
    }

    public void setMonitoringService(String monitoringService) {
        this.monitoringService = monitoringService;
    }

    public String[] getAlertTargetIDs() {
        return alertTargetIDs;
    }

    public void setAlertTargetIDs(String[] alertTargetIDs) {
        this.alertTargetIDs = alertTargetIDs;
    }

    public String[] getConfigurationItems() {
        return configurationItems;
    }

    public void setConfigurationItems(String[] configurationItems) {
        this.configurationItems = configurationItems;
    }

    public String getOriginAlertId() {
        return originAlertId;
    }

    public void setOriginAlertId(String originAlertId) {
        this.originAlertId = originAlertId;
    }

    public String getFiredDateTime() {
        return firedDateTime;
    }

    public void setFiredDateTime(String firedDateTime) {
        this.firedDateTime = firedDateTime;
    }

    public String getDescription() {
        return description;
    }

    public void setDescription(String description) {
        this.description = description;
    }

    public String getEssentialsVersion() {
        return essentialsVersion;
    }

    public void setEssentialsVersion(String essentialsVersion) {
        this.essentialsVersion = essentialsVersion;
    }

    public String getAlertContextVersion() {
        return alertContextVersion;
    }

    public void setAlertContextVersion(String alertContextVersion) {
        this.alertContextVersion = alertContextVersion;
    }
}

我认为这可能会起作用。我会尽快更新

java azure azure-functions webhooks slack
1个回答
0
投票

我的数据模型中遗漏了很多变量。我还没有找到任何相关的模式,所以我必须通过警报来执行此警报,因为 json 对象似乎每个警报都会改变。

© www.soinside.com 2019 - 2024. All rights reserved.