Browse Source
* feat alert-spi support prometheus alert manager * fix: fix err into message * Update dolphinscheduler-alert/dolphinscheduler-alert-plugins/dolphinscheduler-alert-prometheus/src/main/java/org/apache/dolphinscheduler/plugin/alert/prometheus/PrometheusAlertSender.java Co-authored-by: 旺阳 <wang@lqwang.net>3.2.1-prepare
Jingliu Xiong
1 year ago
committed by
GitHub
12 changed files with 478 additions and 3 deletions
@ -0,0 +1,39 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<!-- |
||||
~ Licensed to the Apache Software Foundation (ASF) under one or more |
||||
~ contributor license agreements. See the NOTICE file distributed with |
||||
~ this work for additional information regarding copyright ownership. |
||||
~ The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
~ (the "License"); you may not use this file except in compliance with |
||||
~ the License. You may obtain a copy of the License at |
||||
~ |
||||
~ http://www.apache.org/licenses/LICENSE-2.0 |
||||
~ |
||||
~ Unless required by applicable law or agreed to in writing, software |
||||
~ distributed under the License is distributed on an "AS IS" BASIS, |
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
~ See the License for the specific language governing permissions and |
||||
~ limitations under the License. |
||||
--> |
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> |
||||
<modelVersion>4.0.0</modelVersion> |
||||
<parent> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-alert-plugins</artifactId> |
||||
<version>dev-SNAPSHOT</version> |
||||
</parent> |
||||
<artifactId>dolphinscheduler-alert-prometheus</artifactId> |
||||
<packaging>jar</packaging> |
||||
|
||||
<dependencies> |
||||
<dependency> |
||||
<groupId>org.apache.dolphinscheduler</groupId> |
||||
<artifactId>dolphinscheduler-alert-api</artifactId> |
||||
</dependency> |
||||
<dependency> |
||||
<groupId>org.apache.httpcomponents</groupId> |
||||
<artifactId>httpclient</artifactId> |
||||
</dependency> |
||||
</dependencies> |
||||
</project> |
@ -0,0 +1,39 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
import org.apache.dolphinscheduler.alert.api.AlertChannel; |
||||
import org.apache.dolphinscheduler.alert.api.AlertData; |
||||
import org.apache.dolphinscheduler.alert.api.AlertInfo; |
||||
import org.apache.dolphinscheduler.alert.api.AlertResult; |
||||
|
||||
import java.util.Map; |
||||
|
||||
public final class PrometheusAlertChannel implements AlertChannel { |
||||
|
||||
@Override |
||||
public AlertResult process(AlertInfo info) { |
||||
AlertData alertData = info.getAlertData(); |
||||
Map<String, String> paramsMap = info.getAlertParams(); |
||||
if (null == paramsMap) { |
||||
return new AlertResult("false", "prometheus alert manager params is null"); |
||||
} |
||||
return new PrometheusAlertSender(paramsMap).sendMessage(alertData); |
||||
|
||||
} |
||||
} |
@ -0,0 +1,74 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
import org.apache.dolphinscheduler.alert.api.AlertChannel; |
||||
import org.apache.dolphinscheduler.alert.api.AlertChannelFactory; |
||||
import org.apache.dolphinscheduler.alert.api.AlertInputTips; |
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams; |
||||
import org.apache.dolphinscheduler.spi.params.base.Validate; |
||||
import org.apache.dolphinscheduler.spi.params.input.InputParam; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import com.google.auto.service.AutoService; |
||||
|
||||
@AutoService(AlertChannelFactory.class) |
||||
public final class PrometheusAlertChannelFactory implements AlertChannelFactory { |
||||
|
||||
@Override |
||||
public String name() { |
||||
return "Prometheus AlertManager"; |
||||
} |
||||
|
||||
@Override |
||||
public List<PluginParams> params() { |
||||
InputParam urlParam = |
||||
InputParam |
||||
.newBuilder(PrometheusAlertConstants.NAME_ALERT_MANAGER_URL, |
||||
PrometheusAlertConstants.ALERT_MANAGER_URL) |
||||
.setPlaceholder(AlertInputTips.URL.getMsg()) |
||||
.addValidate(Validate.newBuilder() |
||||
.setRequired(true) |
||||
.build()) |
||||
.build(); |
||||
InputParam annotationParam = |
||||
InputParam |
||||
.newBuilder(PrometheusAlertConstants.NAME_ALERT_MANAGER_ANNOTATIONS, |
||||
PrometheusAlertConstants.ALERT_MANAGER_ANNOTATIONS) |
||||
.setPlaceholder(AlertInputTips.ANNOTATION.getMsg()) |
||||
.addValidate(Validate.newBuilder() |
||||
.setRequired(false).build()) |
||||
.build(); |
||||
InputParam generatorUrlParam = |
||||
InputParam |
||||
.newBuilder(PrometheusAlertConstants.NAME_GENERATOR_URL, PrometheusAlertConstants.GENERATOR_URL) |
||||
.setPlaceholder(AlertInputTips.GENERATOR_URL.getMsg()) |
||||
.addValidate(Validate.newBuilder() |
||||
.setRequired(false).build()) |
||||
.build(); |
||||
|
||||
return Arrays.asList(urlParam, annotationParam, generatorUrlParam); |
||||
} |
||||
|
||||
@Override |
||||
public AlertChannel create() { |
||||
return new PrometheusAlertChannel(); |
||||
} |
||||
} |
@ -0,0 +1,30 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
public class PrometheusAlertConstants { |
||||
|
||||
static final String ALERT_MANAGER_URL = "$t('url')"; |
||||
static final String NAME_ALERT_MANAGER_URL = "url"; |
||||
static final String ALERT_MANAGER_ANNOTATIONS = "$t('annotations')"; |
||||
static final String NAME_ALERT_MANAGER_ANNOTATIONS = "annotations"; |
||||
static final String ALERT_V2_API_PATH = "/api/v2/alerts"; |
||||
static final String GENERATOR_URL = "$t('generatorURL')"; |
||||
static final String NAME_GENERATOR_URL = "generatorURL"; |
||||
static final String ALERT_SUCCESS = "alert success"; |
||||
} |
@ -0,0 +1,166 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
import org.apache.dolphinscheduler.alert.api.AlertData; |
||||
import org.apache.dolphinscheduler.alert.api.AlertResult; |
||||
import org.apache.dolphinscheduler.alert.api.HttpServiceRetryStrategy; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
|
||||
import org.apache.commons.collections4.CollectionUtils; |
||||
import org.apache.http.HttpEntity; |
||||
import org.apache.http.HttpStatus; |
||||
import org.apache.http.client.methods.CloseableHttpResponse; |
||||
import org.apache.http.client.methods.HttpPost; |
||||
import org.apache.http.entity.ContentType; |
||||
import org.apache.http.entity.StringEntity; |
||||
import org.apache.http.impl.client.CloseableHttpClient; |
||||
import org.apache.http.impl.client.HttpClients; |
||||
import org.apache.http.util.EntityUtils; |
||||
|
||||
import java.io.IOException; |
||||
import java.text.SimpleDateFormat; |
||||
import java.util.ArrayList; |
||||
import java.util.Date; |
||||
import java.util.HashMap; |
||||
import java.util.List; |
||||
import java.util.Map; |
||||
import java.util.Objects; |
||||
|
||||
import lombok.extern.slf4j.Slf4j; |
||||
|
||||
@Slf4j |
||||
public class PrometheusAlertSender { |
||||
|
||||
private String url; |
||||
private String generatorURL; |
||||
private String annotations; |
||||
|
||||
public PrometheusAlertSender(Map<String, String> config) { |
||||
url = config.get(PrometheusAlertConstants.NAME_ALERT_MANAGER_URL); |
||||
generatorURL = config.get(PrometheusAlertConstants.NAME_GENERATOR_URL); |
||||
annotations = config.get(PrometheusAlertConstants.NAME_ALERT_MANAGER_ANNOTATIONS); |
||||
} |
||||
|
||||
public AlertResult sendMessage(AlertData alertData) { |
||||
AlertResult alertResult; |
||||
try { |
||||
String resp = sendMsg(alertData); |
||||
return checkSendAlertManageMsgResult(resp); |
||||
} catch (Exception e) { |
||||
String errorMsg = String.format("send prometheus alert manager alert error, exception: %s", e.getMessage()); |
||||
log.error(errorMsg); |
||||
alertResult = new AlertResult(); |
||||
alertResult.setStatus("false"); |
||||
alertResult.setMessage(errorMsg); |
||||
} |
||||
return alertResult; |
||||
} |
||||
|
||||
private String sendMsg(AlertData alertData) throws IOException { |
||||
String v2Path = String.format("%s%s", this.url, PrometheusAlertConstants.ALERT_V2_API_PATH); |
||||
String msg = generateContentJson(alertData); |
||||
HttpPost httpPost = constructHttpPost(v2Path, msg); |
||||
|
||||
try (CloseableHttpClient httpClient = getDefaultClient()) { |
||||
try (CloseableHttpResponse response = httpClient.execute(httpPost)) { |
||||
String resp; |
||||
int statusCode = response.getStatusLine().getStatusCode(); |
||||
if (statusCode == HttpStatus.SC_OK) { |
||||
resp = PrometheusAlertConstants.ALERT_SUCCESS; |
||||
log.info("Prometheus alert manager send alert succeed, title: {} ,content: {}", |
||||
alertData.getTitle(), |
||||
alertData.getContent()); |
||||
return resp; |
||||
} |
||||
|
||||
HttpEntity entity = response.getEntity(); |
||||
resp = EntityUtils.toString(entity, "utf-8"); |
||||
EntityUtils.consume(entity); |
||||
log.error( |
||||
"Prometheus alert manager send alert failed, http status code: {}, title: {} ,content: {}, resp: {}", |
||||
statusCode, |
||||
alertData.getTitle(), |
||||
alertData.getContent(), resp); |
||||
|
||||
return resp; |
||||
} |
||||
} |
||||
} |
||||
|
||||
public AlertResult checkSendAlertManageMsgResult(String resp) { |
||||
AlertResult alertResult = new AlertResult(); |
||||
alertResult.setStatus("false"); |
||||
|
||||
if (Objects.equals(resp, PrometheusAlertConstants.ALERT_SUCCESS)) { |
||||
alertResult.setStatus("true"); |
||||
alertResult.setMessage("prometheus alert manager send success"); |
||||
return alertResult; |
||||
} |
||||
|
||||
alertResult.setMessage(String.format("prometheus alert manager send fail, resp is %s", resp)); |
||||
log.info("send prometheus alert manager msg error, resp error"); |
||||
return alertResult; |
||||
} |
||||
|
||||
public String generateContentJson(AlertData alertData) { |
||||
List<HashMap> list = JSONUtils.toList(alertData.getContent(), HashMap.class); |
||||
HashMap<String, String> labels = new HashMap<>(); |
||||
if (CollectionUtils.isEmpty(list)) { |
||||
labels.put("content", alertData.getContent()); |
||||
} |
||||
for (Map map : list) { |
||||
for (Map.Entry<String, Object> entry : (Iterable<Map.Entry<String, Object>>) map.entrySet()) { |
||||
String key = entry.getKey(); |
||||
String value = entry.getValue().toString(); |
||||
labels.put(key, value); |
||||
} |
||||
} |
||||
labels.put("title", alertData.getTitle()); |
||||
|
||||
Map<String, Object> alert = new HashMap<>(); |
||||
alert.put("labels", labels); |
||||
|
||||
Map<String, String> annotations = JSONUtils.toMap(this.annotations); |
||||
if (annotations != null) { |
||||
alert.put("annotations", annotations); |
||||
} |
||||
|
||||
String formattedTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'").format(new Date()); |
||||
alert.put("startsAt", formattedTime); |
||||
alert.put("endsAt", formattedTime); |
||||
|
||||
if (generatorURL != null && generatorURL.length() != 0) { |
||||
alert.put("generatorURL", generatorURL); |
||||
} |
||||
List<Map<String, Object>> body = new ArrayList<>(); |
||||
body.add(alert); |
||||
return JSONUtils.toJsonString(body); |
||||
} |
||||
|
||||
private static CloseableHttpClient getDefaultClient() { |
||||
return HttpClients.custom().setRetryHandler(HttpServiceRetryStrategy.retryStrategy).build(); |
||||
} |
||||
|
||||
private static HttpPost constructHttpPost(String url, String msg) { |
||||
HttpPost post = new HttpPost(url); |
||||
StringEntity entity = new StringEntity(msg, ContentType.APPLICATION_JSON); |
||||
post.setEntity(entity); |
||||
return post; |
||||
} |
||||
} |
@ -0,0 +1,45 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
import org.apache.dolphinscheduler.alert.api.AlertChannel; |
||||
import org.apache.dolphinscheduler.common.utils.JSONUtils; |
||||
import org.apache.dolphinscheduler.spi.params.base.PluginParams; |
||||
|
||||
import java.util.List; |
||||
|
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
public class PrometheusAlertFactoryTest { |
||||
|
||||
@Test |
||||
public void testGetParams() { |
||||
PrometheusAlertChannelFactory prometheusAlertChannelFactory = new PrometheusAlertChannelFactory(); |
||||
List<PluginParams> params = prometheusAlertChannelFactory.params(); |
||||
JSONUtils.toJsonString(params); |
||||
Assertions.assertEquals(3, params.size()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCreate() { |
||||
PrometheusAlertChannelFactory prometheusAlertChannelFactory = new PrometheusAlertChannelFactory(); |
||||
AlertChannel alertChannel = prometheusAlertChannelFactory.create(); |
||||
Assertions.assertNotNull(alertChannel); |
||||
} |
||||
} |
@ -0,0 +1,71 @@
|
||||
/* |
||||
* Licensed to the Apache Software Foundation (ASF) under one or more |
||||
* contributor license agreements. See the NOTICE file distributed with |
||||
* this work for additional information regarding copyright ownership. |
||||
* The ASF licenses this file to You under the Apache License, Version 2.0 |
||||
* (the "License"); you may not use this file except in compliance with |
||||
* the License. You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.apache.dolphinscheduler.plugin.alert.prometheus; |
||||
|
||||
import org.apache.dolphinscheduler.alert.api.AlertData; |
||||
import org.apache.dolphinscheduler.alert.api.AlertResult; |
||||
|
||||
import java.util.HashMap; |
||||
import java.util.Map; |
||||
|
||||
import org.junit.jupiter.api.AfterEach; |
||||
import org.junit.jupiter.api.Assertions; |
||||
import org.junit.jupiter.api.BeforeEach; |
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
public class PrometheusAlertSenderTest { |
||||
|
||||
private static Map<String, String> config = new HashMap<>(); |
||||
|
||||
@BeforeEach |
||||
public void initConfig() { |
||||
config.put(PrometheusAlertConstants.NAME_ALERT_MANAGER_URL, "http://127.0.0.1:9093"); |
||||
config.put(PrometheusAlertConstants.NAME_GENERATOR_URL, "localhost:8080"); |
||||
config.put(PrometheusAlertConstants.NAME_ALERT_MANAGER_ANNOTATIONS, "{\"annotation1\": \"string\"," + |
||||
" \"annotation2\": \"string\"}"); |
||||
} |
||||
|
||||
@AfterEach |
||||
public void resetConfig() { |
||||
config = new HashMap<>(); |
||||
} |
||||
|
||||
@Test |
||||
public void testSendAlert() { |
||||
AlertData alertData = new AlertData(); |
||||
alertData.setTitle("[alertManager alert] test title"); |
||||
alertData.setContent("[{\n" + |
||||
" \"additionalProp1\": \"string\",\n" + |
||||
" \"additionalProp2\": \"string\",\n" + |
||||
" }]"); |
||||
PrometheusAlertSender sender = new PrometheusAlertSender(config); |
||||
AlertResult result = sender.sendMessage(alertData); |
||||
Assertions.assertEquals("false", result.getStatus()); |
||||
} |
||||
|
||||
@Test |
||||
public void testCheckSendAlertManageMsgResult() { |
||||
PrometheusAlertSender prometheusAlertSender = new PrometheusAlertSender(config); |
||||
AlertResult alertResult1 = prometheusAlertSender.checkSendAlertManageMsgResult(""); |
||||
Assertions.assertFalse(Boolean.parseBoolean(alertResult1.getStatus())); |
||||
Assertions.assertEquals("prometheus alert manager send fail, resp is ", alertResult1.getMessage()); |
||||
AlertResult alertResult2 = prometheusAlertSender.checkSendAlertManageMsgResult("alert success"); |
||||
Assertions.assertTrue(Boolean.parseBoolean(alertResult2.getStatus())); |
||||
Assertions.assertEquals("prometheus alert manager send success", alertResult2.getMessage()); |
||||
} |
||||
} |
Loading…
Reference in new issue