You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ta...@apache.org on 2020/02/10 09:42:47 UTC

[skywalking] 01/02: support gRPC hook.

This is an automated email from the ASF dual-hosted git repository.

tanjian pushed a commit to branch grpc_alarm
in repository https://gitbox.apache.org/repos/asf/skywalking.git

commit 788a416b90e721cfffc300023ebd1ff05c50d6d8
Author: JaredTan95 <ji...@daocloud.io>
AuthorDate: Mon Feb 10 17:37:55 2020 +0800

    support gRPC hook.
---
 docs/en/setup/backend/backend-alarm.md             |  19 ++++
 oap-server/server-alarm-plugin/pom.xml             |  34 +++++++
 .../core/alarm/provider/AlarmRulesWatcher.java     |  21 +++--
 .../server/core/alarm/provider/NotifyHandler.java  |   2 +
 .../oap/server/core/alarm/provider/Rules.java      |   2 +
 .../server/core/alarm/provider/RulesReader.java    |  29 +++++-
 .../{Rules.java => grpc/GRPCAlarmSetting.java}     |  25 +++--
 .../core/alarm/provider/grpc/GRPCCallback.java     | 102 +++++++++++++++++++++
 .../provider/Rules.java => proto/alarm-hook.proto} |  32 ++++---
 .../core/alarm/provider/AlarmRulesWatcherTest.java |  13 ++-
 .../alarm/provider/grpc/AlarmMockReceiver.java     |  73 +++++++++++++++
 .../alarm/provider/grpc/GRPChookCallbackTest.java  |  72 +++++++++++++++
 .../src/test/resources/alarm-settings.yml          |   4 +
 .../src/main/resources/alarm-settings.yml          |   4 +
 14 files changed, 388 insertions(+), 44 deletions(-)

diff --git a/docs/en/setup/backend/backend-alarm.md b/docs/en/setup/backend/backend-alarm.md
index d277958..2787f95 100644
--- a/docs/en/setup/backend/backend-alarm.md
+++ b/docs/en/setup/backend/backend-alarm.md
@@ -3,6 +3,7 @@ Alarm core is driven by a collection of rules, which are defined in `config/alar
 There are two parts in alarm rule definition.
 1. [Alarm rules](#rules). They define how metrics alarm should be triggered, what conditions should be considered.
 1. [Webhooks](#webhook). The list of web service endpoint, which should be called after the alarm is triggered.
+1. [gRPCHook](#gRPCHook). The host and port of remote gRPC method, which should be called after the alarm is triggered.
 
 ## Rules
 Alarm rule is constituted by following keys
@@ -113,6 +114,24 @@ Example as following
 }]
 ```
 
+## gRPCHook
+The alarm message will send through remote gRPC method by `Protobuf` content type. 
+The message format with following key information which are defined in `oap-server/server-alarm-plugin/src/main/proto/alarm-hook.proto`.
+
+Example as following
+```text
+message AlarmMessage {
+    int64 scopeId = 1;
+    string scope = 2;
+    string name = 3;
+    int64 id0 = 4;
+    int64 id1 = 5;
+    string ruleName = 6;
+    string alarmMessage = 7;
+    int64 startTime = 8;
+}
+```
+
 ## Update the settings dynamically
 Since 6.5.0, the alarm settings can be updated dynamically at runtime by [Dynamic Configuration](dynamic-config.md),
 which will override the settings in `alarm-settings.yml`.
diff --git a/oap-server/server-alarm-plugin/pom.xml b/oap-server/server-alarm-plugin/pom.xml
index 362902d..24fe8bf 100644
--- a/oap-server/server-alarm-plugin/pom.xml
+++ b/oap-server/server-alarm-plugin/pom.xml
@@ -26,6 +26,7 @@
     <modelVersion>4.0.0</modelVersion>
 
     <artifactId>server-alarm-plugin</artifactId>
+
     <dependencies>
         <dependency>
             <groupId>org.apache.skywalking</groupId>
@@ -37,7 +38,40 @@
             <artifactId>library-util</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>io.grpc</groupId>
