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

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


The following commit(s) were added to refs/heads/master by this push:
     new 0cd43544e5 Add `Get Alarm Runtime Status` API. (#13028)
0cd43544e5 is described below

commit 0cd43544e56440c9e42660216275dd6f31417234
Author: Wan Kai <[email protected]>
AuthorDate: Wed Feb 12 23:22:47 2025 +0800

    Add `Get Alarm Runtime Status` API. (#13028)
---
 docs/en/changes/changes.md                         |   2 +
 docs/en/status/query_alarm_runtime_status.md       | 161 +++++++++++++++++
 docs/en/status/status_apis.md                      |   1 +
 docs/menu.yml                                      |   2 +
 .../core/alarm/provider/AlarmMessageFormatter.java |   4 +-
 .../core/alarm/provider/AlarmModuleProvider.java   |   2 +
 .../server/core/alarm/provider/RunningRule.java    |  19 +++
 .../status-query-plugin/pom.xml                    |   5 +
 .../oap/query/debug/AlarmStatusQueryHandler.java   | 190 +++++++++++++++++++++
 .../oap/query/debug/StatusQueryProvider.java       |   4 +
 10 files changed, 389 insertions(+), 1 deletion(-)

diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index e226fb0424..befc5aad67 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -70,6 +70,8 @@
 * Add type descriptor when converting Envoy logs to JSON for persistence, to 
avoid conversion error.
 * Bseline: Support query baseline with MQE and use in the Alarm Rule.
 * Bump up netty to 4.11.118 to fix CVE-2025-24970.
+* Add `Get Alarm Runtime Status` API.
+* Add `lock` when query the Alarm metrics window values.
 
 #### UI
 
diff --git a/docs/en/status/query_alarm_runtime_status.md 
b/docs/en/status/query_alarm_runtime_status.md
new file mode 100644
index 0000000000..e3678e0df2
--- /dev/null
+++ b/docs/en/status/query_alarm_runtime_status.md
@@ -0,0 +1,161 @@
+# Get Alarm Runtime Status
+
+OAP calculates the alarm conditions in the memory based on the alarm rules and 
the metrics data.
+The following APIs are exposed to make the alerting running kernel visible.
+
+## Get Alarm Running Rules
+
+Return the list of alarm running rules.
+
+- URL, `http://{core restHost}:{core restPort}/status/alarm/rules`
+- HTTP GET method.
+
+```json
+{
+  "ruleNames": [
+    "service_percentile_rule",
+    "service_resp_time_rule"
+  ]
+}
+```
+
+## Get Alarm Running Rule Info
+
+Return the detailed information of the alarm running rule.
+
+- URL, `http://{core restHost}:{core restPort}/status/alarm/rules/{ruleName}`
+- HTTP GET method.
+
+```json
+{
+  "ruleName": "service_resp_time_rule",
+  "expression": "sum(service_resp_time > baseline(service_resp_time,upper)) >= 
1",
+  "period": 10,
+  "silentPeriod": 10,
+  "additonalPeriod": 0,
+  "includeNames": [
+    "mock_a_service",
+    "mock_b_service",
+    "mock_c_service"
+  ],
+  "excludeNames": [],
+  "includeNamesRegex": "",
+  "excludeNamesRegex": "",
+  "affectedEntities": [
+    {
+      "scope": "SERVICE",
+      "name": "mock_b_service"
+    },
+    {
+      "scope": "SERVICE",
+      "name": "mock_a_service"
+    },
+    {
+      "scope": "SERVICE",
+      "name": "mock_c_service"
+    }
+  ],
+  "tags": [
+    {
+      "key": "level",
+      "value": "WARNING"
+    }
+  ],
+  "hooks": [
+    "webhook.default",
+    "wechat.default"
+  ],
+  "includeMetrics": [
+    "service_resp_time"
+  ],
+  "formattedMessages": [
+    {
+      "mock_b_service": "Response time of service mock_b_service is more than 
upper baseline in 1 minutes of last 10 minutes."
+    },
+    {
+      "mock_a_service": "Response time of service mock_a_service is more than 
upper baseline in 1 minutes of last 10 minutes."
+    },
+    {
+      "mock_c_service": "Response time of service mock_c_service is more than 
upper baseline in 1 minutes of last 10 minutes."
+    }
+  ]
+}
+```
+
+- `additonalPeriod` is the additional period if the expression includes the 
[increase/rate function](../api/metrics-query-expression.md#trend-operation).
+This additional period is used to enlarge window size for calculating the 
trend value.
+- `affectedEntities` is the entities that have metrics data and being 
calculated by the alarm rule.
+- `formattedMessages` is the result message according to the message template 
and the affected entities.
+
+## Get Alarm Running Context
+
+Return the running context of the alarm rule.
+
+- URL, `http://{core restHost}:{core 
restPort}/status/alarm/{ruleName}/{entityName}`
+- HTTP GET method.
+
+```json
+{
+  "expression": "sum(service_resp_time > baseline(service_resp_time,upper)) >= 
1",
+  "endTime": "2025-02-12T13:39:00.000",
+  "additionalPeriod": 0,
+  "size": 10,
+  "silenceCountdown": 10,
+  "windowValues": [
+    {
+      "index": 0,
+      "metrics": []
+    },
+    {
+      "index": 1,
+      "metrics": []
+    },
+    {
+      "index": 2,
+      "metrics": []
+    },
+    {
+      "index": 3,
+      "metrics": []
+    },
+    {
+      "index": 4,
+      "metrics": []
+    },
+    {
+      "index": 5,
+      "metrics": []
+    },
+    {
+      "index": 6,
+      "metrics": []
+    },
+    {
+      "index": 7,
+      "metrics": [
+        {
+          "timeBucket": 202502121437,
+          "name": "service_resp_time",
+          "value": "6000"
+        }
+      ]
+    },
+    {
+      "index": 8,
+      "metrics": []
+    },
+    {
+      "index": 9,
+      "metrics": []
+    }
+  ],
+  "mqeMetricsSnapshot": {
+    "service_resp_time": 
"[{\"metric\":{\"labels\":[]},\"values\":[{\"id\":\"202502121430\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"202502121431\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"202502121432\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"202502121433\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"202502121434\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"202502121435\",\"doubleValue\":0.0,\"isEmptyValue\":true},{\"id\":\"2025021
 [...]
+    "baseline(service_resp_time,upper)": 
"[{\"metric\":{\"labels\":[]},\"values\":[{\"id\":\"202502121430\",\"doubleValue\":10.0,\"isEmptyValue\":false},{\"id\":\"202502121431\",\"doubleValue\":10.0,\"isEmptyValue\":false},{\"id\":\"202502121432\",\"doubleValue\":10.0,\"isEmptyValue\":false},{\"id\":\"202502121433\",\"doubleValue\":10.0,\"isEmptyValue\":false},{\"id\":\"202502121434\",\"doubleValue\":10.0,\"isEmptyValue\":false},{\"id\":\"202502121435\",\"doubleValue\":10.0,\"isEmptyValu
 [...]
+  }
+}
+```
+`size` is the window size. Equal to the `period + additionalPeriod`.
+`silenceCountdown` is the countdown of the silence period. -1 means silence 
countdown is not running.
+`windowValues` is the original metrics data. The `index` is the index of the 
window, starting from 0.
+`mqeMetricsSnapshot` is the metrics data in the MQE format. When checking 
conditions, these data will be calculated according to the expression.
diff --git a/docs/en/status/status_apis.md b/docs/en/status/status_apis.md
index 01cc939e72..67e144fae0 100644
--- a/docs/en/status/status_apis.md
+++ b/docs/en/status/status_apis.md
@@ -11,6 +11,7 @@ logs and self-observability solutions.
 - [Tracing Query Execution APIs](../debugging/query-tracing.md)
 - [Get Effective TTL Configurations API](query_ttl_setup.md)
 - [Query Cluster Nodes API](query_cluster_nodes.md)
+- [Get Alarm Runtime Status API](query_alarm_runtime_status.md)
 
 If you have a proposal about new status API, please don't hesitate
 to [create a 
discussion](https://github.com/apache/skywalking/discussions/new?category=ideas).
diff --git a/docs/menu.yml b/docs/menu.yml
index a1416469ad..6643b4013b 100644
--- a/docs/menu.yml
+++ b/docs/menu.yml
@@ -346,6 +346,8 @@ catalog:
                 path: "/en/status/query_ttl_setup"
               - name: "Get Node List in the Cluster"
                 path: "/en/status/query_cluster_nodes"
+              - name: "Get Alarm Runtime Status"
+                path: "/en/status/query_alarm_runtime_status"
   - name: "Customization"
     catalog:
       - name: "Overview"
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
index 87e5dc5fa3..55aa0c7589 100644
--- 
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
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.alarm.provider;
 
 import java.util.ArrayList;
 import java.util.List;
+import lombok.Getter;
 
 /**
  * This is a formatter especially for alarm message.
@@ -28,6 +29,7 @@ import java.util.List;
  * <p>
  * - Successful rate of endpoint {name} is lower than 75%
  */
+@Getter
 public class AlarmMessageFormatter {
     private List<String> formatSegments;
     private List<ValueFrom> valueFroms;
@@ -88,7 +90,7 @@ public class AlarmMessageFormatter {
         return message.toString();
     }
 
-    private enum ValueFrom {
+    public enum ValueFrom {
         ID, NAME
     }
 }
diff --git 
a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmModuleProvider.java
 
b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmModuleProvider.java
index c73054e785..8acac27b30 100644
--- 
a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmModuleProvider.java
+++ 
b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmModuleProvider.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.alarm.provider;
 
 import java.io.FileNotFoundException;
 import java.io.Reader;
+import lombok.Getter;
 import org.apache.skywalking.oap.server.configuration.api.ConfigurationModule;
 import 
org.apache.skywalking.oap.server.configuration.api.DynamicConfigurationService;
 import org.apache.skywalking.oap.server.core.CoreModule;
@@ -35,6 +36,7 @@ import 
org.apache.skywalking.oap.server.library.util.ResourceUtils;
 public class AlarmModuleProvider extends ModuleProvider {
 
     private NotifyHandler notifyHandler;
+    @Getter
     private AlarmRulesWatcher alarmRulesWatcher;
 
     @Override
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 dcf10cb816..d270611b88 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
@@ -29,8 +29,10 @@ import java.util.Optional;
 import java.util.Set;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.locks.ReentrantLock;
+import java.util.function.Consumer;
 import java.util.regex.Pattern;
 import java.util.stream.Collectors;
+import lombok.Getter;
 import lombok.RequiredArgsConstructor;
 import lombok.ToString;
 import lombok.extern.slf4j.Slf4j;
@@ -68,6 +70,7 @@ import static 
org.apache.skywalking.oap.server.core.query.type.debugging.Debuggi
  * RunningRule represents each rule in running status. Based on the {@link 
AlarmRule} definition,
  */
 @Slf4j
+@Getter
 public class RunningRule {
     private static DateTimeFormatter TIME_BUCKET_FORMATTER = 
DateTimeFormat.forPattern("yyyyMMddHHmm");
 
@@ -243,12 +246,17 @@ public class RunningRule {
      * buckets.
      */
     public class Window {
+        @Getter
         private LocalDateTime endTime;
+        @Getter
         private final int additionalPeriod;
+        @Getter
         private final int size;
+        @Getter
         private int silenceCountdown;
         private LinkedList<Map<String, Metrics>> values;
         private ReentrantLock lock = new ReentrantLock();
+        @Getter
         private JsonObject mqeMetricsSnapshot;
         private AlarmEntity entity;
 
@@ -356,6 +364,7 @@ public class RunningRule {
         }
 
         private boolean isMatch() {
+            this.lock.lock();
             int isMatch = 0;
             try {
                 TRACE_CONTEXT.set(new DebuggingTraceContext(expression, false, 
false));
@@ -407,6 +416,7 @@ public class RunningRule {
                 this.mqeMetricsSnapshot = visitor.getMqeMetricsSnapshot();
                 return isMatch == 1;
             } finally {
+                this.lock.unlock();
                 TRACE_CONTEXT.remove();
             }
         }
@@ -422,6 +432,15 @@ public class RunningRule {
             return true;
         }
 
+        public void scanWindowValues(Consumer<LinkedList<Map<String, 
Metrics>>> scanFunction) {
+            lock.lock();
+            try {
+                scanFunction.accept(values);
+            } finally {
+                lock.unlock();
+            }
+        }
+
         private void init() {
             values = new LinkedList<>();
             for (int i = 0; i < size; i++) {
diff --git a/oap-server/server-query-plugin/status-query-plugin/pom.xml 
b/oap-server/server-query-plugin/status-query-plugin/pom.xml
index 67c410d184..89be571bf5 100644
--- a/oap-server/server-query-plugin/status-query-plugin/pom.xml
+++ b/oap-server/server-query-plugin/status-query-plugin/pom.xml
@@ -44,5 +44,10 @@
             <artifactId>zipkin-query-plugin</artifactId>
             <version>${project.version}</version>
         </dependency>
+        <dependency>
+            <groupId>org.apache.skywalking</groupId>
+            <artifactId>server-alarm-plugin</artifactId>
+            <version>${project.version}</version>
+        </dependency>
     </dependencies>
 </project>
diff --git 
a/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/AlarmStatusQueryHandler.java
 
b/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/AlarmStatusQueryHandler.java
new file mode 100644
index 0000000000..b277970306
--- /dev/null
+++ 
b/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/AlarmStatusQueryHandler.java
@@ -0,0 +1,190 @@
+/*
+ * 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.query.debug;
+
+import com.google.gson.Gson;
+import com.google.gson.JsonArray;
+import com.google.gson.JsonObject;
+import com.linecorp.armeria.common.HttpResponse;
+import com.linecorp.armeria.common.MediaType;
+import com.linecorp.armeria.server.annotation.ExceptionHandler;
+import com.linecorp.armeria.server.annotation.Get;
+import com.linecorp.armeria.server.annotation.Param;
+import java.util.List;
+import java.util.Map;
+import java.util.stream.Collectors;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.skywalking.oap.server.core.alarm.AlarmModule;
+import org.apache.skywalking.oap.server.core.alarm.provider.AlarmEntity;
+import 
org.apache.skywalking.oap.server.core.alarm.provider.AlarmModuleProvider;
+import org.apache.skywalking.oap.server.core.alarm.provider.AlarmRulesWatcher;
+import org.apache.skywalking.oap.server.core.alarm.provider.RunningRule;
+import 
org.apache.skywalking.oap.server.core.analysis.metrics.DoubleValueHolder;
+import org.apache.skywalking.oap.server.core.analysis.metrics.IntValueHolder;
+import 
org.apache.skywalking.oap.server.core.analysis.metrics.LabeledValueHolder;
+import org.apache.skywalking.oap.server.core.analysis.metrics.LongValueHolder;
+import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
+
+@Slf4j
+@ExceptionHandler(StatusQueryExceptionHandler.class)
+public class AlarmStatusQueryHandler {
+    private final Gson gson = new Gson();
+    private final ModuleManager moduleManager;
+    private AlarmRulesWatcher alarmRulesWatcher;
+
+    public AlarmStatusQueryHandler(final ModuleManager manager) {
+        this.moduleManager = manager;
+    }
+
+    private AlarmRulesWatcher getAlarmRulesWatcher() {
+        if (alarmRulesWatcher == null) {
+
+            AlarmModuleProvider provider = (AlarmModuleProvider) 
moduleManager.find(AlarmModule.NAME)
+                                               .provider();
+            alarmRulesWatcher = provider.getAlarmRulesWatcher();
+        }
+        return alarmRulesWatcher;
+    }
+
+    @Get("/status/alarm/rules")
+    public HttpResponse getAlarmRules() {
+        Map<String, RunningRule> runningRules = 
getAlarmRulesWatcher().getRunningContext().values().stream().map(List::stream)
+            .flatMap(r -> 
r).collect(Collectors.toMap(RunningRule::getRuleName, r -> r));
+        JsonObject runningRuleNames = new JsonObject();
+        JsonArray nameList = new JsonArray();
+        runningRuleNames.add("ruleNames", nameList);
+        runningRules.keySet().forEach(nameList::add);
+        return HttpResponse.of(MediaType.JSON_UTF_8, 
gson.toJson(runningRuleNames));
+    }
+
+    @Get("/status/alarm/{ruleName}")
+    public HttpResponse getAlarmRuleByName(@Param("ruleName") String ruleName) 
{
+        Map<String, RunningRule> runningRules = 
getAlarmRulesWatcher().getRunningContext().values().stream().flatMap(List::stream)
+                                                                      
.collect(Collectors.toMap(RunningRule::getRuleName, r -> r));
+        RunningRule rule = runningRules.get(ruleName);
+        JsonObject runningRuleInfo = new JsonObject();
+        runningRuleInfo.addProperty("ruleName", rule.getRuleName());
+        runningRuleInfo.addProperty("expression", rule.getExpression());
+        runningRuleInfo.addProperty("period", rule.getPeriod());
+        runningRuleInfo.addProperty("silentPeriod", rule.getSilencePeriod());
+        runningRuleInfo.addProperty("additonalPeriod", 
rule.getAdditionalPeriod());
+
+        JsonArray includeNameList = new JsonArray();
+        runningRuleInfo.add("includeNames", includeNameList);
+        rule.getIncludeNames().forEach(includeNameList::add);
+
+        JsonArray excludeNameList = new JsonArray();
+        runningRuleInfo.add("excludeNames", excludeNameList);
+        rule.getExcludeNames().forEach(excludeNameList::add);
+
+        runningRuleInfo.addProperty("includeNamesRegex", 
rule.getExcludeNamesRegex() == null ? "" : 
rule.getIncludeNamesRegex().toString());
+        runningRuleInfo.addProperty("excludeNamesRegex", 
rule.getExcludeNamesRegex() == null ? "" : 
rule.getExcludeNamesRegex().toString());
+
+        JsonArray affectedEntities = new JsonArray();
+        runningRuleInfo.add("affectedEntities", affectedEntities);
+        JsonArray msgFormatter = new JsonArray();
+        rule.getWindows().keySet().forEach(e -> {
+            JsonObject entity = new JsonObject();
+            entity.addProperty("scope", e.getScope());
+            entity.addProperty("name", e.getName());
+            affectedEntities.add(entity);
+            JsonObject msg = new JsonObject();
+            msg.addProperty(e.getName(), rule.getFormatter().format(e));
+            msgFormatter.add(msg);
+        });
+
+        JsonArray tagList = new JsonArray();
+        runningRuleInfo.add("tags", tagList);
+        rule.getTags().forEach(tag -> {
+            JsonObject tagInfo = new JsonObject();
+            tagInfo.addProperty("key", tag.getKey());
+            tagInfo.addProperty("value", tag.getValue());
+            tagList.add(tagInfo);
+        });
+
+        JsonArray hookList = new JsonArray();
+        runningRuleInfo.add("hooks", hookList);
+        rule.getHooks().forEach(hookList::add);
+
+        JsonArray includeMetricList = new JsonArray();
+        runningRuleInfo.add("includeMetrics", includeMetricList);
+        rule.getIncludeMetrics().forEach(includeMetricList::add);
+
+        runningRuleInfo.add("formattedMessages", msgFormatter);
+
+        return HttpResponse.of(MediaType.JSON_UTF_8, 
runningRuleInfo.toString());
+    }
+
+    @Get("/status/alarm/{ruleName}/{entityName}")
+    public HttpResponse getAlarmRuleContext(@Param("ruleName") String 
ruleName, @Param("entityName") String entityName) {
+        Map<String, RunningRule> runningRules = 
getAlarmRulesWatcher().getRunningContext().values().stream().flatMap(List::stream)
+                                                                      
.collect(Collectors.toMap(RunningRule::getRuleName, r -> r));
+        RunningRule rule = runningRules.get(ruleName);
+        Map<AlarmEntity, RunningRule.Window> windows = rule.getWindows();
+        RunningRule.Window window = windows.keySet().stream().filter(e -> 
e.getName().equals(entityName)).map(windows::get)
+            .findFirst().orElse(null);
+        JsonObject runningContext = new JsonObject();
+        if (window == null) {
+            return HttpResponse.of(MediaType.JSON_UTF_8, 
runningContext.toString());
+        }
+
+        runningContext.addProperty("expression", rule.getExpression());
+        runningContext.addProperty("endTime", window.getEndTime().toString());
+        runningContext.addProperty("additionalPeriod", 
window.getAdditionalPeriod());
+        runningContext.addProperty("size", window.getSize());
+        runningContext.addProperty("silenceCountdown", 
window.getSilenceCountdown());
+
+        JsonArray metricValues = new JsonArray();
+        runningContext.add("windowValues", metricValues);
+
+        window.scanWindowValues(values -> {
+            for (int i = 0; i < values.size(); i++) {
+                JsonObject index = new JsonObject();
+                JsonArray metrics = new JsonArray();
+                metricValues.add(index);
+                index.addProperty("index", i);
+                index.add("metrics", metrics);
+                Map<String, Metrics> m = values.get(i);
+                if (null != m) {
+                    m.forEach((name, metric) -> {
+                        JsonObject metricValue = new JsonObject();
+                        metricValue.addProperty("timeBucket", 
metric.getTimeBucket());
+                        metricValue.addProperty("name", name);
+                        String value = "";
+                        if (metric instanceof LongValueHolder) {
+                            value = Long.toString(((LongValueHolder) 
metric).getValue());
+                        } else if (metric instanceof IntValueHolder) {
+                            value = Integer.toString(((IntValueHolder) 
metric).getValue());
+                        } else if (metric instanceof DoubleValueHolder) {
+                            value = Double.toString(((DoubleValueHolder) 
metric).getValue());
+                        } else if (metric instanceof LabeledValueHolder) {
+                            value = ((LabeledValueHolder) 
metric).getValue().toString();
+                        }
+                        metricValue.addProperty("value", value);
+                        metrics.add(metricValue);
+                    });
+                }
+            }
+        });
+
+        runningContext.add("mqeMetricsSnapshot", 
window.getMqeMetricsSnapshot());
+        return HttpResponse.of(MediaType.JSON_UTF_8, 
gson.toJson(runningContext));
+    }
+}
diff --git 
a/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/StatusQueryProvider.java
 
b/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/StatusQueryProvider.java
index ebeb939ab8..5d1f84fb74 100644
--- 
a/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/StatusQueryProvider.java
+++ 
b/oap-server/server-query-plugin/status-query-plugin/src/main/java/org/apache/skywalking/oap/query/debug/StatusQueryProvider.java
@@ -75,6 +75,10 @@ public class StatusQueryProvider extends ModuleProvider {
             new ClusterStatusQueryHandler(getManager()),
             Collections.singletonList(HttpMethod.GET)
         );
+        service.addHandler(
+            new AlarmStatusQueryHandler(getManager()),
+            Collections.singletonList(HttpMethod.GET)
+        );
     }
 
     public void notifyAfterCompleted() throws ServiceNotProvidedException, 
ModuleStartException {

Reply via email to