From 933ae20b1cdd9d2772b7a841717a9acd1c3defdb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=99=9F=20Wu=20Sheng?= Date: Tue, 25 Sep 2018 20:23:36 +0800 Subject: [PATCH] Alarm module code core ready (#1644) * Support alarm message. * Fix document words. * Support alarm hook. * Fix javadoc issue. * Sync submodule * Sync submodule --- .../trace-ignore-plugin/README.md | 17 --- .../trace-ignore-plugin/README_CN.md | 18 --- .../trace-ignore-plugin/pom.xml | 29 ----- .../setup/service-agent/java-agent/README.md | 2 +- .../trace-ignore-plugin.md | 6 +- .../alarm/provider/AlarmMessageFormatter.java | 97 ++++++++++++++ .../server/core/alarm/provider/AlarmRule.java | 1 + .../core/alarm/provider/RulesReader.java | 1 + .../core/alarm/provider/RunningRule.java | 13 +- .../core/alarm/provider/WebhookCallback.java | 61 +++++++++ .../provider/AlarmMessageFormatterTest.java | 83 ++++++++++++ .../alarm/provider/AlarmRuleInitTest.java | 3 + .../core/alarm/provider/RunningRuleTest.java | 12 +- .../alarm/provider/WebhookCallbackTest.java | 122 ++++++++++++++++++ .../src/test/resources/alarm-settings.yml | 1 + .../oap/server/core/alarm/AlarmMessage.java | 7 + 16 files changed, 399 insertions(+), 74 deletions(-) delete mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/README.md delete mode 100644 apm-sniffer/optional-plugins/trace-ignore-plugin/README_CN.md create mode 100644 oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatter.java create mode 100644 oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatterTest.java create mode 100644 oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallbackTest.java diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md b/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md deleted file mode 100644 index 89195e48c..000000000 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/README.md +++ /dev/null @@ -1,17 +0,0 @@ -## Support custom trace ignore -Here is an optional plugin `apm-trace-ignore-plugin` - -## Introduce -- The purpose of this plugin is to filter custom services which are expected to ignore from the tracing system. -- You can set up multiple URL path patterns, The services matches these patterns means won't be traced and analysis by agent and collector. -- The current matching rule follows `Ant Path` match style , like `/path/*`, `/path/**`, `/path/?`. -- Copy `apm-trace-ignore-plugin-x.jar` to `agent/plugins`, restarting the `agent` can effect the plugin. - -## How to configure -There are two ways to configure ignore patterns. Settings through system env has higher priority. - 1. Set through the system environment variable,you need to add `skywalking.trace.ignore_path` to the system variables, the value is the path that you need to ignore, multiple paths should be separated by `,` - 2. Copy`/agent/optional-plugins/apm-trace-ignore-plugin/apm-trace-ignore-plugin.config` to `/agent/config/` dir, and add rules to filter traces -``` -trace.ignore_path=/your/path/1/**,/your/path/2/** -``` - diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/README_CN.md b/apm-sniffer/optional-plugins/trace-ignore-plugin/README_CN.md deleted file mode 100644 index 3a21bec87..000000000 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/README_CN.md +++ /dev/null @@ -1,18 +0,0 @@ -## 个性化服务过滤 -提供了一个可选插件 `apm-trace-ignore-plugin` - -## 介绍 -- 这个插件的作用是对追踪的个性化服务过滤. -- 你可以设置多个需要忽略的URL路径, 意味着包含这些路径的`追踪信息`不会被`agent`发送到 `collector`. -- 当前的路径匹配规则是 `Ant Path`匹配风格 , 例如 `/path/*`, `/path/**`, `/path/?`. -- 将`apm-trace-ignore-plugin-x.jar`拷贝到`agent/plugins`后,重启探针即可生效 -- [Skywalking-使用可选插件 apm-trace-ignore-plugin](https://blog.csdn.net/u013095337/article/details/80452088) 有详细使用介绍 - -## 如何配置路径 -有两种配置方式,可使用任意一种,配置生效的优先级从高到低 - 1. 在系统环境变量中配置,你需要在系统变量中添加`skywalking.trace.ignore_path`, 值是你需要忽略的路径,多个以`,`号分隔 - 2. 将`/agent/optional-plugins/apm-trace-ignore-plugin/apm-trace-ignore-plugin.config` 复制或剪切到 `/agent/config/` 目录下,加上配置 -``` -trace.ignore_path=/your/path/1/**,/your/path/2/** -``` - diff --git a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml index 7f2701c3d..ac0fee74c 100644 --- a/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml +++ b/apm-sniffer/optional-plugins/trace-ignore-plugin/pom.xml @@ -30,33 +30,4 @@ apm-trace-ignore-plugin http://maven.apache.org - - - - - maven-antrun-plugin - - - package - - run - - - - - - - - - - - - - - - - - - - diff --git a/docs/en/setup/service-agent/java-agent/README.md b/docs/en/setup/service-agent/java-agent/README.md index 3d8641d4e..135227780 100644 --- a/docs/en/setup/service-agent/java-agent/README.md +++ b/docs/en/setup/service-agent/java-agent/README.md @@ -53,7 +53,7 @@ For using these plugins, you need to compile source codes by yourself, or copy t Now, we have the following known plugins. * [Trace Spring beans](agent-optional-plugins/Spring-bean-plugins.md) * [Trace Oracle and Resin](agent-optional-plugins/Oracle-Resin-plugins.md) -* [Filter traces through custom services](agent-optional-plugins/trace-ignore-plugin.md) +* [Filter traces through specified endpoint name patterns](agent-optional-plugins/trace-ignore-plugin.md) ## Advanced Features * Set the settings through system properties for config file override. Read [setting override](Setting-override.md). diff --git a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md index 89195e48c..6da90cf83 100644 --- a/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md +++ b/docs/en/setup/service-agent/java-agent/agent-optional-plugins/trace-ignore-plugin.md @@ -2,9 +2,9 @@ Here is an optional plugin `apm-trace-ignore-plugin` ## Introduce -- The purpose of this plugin is to filter custom services which are expected to ignore from the tracing system. -- You can set up multiple URL path patterns, The services matches these patterns means won't be traced and analysis by agent and collector. -- The current matching rule follows `Ant Path` match style , like `/path/*`, `/path/**`, `/path/?`. +- The purpose of this plugin is to filter endpoint which are expected to be ignored by the tracing system. +- You can setup multiple URL path patterns, The endpoints match these patterns wouldn't be traced. +- The current matching rules follow `Ant Path` match style , like `/path/*`, `/path/**`, `/path/?`. - Copy `apm-trace-ignore-plugin-x.jar` to `agent/plugins`, restarting the `agent` can effect the plugin. ## How to configure diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatter.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatter.java new file mode 100644 index 000000000..a209b0cb8 --- /dev/null +++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatter.java @@ -0,0 +1,97 @@ +/* + * 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.skywalking.oap.server.core.alarm.provider; + +import java.util.ArrayList; +import java.util.List; +import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm; + +/** + * This is a formatter especially for alarm message. + * + * Format string in alarm-settings.yml, such as: + * + * - Successful rate of endpoint {name} is lower than 75% + * + * @author wusheng + */ +public class AlarmMessageFormatter { + private List formatSegments; + private List valueFroms; + + public AlarmMessageFormatter(String format) { + if (format == null) { + format = ""; + } + formatSegments = new ArrayList<>(); + this.valueFroms = new ArrayList<>(); + boolean match = false; + int idx = 0; + do { + match = false; + int start = format.indexOf("{", idx); + if (start > -1) { + int end = format.indexOf("}", start); + if (end > -1) { + + String name = format.substring(start + 1, end); + switch (name) { + case "id": + valueFroms.add(ValueFrom.ID); + break; + case "name": + valueFroms.add(ValueFrom.NAME); + break; + default: + throw new IllegalArgumentException("Var [" + name + "] in alarm message [" + format + "] is illegal"); + } + formatSegments.add(format.substring(idx, start)); + idx = end + 1; + match = true; + } + } + + if (!match) { + formatSegments.add(format.substring(idx)); + } + } + while (match); + } + + public String format(MetaInAlarm meta) { + StringBuilder message = new StringBuilder(); + for (int i = 0; i < formatSegments.size(); i++) { + message.append(formatSegments.get(i)); + if (i != formatSegments.size() - 1) { + switch (valueFroms.get(i)) { + case ID: + message.append(meta.getId0()); + break; + case NAME: + message.append(meta.getName()); + } + } + } + return message.toString(); + } + + private enum ValueFrom { + ID, NAME + } +} diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java index 7f3e1dce4..03f299f8d 100644 --- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java +++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRule.java @@ -38,4 +38,5 @@ public class AlarmRule { private int period; private int count; private int silencePeriod; + private String message; } diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java index 77de2e507..e2a28736c 100644 --- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java +++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReader.java @@ -66,6 +66,7 @@ public class RulesReader { alarmRule.setPeriod((Integer)settings.getOrDefault("period", 1)); alarmRule.setCount((Integer)settings.getOrDefault("count", 1)); alarmRule.setSilencePeriod((Integer)settings.getOrDefault("silence-period", alarmRule.getPeriod())); + alarmRule.setMessage((String)settings.getOrDefault("message", "Alarm caused by Rule " + alarmRule.getAlarmRuleName())); rules.getRules().add(alarmRule); } diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java index 872d5a24a..f2a96fa32 100644 --- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java +++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRule.java @@ -58,6 +58,7 @@ public class RunningRule { private volatile IndicatorValueType valueType; private Scope targetScope; private List includeNames; + private AlarmMessageFormatter formatter; public RunningRule(AlarmRule alarmRule) { indicatorName = alarmRule.getIndicatorName(); @@ -75,6 +76,7 @@ public class RunningRule { this.silencePeriod = alarmRule.getSilencePeriod(); this.includeNames = alarmRule.getIncludeNames(); + this.formatter = new AlarmMessageFormatter(alarmRule.getMessage()); } /** @@ -136,9 +138,16 @@ public class RunningRule { public List check() { List alarmMessageList = new ArrayList<>(30); - windows.values().forEach(window -> { + windows.entrySet().forEach(entry -> { + MetaInAlarm meta = entry.getKey(); + Window window = entry.getValue(); AlarmMessage alarmMessage = window.checkAlarm(); if (alarmMessage != AlarmMessage.NONE) { + alarmMessage.setScope(meta.getScope()); + alarmMessage.setName(meta.getName()); + alarmMessage.setId0(meta.getId0()); + alarmMessage.setId1(meta.getId1()); + alarmMessage.setAlarmMessage(formatter.format(meta)); alarmMessageList.add(alarmMessage); } }); @@ -238,7 +247,7 @@ public class RunningRule { if (counter >= countThreshold && silenceCountdown < 1) { silenceCountdown = silencePeriod; - //TODO + // set empty message, but new message AlarmMessage message = new AlarmMessage(); return message; } else { diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallback.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallback.java index 7655b4229..582bc4f23 100644 --- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallback.java +++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallback.java @@ -18,21 +18,82 @@ package org.apache.skywalking.oap.server.core.alarm.provider; +import com.google.gson.Gson; +import java.io.IOException; +import java.io.UnsupportedEncodingException; import java.util.List; +import org.apache.http.StatusLine; +import org.apache.http.client.ClientProtocolException; +import org.apache.http.client.config.RequestConfig; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; import org.apache.skywalking.oap.server.core.alarm.AlarmCallback; import org.apache.skywalking.oap.server.core.alarm.AlarmMessage; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * Use SkyWalking alarm webhook API call a remote endpoints. + * + * @author wusheng */ public class WebhookCallback implements AlarmCallback { + private static final Logger logger = LoggerFactory.getLogger(WebhookCallback.class); + private static final int HTTP_CONNECT_TIMEOUT = 1000; + private static final int HTTP_CONNECTION_REQUEST_TIMEOUT = 1000; + private static final int HTTP_SOCKET_TIMEOUT = 10000; + private List remoteEndpoints; + private RequestConfig requestConfig; + private Gson gson = new Gson(); public WebhookCallback(List remoteEndpoints) { this.remoteEndpoints = remoteEndpoints; + requestConfig = RequestConfig.custom() + .setConnectTimeout(HTTP_CONNECT_TIMEOUT) + .setConnectionRequestTimeout(HTTP_CONNECTION_REQUEST_TIMEOUT) + .setSocketTimeout(HTTP_SOCKET_TIMEOUT).build(); } @Override public void doAlarm(List alarmMessage) { + if (remoteEndpoints.size() == 0) { + return; + } + + CloseableHttpClient httpClient = HttpClients.custom().build(); + try { + remoteEndpoints.forEach(url -> { + HttpPost post = new HttpPost(url); + post.setConfig(requestConfig); + post.setHeader("Accept", "application/json"); + post.setHeader("Content-type", "application/json"); + StringEntity entity = null; + try { + entity = new StringEntity(gson.toJson(alarmMessage)); + post.setEntity(entity); + CloseableHttpResponse httpResponse = httpClient.execute(post); + StatusLine statusLine = httpResponse.getStatusLine(); + if (statusLine != null && statusLine.getStatusCode() != 200) { + logger.error("send alarm to " + url + " failure. Response code: " + statusLine.getStatusCode()); + } + } catch (UnsupportedEncodingException e) { + logger.error("Alarm to JSON error, " + e.getMessage(), e); + } catch (ClientProtocolException e) { + logger.error("send alarm to " + url + " failure.", e); + } catch (IOException e) { + logger.error("send alarm to " + url + " failure.", e); + } + }); + } finally { + try { + httpClient.close(); + } catch (IOException e) { + logger.error(e.getMessage(), e); + } + } } } diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatterTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatterTest.java new file mode 100644 index 000000000..02a3699ca --- /dev/null +++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmMessageFormatterTest.java @@ -0,0 +1,83 @@ +/* + * 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.skywalking.oap.server.core.alarm.provider; + +import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm; +import org.apache.skywalking.oap.server.core.source.Scope; +import org.junit.Assert; +import org.junit.Test; + +public class AlarmMessageFormatterTest { + @Test + public void testStringFormatWithNoArg() { + AlarmMessageFormatter formatter = new AlarmMessageFormatter("abc words {sdf"); + String message = formatter.format(new MetaInAlarm() { + + @Override public Scope getScope() { + return null; + } + + @Override public String getName() { + return null; + } + + @Override public String getIndicatorName() { + return null; + } + + @Override public int getId0() { + return 0; + } + + @Override public int getId1() { + return 0; + } + }); + + Assert.assertEquals("abc words {sdf", message); + } + + @Test + public void testStringFormatWithArg() { + AlarmMessageFormatter formatter = new AlarmMessageFormatter("abc} words {name} - {id} .. {"); + String message = formatter.format(new MetaInAlarm() { + + @Override public Scope getScope() { + return null; + } + + @Override public String getName() { + return "service"; + } + + @Override public String getIndicatorName() { + return null; + } + + @Override public int getId0() { + return 1290; + } + + @Override public int getId1() { + return 0; + } + }); + Assert.assertEquals("abc} words service - 1290 .. {", message); + } +} diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleInitTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleInitTest.java index 09aeae68b..debcf5cfb 100644 --- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleInitTest.java +++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleInitTest.java @@ -34,11 +34,14 @@ public class AlarmRuleInitTest { Assert.assertEquals("85", ruleList.get(1).getThreshold()); Assert.assertEquals("endpoint_percent_rule", ruleList.get(0).getAlarmRuleName()); Assert.assertEquals(0, ruleList.get(0).getIncludeNames().size()); + Assert.assertEquals("Successful rate of endpoint {name} is lower than 75%", ruleList.get(0).getMessage()); Assert.assertEquals("service_b", ruleList.get(1).getIncludeNames().get(1)); + Assert.assertEquals("Alarm caused by Rule service_percent_rule", ruleList.get(1).getMessage()); List rulesWebhooks = rules.getWebhooks(); Assert.assertEquals(2, rulesWebhooks.size()); Assert.assertEquals("http://127.0.0.1/go-wechat/", rulesWebhooks.get(1)); + } } diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRuleTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRuleTest.java index 12121df45..336e6df70 100644 --- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRuleTest.java +++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RunningRuleTest.java @@ -82,6 +82,7 @@ public class RunningRuleTest { alarmRule.setThreshold("75"); alarmRule.setCount(3); alarmRule.setPeriod(15); + alarmRule.setMessage("Successful rate of endpoint {name} is lower than 75%"); RunningRule runningRule = new RunningRule(alarmRule); LocalDateTime startTime = TIME_BUCKET_FORMATTER.parseLocalDateTime("201808301440"); @@ -95,14 +96,17 @@ public class RunningRuleTest { runningRule.in(getMetaInAlarm(123), getIndicator(timeInPeriod3, 74)); // check at 201808301440 - Assert.assertEquals(0, runningRule.check().size()); + List alarmMessages = runningRule.check(); + Assert.assertEquals(0, alarmMessages.size()); runningRule.moveTo(TIME_BUCKET_FORMATTER.parseLocalDateTime("201808301441")); // check at 201808301441 - Assert.assertEquals(0, runningRule.check().size()); + alarmMessages = runningRule.check(); + Assert.assertEquals(0, alarmMessages.size()); runningRule.moveTo(TIME_BUCKET_FORMATTER.parseLocalDateTime("201808301442")); // check at 201808301442 - Assert.assertEquals(1, runningRule.check().size()); - + alarmMessages = runningRule.check(); + Assert.assertEquals(1, alarmMessages.size()); + Assert.assertEquals("Successful rate of endpoint Service_123 is lower than 75%", alarmMessages.get(0).getAlarmMessage()); } @Test diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallbackTest.java new file mode 100644 index 000000000..961acf775 --- /dev/null +++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/WebhookCallbackTest.java @@ -0,0 +1,122 @@ +/* + * 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.skywalking.oap.server.core.alarm.provider; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.InetSocketAddress; +import java.util.ArrayList; +import java.util.List; +import javax.servlet.Servlet; +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.ServletRequest; +import javax.servlet.ServletResponse; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import org.apache.skywalking.oap.server.core.alarm.AlarmMessage; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.servlet.ServletContextHandler; +import org.eclipse.jetty.servlet.ServletHolder; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +public class WebhookCallbackTest implements Servlet { + private Server server; + private volatile boolean isSuccess = false; + + @Before + public void init() throws Exception { + server = new Server(new InetSocketAddress("127.0.0.1", 8778)); + ServletContextHandler servletContextHandler = new ServletContextHandler(ServletContextHandler.NO_SESSIONS); + servletContextHandler.setContextPath("/webhook"); + + server.setHandler(servletContextHandler); + + ServletHolder servletHolder = new ServletHolder(); + servletHolder.setServlet(this); + servletContextHandler.addServlet(servletHolder, "/receiveAlarm"); + + server.start(); + } + + @After + public void stop() throws Exception { + server.stop(); + } + + @Test + public void testWebhook() { + List remoteEndpoints = new ArrayList<>(); + remoteEndpoints.add("http://127.0.0.1:8778/webhook/receiveAlarm"); + WebhookCallback webhookCallback = new WebhookCallback(remoteEndpoints); + List alarmMessages = new ArrayList<>(2); + alarmMessages.add(new AlarmMessage()); + alarmMessages.add(new AlarmMessage()); + webhookCallback.doAlarm(alarmMessages); + + Assert.assertTrue(isSuccess); + } + + @Override public void init(ServletConfig config) throws ServletException { + + } + + @Override public ServletConfig getServletConfig() { + return null; + } + + @Override + public void service(ServletRequest request, ServletResponse response) throws ServletException, IOException { + HttpServletRequest httpServletRequest = (HttpServletRequest)request; + if (httpServletRequest.getContentType().equals("application/json")) { + InputStream inputStream = request.getInputStream(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + byte[] buffer = new byte[2048]; + int readCntOnce; + + while ((readCntOnce = inputStream.read(buffer)) >= 0) { + out.write(buffer, 0, readCntOnce); + } + + JsonArray elements = new Gson().fromJson(new String(out.toByteArray()), JsonArray.class); + if (elements.size() == 2) { + ((HttpServletResponse)response).setStatus(200); + isSuccess = true; + return; + } + + ((HttpServletResponse)response).setStatus(500); + } + } + + @Override public String getServletInfo() { + return null; + } + + @Override public void destroy() { + + } + +} diff --git a/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml b/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml index 7fce7f413..a39264861 100644 --- a/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml +++ b/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml @@ -27,6 +27,7 @@ rules: count: 3 # How many times of checks, the alarm keeps silence after alarm triggered, default as same as period. silence-period: 10 + message: Successful rate of endpoint {name} is lower than 75% service_percent_rule: indicator-name: service_percent # [Optional] Default, match all services in this indicator diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMessage.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMessage.java index 7a8f28eb4..c0ab5b0e4 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMessage.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/alarm/AlarmMessage.java @@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.alarm; import lombok.AccessLevel; import lombok.Getter; import lombok.Setter; +import org.apache.skywalking.oap.server.core.source.Scope; /** * Alarm message represents the details of each alarm. @@ -32,6 +33,12 @@ import lombok.Setter; public class AlarmMessage { public static AlarmMessage NONE = new NoAlarm(); + private Scope scope; + private String name; + private int id0; + private int id1; + private String alarmMessage; + private static class NoAlarm extends AlarmMessage { } -- GitLab