+            <artifactId>grpc-testing</artifactId>
+        </dependency>
     </dependencies>
 
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.xolstice.maven.plugins</groupId>
+                <artifactId>protobuf-maven-plugin</artifactId>
+                <version>${protobuf-maven-plugin.version}</version>
+                <configuration>
+                    <!--
+                      The version of protoc must match protobuf-java. If you don't depend on
+                      protobuf-java directly, you will be transitively depending on the
+                      protobuf-java version that grpc depends on.
+                    -->
+                    <protocArtifact>com.google.protobuf:protoc:${com.google.protobuf.protoc.version}:exe:${os.detected.classifier}
+                    </protocArtifact>
+                    <pluginId>grpc-java</pluginId>
+                    <pluginArtifact>io.grpc:protoc-gen-grpc-java:${protoc-gen-grpc-java.plugin.version}:exe:${os.detected.classifier}
+                    </pluginArtifact>
+                </configuration>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>compile</goal>
+                            <goal>compile-custom</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>
+    </build>
 
 </project>
\ No newline at end of file
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java
index abfecc9..513eff3 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcher.java
@@ -18,22 +18,21 @@
 
 package org.apache.skywalking.oap.server.core.alarm.provider;
 
-import lombok.Getter;
-import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
-import org.apache.skywalking.oap.server.core.Const;
-import org.apache.skywalking.oap.server.core.alarm.AlarmModule;
-import org.apache.skywalking.oap.server.library.module.ModuleProvider;
-
 import java.io.StringReader;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import lombok.Getter;
+import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.alarm.AlarmModule;
+import org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting;
+import org.apache.skywalking.oap.server.library.module.ModuleProvider;
 
 /**
- * Alarm rules' settings can be dynamically updated via configuration center(s),
- * this class is responsible for monitoring the configuration and parsing them
- * into {@link Rules} and {@link #runningContext}.
+ * Alarm rules' settings can be dynamically updated via configuration center(s), this class is responsible for
+ * monitoring the configuration and parsing them into {@link Rules} and {@link #runningContext}.
  *
  * @author kezhenxu94
  * @since 6.5.0
@@ -104,4 +103,8 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
     public List<String> getWebHooks() {
         return this.rules.getWebhooks();
     }
+
+    public GRPCAlarmSetting getGrpchookSetting() {
+        return this.rules.getGrpchookSetting();
+    }
 }
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java
index 8fbedcb..8b72fb4 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandler.java
@@ -21,6 +21,7 @@ package org.apache.skywalking.oap.server.core.alarm.provider;
 import java.util.*;
 import org.apache.skywalking.oap.server.core.CoreModule;
 import org.apache.skywalking.oap.server.core.alarm.*;
+import org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCCallback;
 import org.apache.skywalking.oap.server.core.analysis.metrics.*;
 import org.apache.skywalking.oap.server.core.cache.*;
 import org.apache.skywalking.oap.server.core.register.*;
@@ -97,6 +98,7 @@ public class NotifyHandler implements MetricsNotify {
     public void init(AlarmCallback... callbacks) {
         List<AlarmCallback> allCallbacks = new ArrayList<>(Arrays.asList(callbacks));
         allCallbacks.add(new WebhookCallback(alarmRulesWatcher));
+        allCallbacks.add(new GRPCCallback(alarmRulesWatcher));
         core.start(allCallbacks);
     }
 
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
index e7a2e34..872ef44 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
@@ -20,12 +20,14 @@ package org.apache.skywalking.oap.server.core.alarm.provider;
 
 import java.util.*;
 import lombok.*;
+import org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting;
 
 @Setter(AccessLevel.PUBLIC)
 @Getter(AccessLevel.PUBLIC)
 public class Rules {
     private List<AlarmRule> rules;
     private List<String> webhooks;
+    private GRPCAlarmSetting grpchookSetting;
 
     public Rules() {
         this.rules = new ArrayList<>();
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 74fb9da..97cbd69 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
@@ -18,8 +18,13 @@
 
 package org.apache.skywalking.oap.server.core.alarm.provider;
 
-import java.io.*;
-import java.util.*;
+import java.io.InputStream;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import org.apache.skywalking.oap.server.core.alarm.provider.grpc.GRPCAlarmSetting;
 import org.yaml.snakeyaml.Yaml;
 
 /**
@@ -74,9 +79,23 @@ public class RulesReader {
             List webhooks = (List)yamlData.get("webhooks");
             if (webhooks != null) {
                 rules.setWebhooks(new ArrayList<>());
-                webhooks.forEach(url -> {
-                    rules.getWebhooks().add((String)url);
-                });
+                webhooks.forEach(url -> rules.getWebhooks().add((String)url));
+            }
+
+            Map grpchooks = (Map)yamlData.get("gRPCHook");
+            if (grpchooks != null) {
+                GRPCAlarmSetting grpcAlarmSetting = new GRPCAlarmSetting();
+                Object targetHost = grpchooks.get("target_host");
+                if (targetHost != null) {
+                    grpcAlarmSetting.setTargetHost((String)targetHost);
+                }
+
+                Object targetPort = grpchooks.get("target_port");
+                if (targetPort != null) {
+                    grpcAlarmSetting.setTargetPort((Integer)targetPort);
+                }
+
+                rules.setGrpchookSetting(grpcAlarmSetting);
             }
         }
 
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCAlarmSetting.java
similarity index 69%
copy from oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
copy to oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCAlarmSetting.java
index e7a2e34..f8a0361 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCAlarmSetting.java
@@ -16,19 +16,18 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.alarm.provider;
+package org.apache.skywalking.oap.server.core.alarm.provider.grpc;
 
-import java.util.*;
-import lombok.*;
+import lombok.Getter;
+import lombok.Setter;
+import org.apache.skywalking.oap.server.library.module.ModuleConfig;
 
-@Setter(AccessLevel.PUBLIC)
-@Getter(AccessLevel.PUBLIC)
-public class Rules {
-    private List<AlarmRule> rules;
-    private List<String> webhooks;
-
-    public Rules() {
-        this.rules = new ArrayList<>();
-        this.webhooks = new ArrayList<>();
-    }
+/**
+ * @author jian.tan
+ */
+@Setter
+@Getter
+public class GRPCAlarmSetting extends ModuleConfig {
+    private String targetHost;
+    private int targetPort;
 }
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCCallback.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCCallback.java
new file mode 100644
index 0000000..d69f732
--- /dev/null
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPCCallback.java
@@ -0,0 +1,102 @@
+/*
+ * 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.grpc;
+
+import io.grpc.stub.StreamObserver;
+import java.util.List;
+import java.util.concurrent.TimeUnit;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.alarm.AlarmCallback;
+import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
+import org.apache.skywalking.oap.server.core.alarm.grpc.AlarmServiceGrpc;
+import org.apache.skywalking.oap.server.core.alarm.grpc.Response;
+import org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher;
+import org.apache.skywalking.oap.server.library.client.grpc.GRPCClient;
+
+/**
+ * Use SkyWalking alarm grpc API call a remote methods.
+ *
+ * @author jian.tan
+ */
+@Slf4j
+public class GRPCCallback implements AlarmCallback {
+
+    GRPCAlarmSetting alarmSetting;
+
+    private AlarmServiceGrpc.AlarmServiceStub alarmServiceStub;
+
+    public GRPCCallback(AlarmRulesWatcher alarmRulesWatcher) {
+        alarmSetting = alarmRulesWatcher.getGrpchookSetting();
+        if (alarmSetting != null) {
+            GRPCClient client = new GRPCClient(alarmSetting.getTargetHost(), alarmSetting.getTargetPort());
+            client.connect();
+            alarmServiceStub = AlarmServiceGrpc.newStub(client.getChannel());
+        }
+    }
+
+    @Override public void doAlarm(List<AlarmMessage> alarmMessage) {
+
+        if (alarmServiceStub == null) {
+            return;
+        }
+
+        StreamObserver<org.apache.skywalking.oap.server.core.alarm.grpc.AlarmMessage> streamObserver =
+            alarmServiceStub.withDeadlineAfter(10, TimeUnit.SECONDS).doAlarm(new StreamObserver<Response>() {
+                @Override public void onNext(Response response) {
+
+                }
+
+                @Override public void onError(Throwable throwable) {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Send alarm message failed: {}", throwable.getMessage());
+                    }
+
+                }
+
+                @Override public void onCompleted() {
+                    if (log.isDebugEnabled()) {
+                        log.debug("Send alarm message successful.");
+                    }
+                }
+            });
+
+        alarmMessage.forEach(message -> {
+            org.apache.skywalking.oap.server.core.alarm.grpc.AlarmMessage.Builder builder =
+                org.apache.skywalking.oap.server.core.alarm.grpc.AlarmMessage.newBuilder();
+
+            builder.setScopeId(message.getScopeId());
+            builder.setScope(message.getScope());
+            builder.setName(message.getName());
+            builder.setId0(message.getId0());
+            builder.setId1(message.getId1());
+            builder.setRuleName(message.getRuleName());
+            builder.setAlarmMessage(message.getAlarmMessage());
+            builder.setStartTime(message.getStartTime());
+
+            streamObserver.onNext(builder.build());
+        });
+
+        streamObserver.onCompleted();
+
+        if (log.isDebugEnabled()) {
+            log.debug("Send {} alarm message to {}:{}.", alarmMessage.size(),
+                alarmSetting.getTargetHost(), alarmSetting.getTargetPort());
+        }
+    }
+}
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java b/oap-server/server-alarm-plugin/src/main/proto/alarm-hook.proto
similarity index 64%
copy from oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
copy to oap-server/server-alarm-plugin/src/main/proto/alarm-hook.proto
index e7a2e34..1e2e638 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/Rules.java
+++ b/oap-server/server-alarm-plugin/src/main/proto/alarm-hook.proto
@@ -16,19 +16,27 @@
  *
  */
 
-package org.apache.skywalking.oap.server.core.alarm.provider;
+syntax = "proto3";
 
-import java.util.*;
-import lombok.*;
+option java_multiple_files = true;
+option java_package = "org.apache.skywalking.oap.server.core.alarm.grpc";
 
-@Setter(AccessLevel.PUBLIC)
-@Getter(AccessLevel.PUBLIC)
-public class Rules {
-    private List<AlarmRule> rules;
-    private List<String> webhooks;
-
-    public Rules() {
-        this.rules = new ArrayList<>();
-        this.webhooks = new ArrayList<>();
+service AlarmService {
+    rpc doAlarm (stream AlarmMessage) returns (Response) {
     }
 }
+
+message AlarmMessage {
+    int64 scopeId = 1;
+    string scope = 2;
+    string name = 3;
+    int64 id0 = 4;
+    int64 id1 = 5;
+    string ruleName = 6;
+    string alarmMessage = 7;
+    int64 startTime = 8;
+}
+
+message Response {
+}
+
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcherTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcherTest.java
index 8535c1d..26b8d45 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcherTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRulesWatcherTest.java
@@ -18,6 +18,10 @@
 
 package org.apache.skywalking.oap.server.core.alarm.provider;
 
+import java.io.IOException;
+import java.io.Reader;
+import java.util.ArrayList;
+import java.util.Arrays;
 import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
 import org.apache.skywalking.oap.server.library.util.ResourceUtils;
 import org.junit.Before;
@@ -25,13 +29,9 @@ import org.junit.Test;
 import org.mockito.MockitoAnnotations;
 import org.mockito.Spy;
 
-import java.io.IOException;
-import java.io.Reader;
-import java.util.ArrayList;
-import java.util.Arrays;
-
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotEquals;
+import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
 import static org.junit.Assert.assertTrue;
 import static org.mockito.Mockito.spy;
@@ -82,6 +82,8 @@ public class AlarmRulesWatcherTest {
 
         assertEquals(2, alarmRulesWatcher.getRules().size());
         assertEquals(2, alarmRulesWatcher.getWebHooks().size());
+        assertNotNull(alarmRulesWatcher.getGrpchookSetting());
+        assertEquals(9888, alarmRulesWatcher.getGrpchookSetting().getTargetPort());
         assertEquals(2, alarmRulesWatcher.getRunningContext().size());
     }
 
@@ -96,6 +98,7 @@ public class AlarmRulesWatcherTest {
 
         assertEquals(0, alarmRulesWatcher.getRules().size());
         assertEquals(0, alarmRulesWatcher.getWebHooks().size());
+        assertNull(alarmRulesWatcher.getGrpchookSetting());
         assertEquals(0, alarmRulesWatcher.getRunningContext().size());
     }
 
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/AlarmMockReceiver.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/AlarmMockReceiver.java
new file mode 100644
index 0000000..0052ef1
--- /dev/null
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/AlarmMockReceiver.java
@@ -0,0 +1,73 @@
+/*
+ * 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.grpc;
+
+import io.grpc.stub.StreamObserver;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.alarm.grpc.AlarmMessage;
+import org.apache.skywalking.oap.server.core.alarm.grpc.AlarmServiceGrpc;
+import org.apache.skywalking.oap.server.core.alarm.grpc.Response;
+import org.apache.skywalking.oap.server.library.server.ServerException;
+import org.apache.skywalking.oap.server.library.server.grpc.GRPCHandler;
+import org.apache.skywalking.oap.server.library.server.grpc.GRPCServer;
+
+@Slf4j
+public class AlarmMockReceiver {
+    public static void main(String[] args) throws ServerException, InterruptedException {
+        GRPCServer server = new GRPCServer("localhost", 9888);
+        server.initialize();
+        server.addHandler(new MockAlarmHandler());
+        server.start();
+
+        while (true) {
+            Thread.sleep(20000L);
+        }
+    }
+
+    public static class MockAlarmHandler extends AlarmServiceGrpc.AlarmServiceImplBase implements GRPCHandler {
+
+        @Override public StreamObserver<AlarmMessage> doAlarm(StreamObserver<Response> responseObserver) {
+            return new StreamObserver<AlarmMessage>() {
+                @Override
+                public void onNext(AlarmMessage value) {
+                    System.out.println(value.toString());
+                    log.info("received alarm message: {}", value.toString());
+                }
+
+                @Override
+                public void onError(Throwable throwable) {
+                    responseObserver.onError(throwable);
+                    if (log.isDebugEnabled()) {
+                        log.debug("received alarm message error.");
+                    }
+                    responseObserver.onCompleted();
+                }
+
+                @Override
+                public void onCompleted() {
+                    responseObserver.onNext(Response.newBuilder().build());
+                    responseObserver.onCompleted();
+                    if (log.isDebugEnabled()) {
+                        log.debug("received alarm message completed.");
+                    }
+                }
+            };
+        }
+    }
+}
\ No newline at end of file
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java
new file mode 100644
index 0000000..bc58ba3
--- /dev/null
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/grpc/GRPChookCallbackTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.grpc;
+
+import com.google.common.collect.Lists;
+import java.util.List;
+import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
+import org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher;
+import org.apache.skywalking.oap.server.core.alarm.provider.Rules;
+import org.apache.skywalking.oap.server.core.query.entity.Scope;
+import org.junit.Before;
+import org.junit.Test;
+
+/**
+ * @author jian.tan
+ */
+public class GRPChookCallbackTest {
+
+    private GRPCCallback grpcCallback;
+
+    private AlarmRulesWatcher alarmRulesWatcher;
+
+    private List<AlarmMessage> alarmMessageList;
+
+    @Before
+    public void init() throws Exception {
+        GRPCAlarmSetting setting = new GRPCAlarmSetting();
+        setting.setTargetHost("127.0.0.1");
+        setting.setTargetPort(9888);
+
+        Rules rules = new Rules();
+        rules.setGrpchookSetting(setting);
+
+        alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+        grpcCallback = new GRPCCallback(alarmRulesWatcher);
+        mockAlarmMessage();
+    }
+
+    @Test
+    public void doAlarm() {
+        grpcCallback.doAlarm(alarmMessageList);
+    }
+
+    private void mockAlarmMessage() {
+        AlarmMessage alarmMessage = new AlarmMessage();
+        alarmMessage.setId0(1);
+        alarmMessage.setId1(2);
+        alarmMessage.setScope(Scope.Service.name());
+        alarmMessage.setName("mock alarm message");
+        alarmMessage.setAlarmMessage("message");
+        alarmMessage.setRuleName("mock_rule");
+        alarmMessage.setStartTime(System.currentTimeMillis());
+
+        alarmMessageList = Lists.newArrayList(alarmMessage);
+    }
+}
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 880e21f..144e94d 100755
--- a/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml
+++ b/oap-server/server-alarm-plugin/src/test/resources/alarm-settings.yml
@@ -44,3 +44,7 @@ webhooks:
   - http://127.0.0.1/notify/
   - http://127.0.0.1/go-wechat/
 
+gRPCHook:
+  target_host: 127.0.0.1
+  target_port: 9888
+
diff --git a/oap-server/server-bootstrap/src/main/resources/alarm-settings.yml b/oap-server/server-bootstrap/src/main/resources/alarm-settings.yml
index 0c224d5..c161092 100755
--- a/oap-server/server-bootstrap/src/main/resources/alarm-settings.yml
+++ b/oap-server/server-bootstrap/src/main/resources/alarm-settings.yml
@@ -43,3 +43,7 @@ webhooks:
 #  - http://127.0.0.1/notify/
 #  - http://127.0.0.1/go-wechat/
 
+gRPCHook:
+#  target_host: 127.0.0.1
+#  target_port: 9888
+