You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by wu...@apache.org on 2025/02/10 12:35:36 UTC
(skywalking) branch master updated: Baseline: Support query baseline with MQE and use in the Alarm Kernel. (#13024)
This is an automated email from the ASF dual-hosted git repository.
wusheng 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 97c47de89b Baseline: Support query baseline with MQE and use in the Alarm Kernel. (#13024)
97c47de89b is described below
commit 97c47de89b36d8fec6ddea860e8a9c7e1bb0790d
Author: Wan Kai <wa...@foxmail.com>
AuthorDate: Mon Feb 10 20:35:30 2025 +0800
Baseline: Support query baseline with MQE and use in the Alarm Kernel. (#13024)
---
docs/en/api/metrics-query-expression.md | 30 +++-
docs/en/changes/changes.md | 1 +
docs/en/setup/backend/backend-alarm.md | 15 ++
.../baseline/service/BaselineQueryService.java | 13 +-
.../baseline/service/BaselineQueryServiceImpl.java | 67 +++++++
.../apache/skywalking/mqe/rt/grammar/MQELexer.g4 | 5 +
.../apache/skywalking/mqe/rt/grammar/MQEParser.g4 | 4 +
oap-server/mqe-rt/pom.xml | 5 +
.../apache/skywalking/mqe/rt/MQEVisitorBase.java | 145 ++++++++++++++-
.../core/alarm/provider/AlarmModuleProvider.java | 4 +-
.../oap/server/core/alarm/provider/AlarmRule.java | 6 +-
.../core/alarm/provider/AlarmRulesWatcher.java | 9 +-
.../server/core/alarm/provider/RulesReader.java | 10 +-
.../server/core/alarm/provider/RunningRule.java | 13 +-
.../provider/expr/rt/AlarmMQEVerifyVisitor.java | 5 +-
.../alarm/provider/expr/rt/AlarmMQEVisitor.java | 82 ++++-----
.../server/core/alarm/provider/AlarmCoreTest.java | 2 +-
.../server/core/alarm/provider/AlarmRuleTest.java | 2 +-
.../core/alarm/provider/AlarmRulesWatcherTest.java | 14 +-
.../core/alarm/provider/NotifyHandlerTest.java | 2 +-
.../core/alarm/provider/RulesReaderTest.java | 2 +-
.../core/alarm/provider/RunningRuleTest.java | 40 ++---
.../dingtalk/DingtalkHookCallbackTest.java | 4 +-
.../provider/feishu/FeishuHookCallbackTest.java | 6 +-
.../alarm/provider/grpc/GRPChookCallbackTest.java | 4 +-
.../pagerduty/PagerDutyHookCallbackTest.java | 2 +-
.../provider/slack/SlackHookCallbackTest.java | 2 +-
.../provider/webhook/WebhookCallbackTest.java | 2 +-
.../provider/wechat/WechatHookCallbackTest.java | 2 +-
.../provider/welink/WeLinkHookCallbackTest.java | 2 +-
.../oap/query/graphql/mqe/rt/MQEVisitor.java | 26 ++-
test/e2e-v2/cases/alarm/alarm-settings.yml | 9 +
.../e2e-v2/cases/alarm/banyandb/docker-compose.yml | 18 ++
test/e2e-v2/cases/alarm/es/docker-compose.yml | 18 ++
.../cases/alarm/es/es-sharding/docker-compose.yml | 20 ++-
.../expected/silence-after-graphql-critical.yml | 56 ++++++
.../alarm/expected/silence-after-graphql-warn.yml | 4 +-
.../expected/silence-before-graphql-critical.yml | 56 ++++++
.../alarm/expected/silence-before-graphql-warn.yml | 2 +-
test/e2e-v2/cases/alarm/mysql/docker-compose.yml | 17 ++
.../e2e-v2/cases/alarm/postgres/docker-compose.yml | 18 ++
test/e2e-v2/cases/mqe/docker-compose.yml | 21 +++
.../expected/baseline-OP.yml} | 52 ++----
.../expected/baseline-label-OP.yml} | 65 +++----
.../expected/baseline-lower-OP.yml} | 52 ++----
.../expected/baseline-upper-OP.yml} | 52 ++----
test/e2e-v2/cases/mqe/mqe-cases.yaml | 10 ++
test/e2e-v2/cases/storage/banyandb/gen-certs.sh | 51 ++++++
.../e2e-mock-baseline-server/pom.xml | 134 ++++++++++++++
.../apache/skywalking/e2e/BaselineQueryServer.java | 195 +++++++++++++++++++++
.../org/apache/skywalking/e2e/DownSampling.java | 39 +++--
.../java/org/apache/skywalking/e2e/KeyValue.java | 25 +--
.../apache/skywalking/e2e/ServiceApplication.java | 32 ++--
.../java/org/apache/skywalking/e2e/TimeBucket.java | 194 ++++++++++++++++++++
.../src/main/proto/baseline.proto | 118 +++++++++++++
.../src/main/resources/application.yml} | 37 ----
test/e2e-v2/java-test-service/pom.xml | 1 +
57 files changed, 1481 insertions(+), 341 deletions(-)
diff --git a/docs/en/api/metrics-query-expression.md b/docs/en/api/metrics-query-expression.md
index ba7a92974c..9f8a02a01a 100644
--- a/docs/en/api/metrics-query-expression.md
+++ b/docs/en/api/metrics-query-expression.md
@@ -432,7 +432,7 @@ then the expression result is:
V(T1)-V(T1-2), V(T2)-V(T1-1), V(T3)-V(T1)
```
-**Note**:
+**Notice**
* If the calculated metric value is empty, the result will be empty. Assume in the T3 point, the increase value = V(T3)-V(T1), If the metric V(T3) or V(T1) is empty, the result value in T3 will be empty.
### Result Type
@@ -494,6 +494,34 @@ metric{label1='a', label2='2c'}
metric{label1='a', label2='2a'}
```
+### Baseline Operation
+Baseline Operation takes an expression and gets the baseline predicted values of the input metric.
+
+Expression:
+```text
+baseline(Expression, <baseline_type>)
+```
+
+- `baseline_type` is the type of the baseline predicted value. The type can be `value`, `upper`, `lower`.
+
+for example:
+If we want to get the baseline predicted `upper` values of the `service_resp_time` metric, we can use the following expression:
+```text
+baseline(service_resp_time, upper)
+```
+
+**Notice**:
+- This feature is required to enable the `baseline module` and deploy a baseline service. And the baseline service should implement the protocol of the [baseline.proto](../../../oap-server/metrics-baseline/src/main/proto/baseline.proto).
+Otherwise, the result will be empty.
+- The baseline operation requires the relative metrics declared through baseline service.
+Otherwise, the result will be empty, which means there is no baseline or predicated value.
+- For now, the predictions aim to every hour.
+And the predicated values provided within this baseline are at a minute-level granularity.
+As a result, for CPM(calls per minute), when the query step is `MINUTE` and duration is in a full hour, the returned values are same in every minute of this whole hour.
+
+### Result Type
+TIME_SERIES_VALUES.
+
## Expression Query Example
### Labeled Value Metrics
```text
diff --git a/docs/en/changes/changes.md b/docs/en/changes/changes.md
index ebc26c6c9c..3878e48c47 100644
--- a/docs/en/changes/changes.md
+++ b/docs/en/changes/changes.md
@@ -68,6 +68,7 @@
* BaseLine: Support query baseline metrics names.
* Add `Get Node List in the Cluster` API.
* 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.
#### UI
diff --git a/docs/en/setup/backend/backend-alarm.md b/docs/en/setup/backend/backend-alarm.md
index a292a33d97..91f623b93a 100644
--- a/docs/en/setup/backend/backend-alarm.md
+++ b/docs/en/setup/backend/backend-alarm.md
@@ -125,6 +125,21 @@ Currently, metrics from the **Service**, **Service Instance**, **Endpoint**, **S
Submit an issue or a pull request if you want to support any other scopes in Alarm.
+### Use the Baseline Predicted Value to trigger the Alarm
+Since 10.2.0, SkyWalking supports using the baseline predicted value in the alarm rule expression.
+The MQE expression can refer to [Baseline Operation](../../api/metrics-query-expression.md#baseline-operation).
+
+For example, the following rule will compare the service response time with the baseline predicted value in each time bucket, and
+when the service response time is higher than the baseline predicted value in 3 minutes of the last 10 minutes, the alarm will be triggered.
+
+```yaml
+rules:
+ service_resp_time_rule:
+ expression: sum(service_resp_time > baseline(service_resp_time, upper)) > 3
+ period: 10
+ message: Service {name} response time is higher than the baseline predicted value in 3 minutes of last 10 minutes.
+```
+
## Hooks
Hooks are a way to send alarm messages to the outside world. SkyWalking supports multiple hooks of the same type, each hook can support different configurations.
For example, you can configure two Slack hooks, one named `default` and set `is-default: true` means this hook will apply on all `Alarm Rules` **without config** `hooks`.
diff --git a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java b/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
index 3bf9818918..860c836d0b 100644
--- a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
+++ b/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.baseline.service;
+import java.util.Map;
import org.apache.skywalking.oap.server.library.module.Service;
import java.util.List;
@@ -25,12 +26,20 @@ import java.util.List;
public interface BaselineQueryService extends Service {
/**
* query supported query baseline metrics names
+ *
* @return
*/
List<String> querySupportedMetrics();
/**
- * query predict metrics
+ * query predicted metrics
*/
- List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket);
+ List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics,
+ long startTimeBucket,
+ long endTimeBucket);
+
+ /**
+ * query predicted metrics from cache, return all predicted metrics for the given service name and time bucket hour
+ */
+ Map<String, PredictServiceMetrics.PredictMetricsValue> queryPredictMetricsFromCache(String serviceName, String timeBucketHour);
}
diff --git a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryServiceImpl.java b/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryServiceImpl.java
index 8f66738a49..c7b43698ca 100644
--- a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryServiceImpl.java
+++ b/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryServiceImpl.java
@@ -18,8 +18,13 @@
package org.apache.skywalking.oap.server.baseline.service;
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
import com.google.protobuf.Empty;
import io.grpc.ManagedChannel;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.apm.baseline.v3.AlarmBaselineMetricPrediction;
import org.apache.skywalking.apm.baseline.v3.AlarmBaselineMetricsNames;
@@ -29,7 +34,11 @@ import org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceGrpc;
import org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceMetricName;
import org.apache.skywalking.apm.baseline.v3.KeyStringValuePair;
import org.apache.skywalking.apm.baseline.v3.TimeBucketStep;
+import org.apache.skywalking.oap.server.core.Const;
+import org.apache.skywalking.oap.server.core.analysis.DownSampling;
+import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
import org.apache.skywalking.oap.server.library.client.grpc.GRPCClient;
+import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import java.util.ArrayList;
@@ -41,8 +50,12 @@ import java.util.stream.Collectors;
@Slf4j
public class BaselineQueryServiceImpl implements BaselineQueryService {
private AlarmBaselineServiceGrpc.AlarmBaselineServiceBlockingStub stub;
+ private final Cache<String/*timeBucket,serviceName*/, Map<String/*metricName*/, PredictServiceMetrics.PredictMetricsValue>> baselineCache;
public BaselineQueryServiceImpl(String addr, int port) {
+ this.baselineCache = CacheBuilder.newBuilder()
+ .expireAfterAccess(1, TimeUnit.HOURS)
+ .build();
if (StringUtil.isEmpty(addr) || port <= 0) {
return;
}
@@ -55,6 +68,7 @@ public class BaselineQueryServiceImpl implements BaselineQueryService {
@Override
public List<String> querySupportedMetrics() {
if (stub == null) {
+ log.warn("Baseline service is not set up, return empty list.");
return Collections.emptyList();
}
@@ -66,6 +80,7 @@ public class BaselineQueryServiceImpl implements BaselineQueryService {
public List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket) {
if (stub == null) {
+ log.warn("Baseline service is not set up, return empty baseline values.");
return Collections.emptyList();
}
@@ -77,6 +92,58 @@ public class BaselineQueryServiceImpl implements BaselineQueryService {
return Collections.emptyList();
}
+ public Map<String, PredictServiceMetrics.PredictMetricsValue> queryPredictMetricsFromCache(String serviceName,
+ String timeBucketHour) {
+ if (stub == null) {
+ log.warn("Baseline service is not set up, return empty baseline values.");
+ return Collections.emptyMap();
+ }
+ String key = timeBucketHour + Const.COMMA + serviceName;
+ Map<String, PredictServiceMetrics.PredictMetricsValue> baselineValues = this.baselineCache.asMap().get(key);
+
+ if (CollectionUtils.isNotEmpty(baselineValues)) {
+ return baselineValues;
+ }
+ //reload all metrics and timeBucket baseline values for this service
+ List<String> metrics = querySupportedMetrics();
+ ServiceMetrics serviceMetrics = ServiceMetrics.builder()
+ .serviceName(serviceName)
+ .metricsNames(metrics)
+ .build();
+ //todo: need config?
+ long startTimeBucket = TimeBucket.getTimeBucket(
+ System.currentTimeMillis() - TimeUnit.HOURS.toMillis(24), DownSampling.Hour);
+ long endTimeBucket = TimeBucket.getTimeBucket(
+ System.currentTimeMillis() + TimeUnit.HOURS.toMillis(24), DownSampling.Hour);
+ List<PredictServiceMetrics> predictServiceMetricsList = queryPredictMetrics(
+ Collections.singletonList(serviceMetrics), startTimeBucket, endTimeBucket);
+ if (CollectionUtils.isEmpty(predictServiceMetricsList)) {
+ return Collections.emptyMap();
+ }
+ for (String metricName : metrics) {
+ for (PredictServiceMetrics predictServiceMetrics : predictServiceMetricsList) {
+ List<PredictServiceMetrics.PredictMetricsValue> predictMetricsValues = predictServiceMetrics.getMetricsValues()
+ .get(
+ metricName);
+ if (CollectionUtils.isEmpty(predictMetricsValues)) {
+ continue;
+ }
+ for (PredictServiceMetrics.PredictMetricsValue predictMetricsValue : predictMetricsValues) {
+ if (predictMetricsValue == null) {
+ continue;
+ }
+ this.baselineCache.asMap()
+ .computeIfAbsent(
+ predictMetricsValue.getTimeBucket() + Const.COMMA + serviceName,
+ k -> new HashMap<>()
+ )
+ .put(metricName, predictMetricsValue);
+ }
+ }
+ }
+ return this.baselineCache.asMap().getOrDefault(key, Collections.emptyMap());
+ }
+
private List<PredictServiceMetrics> queryPredictMetrics0(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket) {
// building request
final AlarmBaselineRequest.Builder request = AlarmBaselineRequest.newBuilder();
diff --git a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4 b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
index fd4dbdeb8e..44278ebf09 100644
--- a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
+++ b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQELexer.g4
@@ -98,6 +98,11 @@ ATTR3: 'attr3';
ATTR4: 'attr4';
ATTR5: 'attr5';
+BASELINE: 'baseline';
+VALUE: 'value';
+UPPER: 'upper';
+LOWER: 'lower';
+
// Literals
INTEGER: Digit+;
DECIMAL: Digit+ DOT Digit+;
diff --git a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4 b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
index e120357031..ccb0a6c5c8 100644
--- a/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
+++ b/oap-server/mqe-grammar/src/main/antlr4/org/apache/skywalking/mqe/rt/grammar/MQEParser.g4
@@ -40,6 +40,7 @@ expression
| aggregateLabels L_PAREN expression COMMA aggregateLabelsFunc R_PAREN #aggregateLabelsOp
| sort_values L_PAREN expression (COMMA INTEGER)? COMMA order R_PAREN #sortValuesOP
| sort_label_values L_PAREN expression COMMA order COMMA labelNameList R_PAREN #sortLabelValuesOP
+ | baseline L_PAREN metric COMMA baseline_type R_PAREN #baselineOP
;
expressionList
@@ -110,3 +111,6 @@ attributeName:
ATTR0 | ATTR1 | ATTR2 | ATTR3 | ATTR4 | ATTR5;
attribute: attributeName (EQ | NEQ) VALUE_STRING;
attributeList: attribute (COMMA attribute)*;
+
+baseline: BASELINE;
+baseline_type: VALUE | UPPER | LOWER;
diff --git a/oap-server/mqe-rt/pom.xml b/oap-server/mqe-rt/pom.xml
index f22565f1c0..fcaa3ae0f3 100644
--- a/oap-server/mqe-rt/pom.xml
+++ b/oap-server/mqe-rt/pom.xml
@@ -44,5 +44,10 @@
<artifactId>mqe-grammar</artifactId>
<version>${project.version}</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.skywalking</groupId>
+ <artifactId>metrics-baseline</artifactId>
+ <version>${project.version}</version>
+ </dependency>
</dependencies>
</project>
diff --git a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
index ae86ac21e3..9d44c232f9 100644
--- a/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
+++ b/oap-server/mqe-rt/src/main/java/org/apache/skywalking/mqe/rt/MQEVisitorBase.java
@@ -19,10 +19,13 @@
package org.apache.skywalking.mqe.rt;
import java.util.ArrayList;
+import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
+import java.util.function.BiFunction;
+import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
import org.apache.skywalking.mqe.rt.grammar.MQEParserBaseVisitor;
@@ -37,6 +40,11 @@ import org.apache.skywalking.mqe.rt.operation.SortLabelValuesOp;
import org.apache.skywalking.mqe.rt.operation.SortValuesOp;
import org.apache.skywalking.mqe.rt.operation.TopNOfOp;
import org.apache.skywalking.mqe.rt.operation.TrendOp;
+import org.apache.skywalking.oap.server.baseline.BaselineModule;
+import org.apache.skywalking.oap.server.baseline.service.BaselineQueryService;
+import org.apache.skywalking.oap.server.baseline.service.PredictServiceMetrics;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataLabel;
+import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult;
import org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResultType;
@@ -47,18 +55,45 @@ import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingSpan;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext.TRACE_CONTEXT;
+import static org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO.Util.composeLabelConditions;
@Slf4j
public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResult> {
+
+ private final BiFunction<String, Step, String> getPredictTimeBucket = (timePoint, step) -> {
+ switch (step) {
+ case MINUTE:
+ return Long.toString(Long.parseLong(timePoint) / 100);
+ case HOUR:
+ return timePoint;
+ case DAY:
+ return Long.toString(Long.parseLong(timePoint) * 100);
+ default:
+ throw new IllegalArgumentException("Unsupported time step: " + step);
+ }
+ };
+ private BaselineQueryService baselineQueryService;
+ protected final ModuleManager moduleManager;
public final Step queryStep;
- protected MQEVisitorBase(final Step queryStep) {
+ protected MQEVisitorBase(final ModuleManager moduleManager, final Step queryStep) {
+ this.moduleManager = moduleManager;
this.queryStep = queryStep;
}
+ private BaselineQueryService getBaselineQueryService() {
+ if (baselineQueryService == null) {
+ this.baselineQueryService = moduleManager.find(BaselineModule.NAME)
+ .provider()
+ .getService(BaselineQueryService.class);
+ }
+ return baselineQueryService;
+ }
+
@Override
public ExpressionResult visitParensOp(MQEParser.ParensOpContext ctx) {
ExpressionResult result = visit(ctx.expression());
@@ -467,6 +502,17 @@ public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResu
}
}
+ @Override
+ public ExpressionResult visitBaselineOP(MQEParser.BaselineOPContext ctx) {
+ DebuggingTraceContext traceContext = TRACE_CONTEXT.get();
+ DebuggingSpan span = traceContext.createSpan("MQE Baseline OP: " + ctx.getText());
+ try {
+ return visit(ctx.metric());
+ } finally {
+ traceContext.stopSpan(span);
+ }
+ }
+
@Override
public abstract ExpressionResult visitMetric(MQEParser.MetricContext ctx);
@@ -510,4 +556,101 @@ public abstract class MQEVisitorBase extends MQEParserBaseVisitor<ExpressionResu
result.setError(error);
return result;
}
+
+ @SneakyThrows
+ protected List<MQEValues> queryBaseline(String serviceName,
+ String metricName,
+ ArrayList<String> pointOfTimes,
+ int valueType) {
+ List<MQEValues> mqeValuesList = new ArrayList<>();
+ MQEValues mqeValues = new MQEValues();
+ for (String pointOfTime : pointOfTimes) {
+ Map<String, PredictServiceMetrics.PredictMetricsValue> predictValues = getBaselineQueryService().queryPredictMetricsFromCache(
+ serviceName, getPredictTimeBucket.apply(pointOfTime, queryStep));
+ PredictServiceMetrics.PredictMetricsValue predictValue = predictValues.get(metricName);
+ MQEValue mqeValue = new MQEValue();
+ //use timeBucket as id here
+ mqeValue.setId(pointOfTime);
+ if (predictValue == null || predictValue.getSingleValue() == null) {
+ mqeValue.setEmptyValue(true);
+ } else {
+ mqeValue.setDoubleValue(getValueByType(predictValue.getSingleValue(), valueType));
+ }
+ mqeValues.getValues().add(mqeValue);
+ }
+ mqeValuesList.add(mqeValues);
+ return mqeValuesList;
+ }
+
+ @SneakyThrows
+ protected List<MQEValues> queryLabeledBaseline(String serviceName,
+ String metricName,
+ List<KeyValue> queryLabels,
+ ArrayList<String> pointOfTimes,
+ int valueType) {
+ Map<String, DataTable> timeValues = new HashMap<>();
+ for (String pointOfTime : pointOfTimes) {
+ Map<String, PredictServiceMetrics.PredictMetricsValue> predictValues = getBaselineQueryService().queryPredictMetricsFromCache(
+ serviceName, getPredictTimeBucket.apply(pointOfTime, queryStep));
+ PredictServiceMetrics.PredictMetricsValue predictValue = predictValues.get(metricName);
+ if (predictValue != null && predictValue.getLabeledValue() != null) {
+ DataTable dataTable = new DataTable();
+ for (PredictServiceMetrics.PredictLabelValue labeledValue : predictValue.getLabeledValue()) {
+ DataLabel dataLabel = new DataLabel();
+ if (labeledValue != null) {
+ dataLabel.putAll(labeledValue.getLabels());
+ dataTable.put(dataLabel, getValueByType(labeledValue.getValue(), valueType));
+ }
+ }
+ timeValues.put(pointOfTime, dataTable);
+ }
+ }
+ return buildLabledMqeValuesList(timeValues, queryLabels, pointOfTimes);
+ }
+
+ private long getValueByType(PredictServiceMetrics.PredictSingleValue predictSingleValue,
+ int valueType) {
+ switch (valueType) {
+ case MQEParser.VALUE:
+ return predictSingleValue.getValue();
+ case MQEParser.UPPER:
+ return predictSingleValue.getUpperValue();
+ case MQEParser.LOWER:
+ return predictSingleValue.getLowerValue();
+ default:
+ throw new IllegalArgumentException("Unsupported predicted value type: " + valueType);
+ }
+ }
+
+ protected List<MQEValues> buildLabledMqeValuesList(Map<String, DataTable> timeValues, List<KeyValue> queryLabels,
+ ArrayList<String> pointOfTimes) {
+ List<MQEValues> mqeValuesList = new ArrayList<>();
+ List<String> labelConditions = composeLabelConditions(queryLabels, timeValues.values());
+ for (String labelCondition : labelConditions) {
+ MQEValues mqeValues = new MQEValues();
+ for (String pointOfTime : pointOfTimes) {
+ DataTable dataTable = timeValues.getOrDefault(pointOfTime, new DataTable());
+ Long metricValue = dataTable.get(labelCondition);
+ MQEValue mqeValue = new MQEValue();
+ //use timeBucket as id here
+ mqeValue.setId(pointOfTime);
+ if (metricValue != null) {
+ mqeValue.setDoubleValue(metricValue);
+ } else {
+ mqeValue.setEmptyValue(true);
+ }
+ mqeValues.getValues().add(mqeValue);
+ }
+ DataLabel dataLabel = new DataLabel();
+ dataLabel.put(labelCondition);
+ for (Map.Entry<String, String> label : dataLabel.entrySet()) {
+ mqeValues.getMetric().getLabels().add(new KeyValue(label.getKey(), label.getValue()));
+ }
+ //Sort labels by key in natural order by default
+ mqeValues.getMetric().sortLabelsByKey(Comparator.naturalOrder());
+ mqeValuesList.add(mqeValues);
+ }
+ return mqeValuesList;
+ }
}
+
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 1b2428524d..c73054e785 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
@@ -54,7 +54,7 @@ public class AlarmModuleProvider extends ModuleProvider {
@Override
public void prepare() throws ServiceNotProvidedException, ModuleStartException {
- alarmRulesWatcher = new AlarmRulesWatcher(new Rules(), this);
+ alarmRulesWatcher = new AlarmRulesWatcher(new Rules(), this, getManager());
notifyHandler = new NotifyHandler(alarmRulesWatcher, getManager());
this.registerServiceImplementation(MetricsNotify.class, notifyHandler);
}
@@ -76,7 +76,7 @@ public class AlarmModuleProvider extends ModuleProvider {
} catch (FileNotFoundException e) {
throw new ModuleStartException("can't load alarm-settings.yml", e);
}
- RulesReader reader = new RulesReader(applicationReader);
+ RulesReader reader = new RulesReader(applicationReader, getManager());
Rules rules = reader.readRules();
alarmRulesWatcher.initConfig(rules);
notifyHandler.init(new AlarmStandardPersistence(getManager()));
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 1e7da460ff..633ea5c646 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
@@ -25,6 +25,7 @@ import java.util.Set;
import lombok.AccessLevel;
import lombok.Data;
import lombok.EqualsAndHashCode;
+import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.ToString;
import org.antlr.v4.runtime.CharStreams;
@@ -40,6 +41,7 @@ import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResultType;
import org.apache.skywalking.oap.server.core.alarm.provider.expr.rt.AlarmMQEVerifyVisitor;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import static org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext.TRACE_CONTEXT;
@@ -47,7 +49,9 @@ import static org.apache.skywalking.oap.server.core.query.type.debugging.Debuggi
@Data
@ToString
@EqualsAndHashCode
+@RequiredArgsConstructor
public class AlarmRule {
+ private final ModuleManager moduleManager;
private String alarmRuleName;
private String expression;
@Setter(AccessLevel.NONE)
@@ -80,7 +84,7 @@ public class AlarmRule {
}
try {
TRACE_CONTEXT.set(new DebuggingTraceContext(expression, false, false));
- AlarmMQEVerifyVisitor visitor = new AlarmMQEVerifyVisitor();
+ AlarmMQEVerifyVisitor visitor = new AlarmMQEVerifyVisitor(moduleManager);
ExpressionResult parseResult = visitor.visit(tree);
if (StringUtil.isNotBlank(parseResult.getError())) {
throw new IllegalExpressionException("Expression: " + expression + " error: " + parseResult.getError());
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 9bf5848997..f826469834 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
@@ -40,6 +40,7 @@ import org.apache.skywalking.oap.server.core.alarm.provider.slack.SlackSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.webhook.WebhookSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.wechat.WechatSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.welink.WeLinkSettings;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.module.ModuleProvider;
/**
@@ -59,8 +60,9 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
private volatile String settingsString;
private final ReentrantLock lock;
private final AtomicBoolean notifiedByDynamicConfig;
+ private final ModuleManager moduleManager;
- public AlarmRulesWatcher(Rules defaultRules, ModuleProvider provider) {
+ public AlarmRulesWatcher(Rules defaultRules, ModuleProvider provider, ModuleManager moduleManager) {
super(AlarmModule.NAME, provider, "alarm-settings");
this.runningContext = new HashMap<>();
this.alarmRuleRunningRuleMap = new HashMap<>();
@@ -68,6 +70,7 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
this.settingsString = null;
this.lock = new ReentrantLock();
this.notifiedByDynamicConfig = new AtomicBoolean(false);
+ this.moduleManager = moduleManager;
notify(defaultRules);
}
@@ -80,7 +83,7 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
notify(new Rules());
} else {
settingsString = value.getNewValue();
- RulesReader rulesReader = new RulesReader(new StringReader(value.getNewValue()));
+ RulesReader rulesReader = new RulesReader(new StringReader(value.getNewValue()), moduleManager);
Rules rules = rulesReader.readRules();
notify(rules);
}
@@ -115,7 +118,7 @@ public class AlarmRulesWatcher extends ConfigChangeWatcher {
* If there is already an alarm rule that is the same as the new one, we'll reuse its
* corresponding runningRule, to keep its history metrics
*/
- RunningRule runningRule = alarmRuleRunningRuleMap.getOrDefault(rule, new RunningRule(rule));
+ RunningRule runningRule = alarmRuleRunningRuleMap.getOrDefault(rule, new RunningRule(rule, moduleManager));
newAlarmRuleRunningRuleMap.put(rule, runningRule);
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 66d5832afb..fde8422c91 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
@@ -33,6 +33,7 @@ import org.apache.skywalking.mqe.rt.exception.IllegalExpressionException;
import org.apache.skywalking.oap.server.core.alarm.provider.discord.DiscordSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.pagerduty.PagerDutySettings;
import org.apache.skywalking.oap.server.core.alarm.provider.webhook.WebhookSettings;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.alarm.provider.dingtalk.DingtalkSettings;
import org.apache.skywalking.oap.server.core.alarm.provider.feishu.FeishuSettings;
@@ -52,13 +53,16 @@ public class RulesReader {
private Map yamlData;
private final Set<String> defaultHooks = new HashSet<>();
private final Set<String> allHooks = new HashSet<>();
+ private final ModuleManager moduleManager;
- public RulesReader(InputStream inputStream) {
+ public RulesReader(InputStream inputStream, ModuleManager moduleManager) {
+ this.moduleManager = moduleManager;
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
yamlData = yaml.load(inputStream);
}
- public RulesReader(Reader io) {
+ public RulesReader(Reader io, ModuleManager moduleManager) {
+ this.moduleManager = moduleManager;
Yaml yaml = new Yaml(new SafeConstructor(new LoaderOptions()));
yamlData = yaml.load(io);
}
@@ -88,7 +92,7 @@ public class RulesReader {
rules.setRules(new ArrayList<>());
rulesData.forEach((k, v) -> {
if (((String) k).endsWith("_rule")) {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(moduleManager);
alarmRule.setAlarmRuleName((String) k);
Map settings = (Map) v;
Object expression = settings.get("expression");
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 aa3de66d7d..dcf10cb816 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
@@ -45,6 +45,7 @@ import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResultType;
import org.apache.skywalking.oap.server.core.query.mqe.MQEValues;
import org.apache.skywalking.oap.server.core.alarm.provider.expr.rt.AlarmMQEVisitor;
import org.apache.skywalking.oap.server.core.query.type.debugging.DebuggingTraceContext;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.StringUtil;
import org.apache.skywalking.oap.server.core.alarm.AlarmMessage;
import org.apache.skywalking.oap.server.core.alarm.MetaInAlarm;
@@ -86,8 +87,9 @@ public class RunningRule {
private final ParseTree exprTree;
// The additional period is used to calculate the trend.
private final int additionalPeriod;
+ private final ModuleManager moduleManager;
- public RunningRule(AlarmRule alarmRule) {
+ public RunningRule(AlarmRule alarmRule, ModuleManager moduleManager) {
expression = alarmRule.getExpression();
this.ruleName = alarmRule.getAlarmRuleName();
this.includeMetrics = alarmRule.getIncludeMetrics();
@@ -113,6 +115,7 @@ public class RunningRule {
parser.addErrorListener(new ParseErrorListener());
this.exprTree = parser.expression();
this.additionalPeriod = alarmRule.getMaxTrendRange();
+ this.moduleManager = moduleManager;
}
/**
@@ -139,7 +142,7 @@ public class RunningRule {
AlarmEntity entity = new AlarmEntity(
meta.getScope(), meta.getScopeId(), meta.getName(), meta.getId0(), meta.getId1());
- Window window = windows.computeIfAbsent(entity, ignored -> new Window(this.period, this.additionalPeriod));
+ Window window = windows.computeIfAbsent(entity, ignored -> new Window(entity, this.period, this.additionalPeriod));
window.add(meta.getMetricsName(), metrics);
}
@@ -247,8 +250,10 @@ public class RunningRule {
private LinkedList<Map<String, Metrics>> values;
private ReentrantLock lock = new ReentrantLock();
private JsonObject mqeMetricsSnapshot;
+ private AlarmEntity entity;
- public Window(int period, int additionalPeriod) {
+ public Window(AlarmEntity entity, int period, int additionalPeriod) {
+ this.entity = entity;
this.additionalPeriod = additionalPeriod;
this.size = period + additionalPeriod;
// -1 means silence countdown is not running.
@@ -354,7 +359,7 @@ public class RunningRule {
int isMatch = 0;
try {
TRACE_CONTEXT.set(new DebuggingTraceContext(expression, false, false));
- AlarmMQEVisitor visitor = new AlarmMQEVisitor(this.values, this.endTime, this.additionalPeriod);
+ AlarmMQEVisitor visitor = new AlarmMQEVisitor(moduleManager, this.entity, this.values, this.endTime, this.additionalPeriod);
ExpressionResult parseResult = visitor.visit(exprTree);
if (StringUtil.isNotBlank(parseResult.getError())) {
log.error("expression:" + expression + " error: " + parseResult.getError());
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVerifyVisitor.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVerifyVisitor.java
index e9482c4e6f..6fd1e5c0cf 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVerifyVisitor.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVerifyVisitor.java
@@ -32,6 +32,7 @@ import org.apache.skywalking.oap.server.core.query.mqe.MQEValues;
import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
/**
* Used for verify the alarm expression and get the metrics name when read the alarm rules.
@@ -42,8 +43,8 @@ public class AlarmMQEVerifyVisitor extends MQEVisitorBase {
private final Set<String> includeMetrics = new HashSet<>();
private int maxTrendRange = 0;
- public AlarmMQEVerifyVisitor() {
- super(Step.MINUTE);
+ public AlarmMQEVerifyVisitor(final ModuleManager moduleManager) {
+ super(moduleManager, Step.MINUTE);
}
@Override
diff --git a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVisitor.java b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVisitor.java
index 3b8f07b164..ee464de162 100644
--- a/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVisitor.java
+++ b/oap-server/server-alarm-plugin/src/main/java/org/apache/skywalking/oap/server/core/alarm/provider/expr/rt/AlarmMQEVisitor.java
@@ -21,7 +21,6 @@ package org.apache.skywalking.oap.server.core.alarm.provider.expr.rt;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import java.util.ArrayList;
-import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
@@ -30,11 +29,11 @@ import java.util.Optional;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.apache.skywalking.mqe.rt.grammar.MQEParser;
+import org.apache.skywalking.oap.server.core.alarm.provider.AlarmEntity;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResult;
import org.apache.skywalking.oap.server.core.query.mqe.ExpressionResultType;
import org.apache.skywalking.oap.server.core.query.mqe.MQEValue;
import org.apache.skywalking.oap.server.core.query.mqe.MQEValues;
-import org.apache.skywalking.oap.server.core.analysis.metrics.DataLabel;
import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
import org.apache.skywalking.oap.server.core.analysis.metrics.DoubleValueHolder;
import org.apache.skywalking.oap.server.core.analysis.metrics.IntValueHolder;
@@ -46,13 +45,13 @@ import org.apache.skywalking.oap.server.core.query.enumeration.Step;
import org.apache.skywalking.oap.server.core.query.type.KeyValue;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
import org.apache.skywalking.oap.server.core.storage.annotation.ValueColumnMetadata;
+import org.apache.skywalking.oap.server.library.module.ModuleManager;
import org.apache.skywalking.oap.server.library.util.CollectionUtils;
import org.joda.time.LocalDateTime;
-import static org.apache.skywalking.oap.server.core.storage.query.IMetricsQueryDAO.Util.composeLabelConditions;
-
@Slf4j
public class AlarmMQEVisitor extends MQEVisitorBase {
+ private final AlarmEntity entity;
private final LinkedList<Map<String, Metrics>> metricsValues;
private final Map<String, Map<String, Double>> commonValuesMap;
private final Map<String, Map<String, DataTable>> labeledValuesMap;
@@ -67,10 +66,13 @@ public class AlarmMQEVisitor extends MQEVisitorBase {
private final JsonObject mqeMetricsSnapshot;
private final static Gson GSON = new Gson();
- public AlarmMQEVisitor(final LinkedList<Map<String, Metrics>> metricsValues,
+ public AlarmMQEVisitor(final ModuleManager moduleManager,
+ final AlarmEntity entity,
+ final LinkedList<Map<String, Metrics>> metricsValues,
final LocalDateTime endTime,
final int maxTrendRange) {
- super(Step.MINUTE);
+ super(moduleManager, Step.MINUTE);
+ this.entity = entity;
this.metricsValues = metricsValues;
this.commonValuesMap = new HashMap<>();
this.labeledValuesMap = new HashMap<>();
@@ -86,6 +88,7 @@ public class AlarmMQEVisitor extends MQEVisitorBase {
public ExpressionResult visitMetric(MQEParser.MetricContext ctx) {
ExpressionResult result = new ExpressionResult();
String metricName = ctx.metricName().getText();
+ String snapshotMetricName = ctx.getText();
Optional<ValueColumnMetadata.ValueColumn> valueColumn = ValueColumnMetadata.INSTANCE.readValueColumnDefinition(
metricName);
if (valueColumn.isEmpty()) {
@@ -98,19 +101,38 @@ public class AlarmMQEVisitor extends MQEVisitorBase {
//if no data, build empty value MQEValuesList for calculation
List<MQEValues> mqeValuesList;
if (dataType == Column.ValueDataType.COMMON_VALUE) {
- Map<String, Double> timeValues = commonValuesMap.get(metricName);
- if (CollectionUtils.isEmpty(timeValues)) {
- mqeValuesList = buildEmptyMQEValuesList();
+ if (ctx.parent instanceof MQEParser.BaselineOPContext) {
+ MQEParser.BaselineOPContext parent = (MQEParser.BaselineOPContext) ctx.parent;
+ mqeValuesList = super.queryBaseline(
+ entity.getName(), metricName, windowTimes, parent.baseline_type()
+ .getStart()
+ .getType());
+ snapshotMetricName = parent.getText();
} else {
- mqeValuesList = buildMqeValuesList(timeValues);
+ Map<String, Double> timeValues = commonValuesMap.get(metricName);
+ if (CollectionUtils.isEmpty(timeValues)) {
+ mqeValuesList = buildEmptyMQEValuesList();
+ } else {
+ mqeValuesList = buildMqeValuesList(timeValues);
+ }
}
+
} else if (dataType == Column.ValueDataType.LABELED_VALUE) {
List<KeyValue> queryLabels = buildLabels(ctx.labelList());
- Map<String, DataTable> timeValues = labeledValuesMap.get(metricName);
- if (CollectionUtils.isEmpty(timeValues)) {
- mqeValuesList = buildEmptyMQEValuesList();
+ if (ctx.parent instanceof MQEParser.BaselineOPContext) {
+ MQEParser.BaselineOPContext parent = (MQEParser.BaselineOPContext) ctx.parent;
+ mqeValuesList = super.queryLabeledBaseline(
+ entity.getName(), metricName, queryLabels, windowTimes, parent.baseline_type()
+ .getStart()
+ .getType());
+ snapshotMetricName = parent.getText();
} else {
- mqeValuesList = buildLabledMqeValuesList(timeValues, queryLabels);
+ Map<String, DataTable> timeValues = labeledValuesMap.get(metricName);
+ if (CollectionUtils.isEmpty(timeValues)) {
+ mqeValuesList = buildEmptyMQEValuesList();
+ } else {
+ mqeValuesList = buildLabledMqeValuesList(timeValues, queryLabels, windowTimes);
+ }
}
result.setLabeledResult(true);
} else {
@@ -129,7 +151,7 @@ public class AlarmMQEVisitor extends MQEVisitorBase {
}
result.setResults(mqeValuesList);
result.setType(ExpressionResultType.TIME_SERIES_VALUES);
- this.mqeMetricsSnapshot.addProperty(metricName, GSON.toJson(mqeValuesList));
+ this.mqeMetricsSnapshot.addProperty(snapshotMetricName, GSON.toJson(mqeValuesList));
return result;
}
@@ -217,36 +239,6 @@ public class AlarmMQEVisitor extends MQEVisitorBase {
return mqeValuesList;
}
- private List<MQEValues> buildLabledMqeValuesList(Map<String, DataTable> timeValues, List<KeyValue> queryLabels) {
- List<MQEValues> mqeValuesList = new ArrayList<>();
- List<String> labelConditions = composeLabelConditions(queryLabels, timeValues.values());
- for (String labelCondition : labelConditions) {
- MQEValues mqeValues = new MQEValues();
- for (String time : windowTimes) {
- DataTable dataTable = timeValues.getOrDefault(time, new DataTable());
- Long metricValue = dataTable.get(labelCondition);
- MQEValue mqeValue = new MQEValue();
- //use timeBucket as id here
- mqeValue.setId(time);
- if (metricValue != null) {
- mqeValue.setDoubleValue(metricValue);
- } else {
- mqeValue.setEmptyValue(true);
- }
- mqeValues.getValues().add(mqeValue);
- }
- DataLabel dataLabel = new DataLabel();
- dataLabel.put(labelCondition);
- for (Map.Entry<String, String> label : dataLabel.entrySet()) {
- mqeValues.getMetric().getLabels().add(new KeyValue(label.getKey(), label.getValue()));
- }
- //Sort labels by key in natural order by default
- mqeValues.getMetric().sortLabelsByKey(Comparator.naturalOrder());
- mqeValuesList.add(mqeValues);
- }
- return mqeValuesList;
- }
-
//init MQEValues with empty value according to window size and end time
private MQEValues initMQEValues() {
MQEValues mqeValues = new MQEValues();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmCoreTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmCoreTest.java
index 69dce8cbe6..68a415d5d8 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmCoreTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmCoreTest.java
@@ -49,7 +49,7 @@ public class AlarmCoreTest {
Rules emptyRules = new Rules();
emptyRules.setRules(new ArrayList<>(0));
- AlarmCore core = new AlarmCore(new AlarmRulesWatcher(emptyRules, null));
+ AlarmCore core = new AlarmCore(new AlarmRulesWatcher(emptyRules, null, null));
Map<String, List<RunningRule>> runningContext = Whitebox.getInternalState(core, "runningContext");
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleTest.java
index 7bbda290a8..c964164de9 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/AlarmRuleTest.java
@@ -60,7 +60,7 @@ public class AlarmRuleTest {
@Test
public void testExpressionVerify() throws IllegalExpressionException {
- AlarmRule rule = new AlarmRule();
+ AlarmRule rule = new AlarmRule(null);
//normal common metric
rule.setExpression("sum(service_percent < 85) >= 3");
//normal labeled metric
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 04f38728da..4a25c6902c 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
@@ -45,7 +45,7 @@ import static org.mockito.Mockito.spy;
public class AlarmRulesWatcherTest {
@Spy
- private AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(new Rules(), null);
+ private AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(new Rules(), null, null);
@BeforeEach
public void setUp() {
@@ -80,9 +80,9 @@ public class AlarmRulesWatcherTest {
@Test
public void shouldClearAlarmRulesOnEventDeleted() throws IOException {
Reader reader = ResourceUtils.read("alarm-settings.yml");
- Rules defaultRules = new RulesReader(reader).readRules();
+ Rules defaultRules = new RulesReader(reader, null).readRules();
- alarmRulesWatcher = spy(new AlarmRulesWatcher(defaultRules, null));
+ alarmRulesWatcher = spy(new AlarmRulesWatcher(defaultRules, null, null));
alarmRulesWatcher.notify(new ConfigChangeWatcher.ConfigChangeEvent("whatever", ConfigChangeWatcher.EventType.DELETE));
@@ -98,7 +98,7 @@ public class AlarmRulesWatcherTest {
Rules rules = new Rules();
rules.getRules().add(rule);
- alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null));
+ alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null, null));
assertEquals(1, alarmRulesWatcher.getRunningContext().size());
assertEquals(1, alarmRulesWatcher.getRunningContext().get(rule.getExpression()).size());
@@ -122,7 +122,7 @@ public class AlarmRulesWatcherTest {
Rules rules = new Rules();
rules.getRules().add(rule);
- alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null));
+ alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null, null));
assertEquals(1, alarmRulesWatcher.getRunningContext().size());
assertEquals(1, alarmRulesWatcher.getRunningContext().get(rule.getExpression()).size());
@@ -146,7 +146,7 @@ public class AlarmRulesWatcherTest {
Rules rules = new Rules();
rules.getRules().add(rule);
- alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null));
+ alarmRulesWatcher = spy(new AlarmRulesWatcher(rules, null, null));
assertEquals(1, alarmRulesWatcher.getRunningContext().size());
assertEquals(1, alarmRulesWatcher.getRunningContext().get(rule.getExpression()).size());
@@ -167,7 +167,7 @@ public class AlarmRulesWatcherTest {
}
private AlarmRule newAlarmRule(String name, String expression) throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName(name);
alarmRule.setIncludeNames(new ArrayList<String>() {
{
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandlerTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandlerTest.java
index 365e8da3b4..7525227427 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandlerTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/NotifyHandlerTest.java
@@ -259,7 +259,7 @@ public class NotifyHandlerTest {
ModuleManager moduleManager = mock(ModuleManager.class);
- notifyHandler = new NotifyHandler(new AlarmRulesWatcher(rules, null), moduleManager);
+ notifyHandler = new NotifyHandler(new AlarmRulesWatcher(rules, null, moduleManager), moduleManager);
notifyHandler.init(alarmMessageList -> {
for (AlarmMessage message : alarmMessageList) {
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java
index f9cb159ca7..2d017c6401 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/RulesReaderTest.java
@@ -51,7 +51,7 @@ public class RulesReaderTest {
public void testReadRules() {
RulesReader reader = new RulesReader(this.getClass()
.getClassLoader()
- .getResourceAsStream("alarm-settings.yml"));
+ .getResourceAsStream("alarm-settings.yml"), null);
Rules rules = reader.readRules();
List<AlarmRule> ruleList = rules.getRules();
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 8843102be0..656babfc83 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
@@ -68,7 +68,7 @@ public class RunningRuleTest {
@Test
public void testInitAndStart() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("mix_rule");
alarmRule.setExpression("sum((increase(endpoint_cpm,5) + increase(endpoint_percent,2)) > 0) >= 1");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -77,7 +77,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.getMillis());
@@ -99,7 +99,7 @@ public class RunningRuleTest {
@Test
public void testAlarm() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 75) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -108,7 +108,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
@@ -130,7 +130,7 @@ public class RunningRuleTest {
@Test
public void testAlarmMetricsOutOfDate() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 75) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -139,7 +139,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(153).getMillis());
@@ -160,7 +160,7 @@ public class RunningRuleTest {
public void testLabeledAlarm() throws IllegalExpressionException {
ValueColumnMetadata.INSTANCE.putIfAbsent(
"endpoint_labeled", "testColumn", Column.ValueDataType.LABELED_VALUE, 0, Scope.Endpoint.getScopeId());
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setExpression("sum(endpoint_labeled{p='95,99'} > 10) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_labeled");
assertLabeled(alarmRule, "{p=50},17|{p=99},11", "{p=75},15|{p=95},12|{p=99},12", "{p=90},1|{p=99},20", 1);
@@ -181,7 +181,7 @@ public class RunningRuleTest {
}
private void multipleMetricsAlarm(String expression, int alarmMsgSize) throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression(expression);
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -191,7 +191,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
long timeInPeriod2 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(4).getMillis());
@@ -214,7 +214,7 @@ public class RunningRuleTest {
@Test
public void testNoAlarm() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent > 75) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -223,7 +223,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
final boolean[] isAlarm = {false};
AlarmCallback assertCallback = new AlarmCallback() {
@@ -262,7 +262,7 @@ public class RunningRuleTest {
@Test
public void testSilence() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 75) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -271,7 +271,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
@@ -301,7 +301,7 @@ public class RunningRuleTest {
@Test
public void testExclude() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 75) >= 3");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -311,7 +311,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
@@ -336,7 +336,7 @@ public class RunningRuleTest {
@Test
public void testIncludeNamesRegex() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 1000) >= 1");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -347,7 +347,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
@@ -372,7 +372,7 @@ public class RunningRuleTest {
@Test
public void testExcludeNamesRegex() throws IllegalExpressionException {
- AlarmRule alarmRule = new AlarmRule();
+ AlarmRule alarmRule = new AlarmRule(null);
alarmRule.setAlarmRuleName("endpoint_percent_rule");
alarmRule.setExpression("sum(endpoint_percent < 1000) >= 1");
alarmRule.getIncludeMetrics().add("endpoint_percent");
@@ -383,7 +383,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
@@ -583,7 +583,7 @@ public class RunningRuleTest {
alarmRule.setTags(new HashMap<String, String>() {{
put("key", "value");
}});
- RunningRule runningRule = new RunningRule(alarmRule);
+ RunningRule runningRule = new RunningRule(alarmRule, null);
DateTime startTime = DateTime.now();
long timeInPeriod1 = TimeBucket.getMinuteTimeBucket(startTime.minusMinutes(6).getMillis());
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/dingtalk/DingtalkHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/dingtalk/DingtalkHookCallbackTest.java
index 175d3349bb..dd0ab94094 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/dingtalk/DingtalkHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/dingtalk/DingtalkHookCallbackTest.java
@@ -90,7 +90,7 @@ public class DingtalkHookCallbackTest {
rules.getDingtalkSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getDingtalkSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
DingtalkHookCallback dingtalkCallBack = new DingtalkHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
@@ -125,7 +125,7 @@ public class DingtalkHookCallbackTest {
rules.getDingtalkSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getDingtalkSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
DingtalkHookCallback dingtalkCallBack = new DingtalkHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java
index 371e4f06e1..0accf98d1c 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/feishu/FeishuHookCallbackTest.java
@@ -88,7 +88,7 @@ public class FeishuHookCallbackTest {
rules.getFeishuSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getFeishuSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
FeishuHookCallback feishuHookCallback = new FeishuHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
@@ -123,7 +123,7 @@ public class FeishuHookCallbackTest {
rules.getFeishuSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getFeishuSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
FeishuHookCallback feishuHookCallback = new FeishuHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
@@ -158,7 +158,7 @@ public class FeishuHookCallbackTest {
rules.getFeishuSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getFeishuSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
FeishuHookCallback feishuHookCallback = new FeishuHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
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
index d4732e19da..9c2934108b 100644
--- 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
@@ -51,7 +51,7 @@ public class GRPChookCallbackTest {
rules.getGrpcAlarmSettingMap().put(setting1.getFormattedName(), setting1);
rules.getGrpcAlarmSettingMap().put(setting2.getFormattedName(), setting2);
- alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
grpcCallback = new GRPCCallback(alarmRulesWatcher);
mockAlarmMessage(setting1.getFormattedName(), setting2.getFormattedName());
}
@@ -68,7 +68,7 @@ public class GRPChookCallbackTest {
GRPCAlarmSetting setting2 = new GRPCAlarmSetting("setting2222222", AlarmHooksType.gRPC, true);
rules.getGrpcAlarmSettingMap().put(setting1.getFormattedName(), setting1);
rules.getGrpcAlarmSettingMap().put(setting2.getFormattedName(), setting2);
- alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
grpcCallback = new GRPCCallback(alarmRulesWatcher);
grpcCallback.doAlarm(alarmMessageList);
}
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/pagerduty/PagerDutyHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/pagerduty/PagerDutyHookCallbackTest.java
index 08b9c7b31d..17cab72dd4 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/pagerduty/PagerDutyHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/pagerduty/PagerDutyHookCallbackTest.java
@@ -50,7 +50,7 @@ public class PagerDutyHookCallbackTest {
rules.getPagerDutySettingsMap().put(setting1.getFormattedName(), setting1);
rules.getPagerDutySettingsMap().put(setting2.getFormattedName(), setting2);
PagerDutyHookCallback pagerDutyHookCallback = new PagerDutyHookCallback(
- new AlarmRulesWatcher(rules, null)
+ new AlarmRulesWatcher(rules, null, null)
);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/slack/SlackHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/slack/SlackHookCallbackTest.java
index 33e9ef105a..5cac6ec355 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/slack/SlackHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/slack/SlackHookCallbackTest.java
@@ -78,7 +78,7 @@ public class SlackHookCallbackTest {
setting2.setTextTemplate(template);
rules.getSlackSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getSlackSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
SlackhookCallback slackhookCallback = new SlackhookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/webhook/WebhookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/webhook/WebhookCallbackTest.java
index 587646f8d5..3c85f35bc2 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/webhook/WebhookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/webhook/WebhookCallbackTest.java
@@ -72,7 +72,7 @@ public class WebhookCallbackTest {
setting2.setUrls(remoteEndpoints);
rules.getWebhookSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getWebhookSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
WebhookCallback webhookCallback = new WebhookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/wechat/WechatHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/wechat/WechatHookCallbackTest.java
index eb555022e4..5f8c5a058b 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/wechat/WechatHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/wechat/WechatHookCallbackTest.java
@@ -79,7 +79,7 @@ public class WechatHookCallbackTest {
setting2.setTextTemplate(template);
rules.getWechatSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getWechatSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
WechatHookCallback wechatHookCallback = new WechatHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/welink/WeLinkHookCallbackTest.java b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/welink/WeLinkHookCallbackTest.java
index 0b0921b94d..511f0a3cfa 100644
--- a/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/welink/WeLinkHookCallbackTest.java
+++ b/oap-server/server-alarm-plugin/src/test/java/org/apache/skywalking/oap/server/core/alarm/provider/welink/WeLinkHookCallbackTest.java
@@ -89,7 +89,7 @@ public class WeLinkHookCallbackTest {
rules.getWeLinkSettingsMap().put(setting1.getFormattedName(), setting1);
rules.getWeLinkSettingsMap().put(setting2.getFormattedName(), setting2);
- AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null);
+ AlarmRulesWatcher alarmRulesWatcher = new AlarmRulesWatcher(rules, null, null);
WeLinkHookCallback welinkHookCallback = new WeLinkHookCallback(alarmRulesWatcher);
List<AlarmMessage> alarmMessages = new ArrayList<>(2);
AlarmMessage alarmMessage = new AlarmMessage();
diff --git a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
index 0d09ecf0e1..9fedf928fa 100644
--- a/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
+++ b/oap-server/server-query-plugin/query-graphql-plugin/src/main/java/org/apache/skywalking/oap/query/graphql/mqe/rt/MQEVisitor.java
@@ -73,7 +73,7 @@ public class MQEVisitor extends MQEVisitorBase {
public MQEVisitor(final ModuleManager moduleManager,
final Entity entity,
final Duration duration) {
- super(duration.getStep());
+ super(moduleManager, duration.getStep());
this.moduleManager = moduleManager;
this.entity = entity;
this.duration = duration;
@@ -153,6 +153,18 @@ public class MQEVisitor extends MQEVisitorBase {
MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
int trendRange = Integer.parseInt(parent.INTEGER().getText());
queryMetrics(metricName, getTrendQueryDuration(trendRange), result);
+ } else if (ctx.parent instanceof MQEParser.BaselineOPContext) {
+ MQEParser.BaselineOPContext parent = (MQEParser.BaselineOPContext) ctx.parent;
+ ArrayList<String> times = new ArrayList<>();
+ for (PointOfTime pointOfTime : duration.assembleDurationPoints()) {
+ times.add(Long.toString(pointOfTime.getPoint()));
+ }
+ List<MQEValues> valuesList = super.queryBaseline(
+ entity.getServiceName(), metricName, times,
+ parent.baseline_type().getStart().getType()
+ );
+ result.setResults(valuesList);
+ result.setType(ExpressionResultType.TIME_SERIES_VALUES);
} else {
queryMetrics(metricName, this.duration, result);
}
@@ -166,6 +178,18 @@ public class MQEVisitor extends MQEVisitorBase {
MQEParser.TrendOPContext parent = (MQEParser.TrendOPContext) ctx.parent;
int trendRange = Integer.parseInt(parent.INTEGER().getText());
queryLabeledMetrics(metricName, queryLabels, getTrendQueryDuration(trendRange), result);
+ } else if (ctx.parent instanceof MQEParser.BaselineOPContext) {
+ MQEParser.BaselineOPContext parent = (MQEParser.BaselineOPContext) ctx.parent;
+ ArrayList<String> times = new ArrayList<>();
+ for (PointOfTime pointOfTime : duration.assembleDurationPoints()) {
+ times.add(Long.toString(pointOfTime.getPoint()));
+ }
+ List<MQEValues> valuesList = super.queryLabeledBaseline(
+ entity.getServiceName(), metricName, queryLabels, times, parent.baseline_type()
+ .getStart()
+ .getType());
+ result.setResults(valuesList);
+ result.setType(ExpressionResultType.TIME_SERIES_VALUES);
} else {
queryLabeledMetrics(metricName, queryLabels, this.duration, result);
}
diff --git a/test/e2e-v2/cases/alarm/alarm-settings.yml b/test/e2e-v2/cases/alarm/alarm-settings.yml
index 04ddbc61cd..de072b729f 100755
--- a/test/e2e-v2/cases/alarm/alarm-settings.yml
+++ b/test/e2e-v2/cases/alarm/alarm-settings.yml
@@ -43,6 +43,15 @@ rules:
tags:
level: CRITICAL
receivers: zhangsan
+ baseline_rule:
+ expression: sum(service_resp_time > baseline(service_resp_time,upper)) >= 1
+ period: 10
+ message: Response time of service {name} is more than baseline in 1 minutes of last 10 minutes.
+ tags:
+ level: CRITICAL
+ receivers: zhangsan
+ hooks:
+ - webhook.none
hooks:
webhook:
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
index a08b02cad0..3be2aca755 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
@@ -30,11 +30,14 @@ services:
environment:
SW_STORAGE: banyandb
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
+ SW_BASELINE_SERVICE_HOST: baseline-server
ports:
- 12800
depends_on:
banyandb:
condition: service_healthy
+ baseline-server:
+ condition: service_healthy
volumes:
- ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
@@ -48,5 +51,20 @@ services:
oap:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+
networks:
e2e:
diff --git a/test/e2e-v2/cases/alarm/es/docker-compose.yml b/test/e2e-v2/cases/alarm/es/docker-compose.yml
index 4e5862e90d..6f30d90658 100644
--- a/test/e2e-v2/cases/alarm/es/docker-compose.yml
+++ b/test/e2e-v2/cases/alarm/es/docker-compose.yml
@@ -37,11 +37,14 @@ services:
environment:
SW_STORAGE: elasticsearch
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
+ SW_BASELINE_SERVICE_HOST: baseline-server
ports:
- 12800
depends_on:
es:
condition: service_healthy
+ baseline-server:
+ condition: service_healthy
volumes:
- ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
@@ -55,5 +58,20 @@ services:
oap:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+
networks:
e2e:
diff --git a/test/e2e-v2/cases/alarm/es/es-sharding/docker-compose.yml b/test/e2e-v2/cases/alarm/es/es-sharding/docker-compose.yml
index b7182c40f2..22f38c98fb 100644
--- a/test/e2e-v2/cases/alarm/es/es-sharding/docker-compose.yml
+++ b/test/e2e-v2/cases/alarm/es/es-sharding/docker-compose.yml
@@ -38,11 +38,14 @@ services:
SW_STORAGE: elasticsearch
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
SW_STORAGE_ES_LOGIC_SHARDING: "true"
+ SW_BASELINE_SERVICE_HOST: baseline-server
ports:
- 12800
depends_on:
es:
condition: service_healthy
+ baseline-server:
+ condition: service_healthy
volumes:
- ../../alarm-settings.yml:/skywalking/config/alarm-settings.yml
@@ -56,5 +59,20 @@ services:
oap:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+
networks:
- e2e:
\ No newline at end of file
+ e2e:
diff --git a/test/e2e-v2/cases/alarm/expected/silence-after-graphql-critical.yml b/test/e2e-v2/cases/alarm/expected/silence-after-graphql-critical.yml
index 0631c162b8..6fb600f2fa 100644
--- a/test/e2e-v2/cases/alarm/expected/silence-after-graphql-critical.yml
+++ b/test/e2e-v2/cases/alarm/expected/silence-after-graphql-critical.yml
@@ -58,4 +58,60 @@ msgs:
{{- end }}
{{- end }}
{{- end }}
+ - starttime: {{ gt .starttime 0 }}
+ scope: Service
+ id: ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1
+ name: e2e-service-provider
+ message: Response time of service e2e-service-provider is more than baseline in 1 minutes of last 10 minutes.
+ tags:
+ - key: level
+ value: CRITICAL
+ - key: receivers
+ value: zhangsan
+ events:
+ {{- contains .events }}
+ - uuid: {{ notEmpty .uuid }}
+ source:
+ service: e2e-service-provider
+ serviceinstance: ""
+ endpoint: ""
+ name: Alarm
+ type: ""
+ message: {{ notEmpty .message }}
+ parameters: []
+ starttime: {{ gt .starttime 0 }}
+ endtime: {{ gt .endtime 0 }}
+ layer: GENERAL
+ {{- end }}
+ snapshot:
+ expression: sum(service_resp_time > baseline(service_resp_time,upper)) >= 1
+ metrics:
+ {{- contains .snapshot.metrics }}
+ - name: service_resp_time
+ results:
+ {{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ owner: null
+ value: {{ .value }}
+ traceid: null
+ {{- end }}
+ {{- end }}
+ - name: baseline(service_resp_time,upper)
+ results:
+ {{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ owner: null
+ value: 10
+ traceid: null
+ {{- end }}
+ {{- end }}
+ {{- end }}
{{- end }}
diff --git a/test/e2e-v2/cases/alarm/expected/silence-after-graphql-warn.yml b/test/e2e-v2/cases/alarm/expected/silence-after-graphql-warn.yml
index f2c9abe6e2..e54e4bd6ab 100644
--- a/test/e2e-v2/cases/alarm/expected/silence-after-graphql-warn.yml
+++ b/test/e2e-v2/cases/alarm/expected/silence-after-graphql-warn.yml
@@ -44,7 +44,7 @@ msgs:
expression: sum(service_percentile{p='50,75,90,95,99'} > 10) >= 3
metrics:
{{- contains .snapshot.metrics }}
- - name: service_percentile
+ - name: service_percentile{p='50,75,90,95,99'}
results:
{{- contains .results }}
- metric:
@@ -103,4 +103,4 @@ msgs:
{{- end }}
{{- end }}
{{- end }}
- {{- end }}
\ No newline at end of file
+ {{- end }}
diff --git a/test/e2e-v2/cases/alarm/expected/silence-before-graphql-critical.yml b/test/e2e-v2/cases/alarm/expected/silence-before-graphql-critical.yml
index 0631c162b8..6fb600f2fa 100644
--- a/test/e2e-v2/cases/alarm/expected/silence-before-graphql-critical.yml
+++ b/test/e2e-v2/cases/alarm/expected/silence-before-graphql-critical.yml
@@ -58,4 +58,60 @@ msgs:
{{- end }}
{{- end }}
{{- end }}
+ - starttime: {{ gt .starttime 0 }}
+ scope: Service
+ id: ZTJlLXNlcnZpY2UtcHJvdmlkZXI=.1
+ name: e2e-service-provider
+ message: Response time of service e2e-service-provider is more than baseline in 1 minutes of last 10 minutes.
+ tags:
+ - key: level
+ value: CRITICAL
+ - key: receivers
+ value: zhangsan
+ events:
+ {{- contains .events }}
+ - uuid: {{ notEmpty .uuid }}
+ source:
+ service: e2e-service-provider
+ serviceinstance: ""
+ endpoint: ""
+ name: Alarm
+ type: ""
+ message: {{ notEmpty .message }}
+ parameters: []
+ starttime: {{ gt .starttime 0 }}
+ endtime: {{ gt .endtime 0 }}
+ layer: GENERAL
+ {{- end }}
+ snapshot:
+ expression: sum(service_resp_time > baseline(service_resp_time,upper)) >= 1
+ metrics:
+ {{- contains .snapshot.metrics }}
+ - name: service_resp_time
+ results:
+ {{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ owner: null
+ value: {{ .value }}
+ traceid: null
+ {{- end }}
+ {{- end }}
+ - name: baseline(service_resp_time,upper)
+ results:
+ {{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ owner: null
+ value: 10
+ traceid: null
+ {{- end }}
+ {{- end }}
+ {{- end }}
{{- end }}
diff --git a/test/e2e-v2/cases/alarm/expected/silence-before-graphql-warn.yml b/test/e2e-v2/cases/alarm/expected/silence-before-graphql-warn.yml
index 2bf89eb7b1..e25f5cf614 100644
--- a/test/e2e-v2/cases/alarm/expected/silence-before-graphql-warn.yml
+++ b/test/e2e-v2/cases/alarm/expected/silence-before-graphql-warn.yml
@@ -44,7 +44,7 @@ msgs:
expression: sum(service_percentile{p='50,75,90,95,99'} > 10) >= 3
metrics:
{{- contains .snapshot.metrics }}
- - name: service_percentile
+ - name: service_percentile{p='50,75,90,95,99'}
results:
{{- contains .results }}
- metric:
diff --git a/test/e2e-v2/cases/alarm/mysql/docker-compose.yml b/test/e2e-v2/cases/alarm/mysql/docker-compose.yml
index 0de65f5e04..19711a7e73 100644
--- a/test/e2e-v2/cases/alarm/mysql/docker-compose.yml
+++ b/test/e2e-v2/cases/alarm/mysql/docker-compose.yml
@@ -39,12 +39,15 @@ services:
environment:
SW_STORAGE: mysql
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
+ SW_BASELINE_SERVICE_HOST: baseline-server
entrypoint: ['sh', '-c', '/download-mysql.sh /skywalking/oap-libs && /skywalking/docker-entrypoint.sh']
ports:
- 12800
depends_on:
mysql:
condition: service_healthy
+ baseline-server:
+ condition: service_healthy
volumes:
- ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
@@ -58,5 +61,19 @@ services:
oap:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
networks:
e2e:
diff --git a/test/e2e-v2/cases/alarm/postgres/docker-compose.yml b/test/e2e-v2/cases/alarm/postgres/docker-compose.yml
index 11c5f30cc1..98c8c258e1 100644
--- a/test/e2e-v2/cases/alarm/postgres/docker-compose.yml
+++ b/test/e2e-v2/cases/alarm/postgres/docker-compose.yml
@@ -39,11 +39,14 @@ services:
SW_STORAGE: postgresql
SW_JDBC_URL: "jdbc:postgresql://postgres:5432/skywalking"
SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
+ SW_BASELINE_SERVICE_HOST: baseline-server
ports:
- 12800
depends_on:
postgres:
condition: service_healthy
+ baseline-server:
+ condition: service_healthy
volumes:
- ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
@@ -57,5 +60,20 @@ services:
oap:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
+
networks:
e2e:
diff --git a/test/e2e-v2/cases/mqe/docker-compose.yml b/test/e2e-v2/cases/mqe/docker-compose.yml
index 9b487d180f..337189fe47 100644
--- a/test/e2e-v2/cases/mqe/docker-compose.yml
+++ b/test/e2e-v2/cases/mqe/docker-compose.yml
@@ -22,6 +22,13 @@ services:
service: oap
volumes:
- ./oal/core.oal:/skywalking/config/oal/core.oal
+ environment:
+ SW_BASELINE_SERVICE_HOST: baseline-server
+ depends_on:
+ banyandb:
+ condition: service_healthy
+ baseline-server:
+ condition: service_healthy
ports:
- 12800
networks:
@@ -54,5 +61,19 @@ services:
provider:
condition: service_healthy
+ baseline-server:
+ image: "eclipse-temurin:11-jre"
+ volumes:
+ - ../../java-test-service/e2e-mock-baseline-server/target/e2e-mock-baseline-server-2.0.0.jar:/e2e-mock-baseline-server-2.0.0.jar
+ command: [ "java", "-jar", "/e2e-mock-baseline-server-2.0.0.jar" ]
+ networks:
+ - e2e
+ ports:
+ - 18080
+ healthcheck:
+ test: ["CMD", "bash", "-c", "cat < /dev/null > /dev/tcp/127.0.0.1/18080"]
+ interval: 5s
+ timeout: 60s
+ retries: 120
networks:
e2e:
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/cases/mqe/expected/baseline-OP.yml
similarity index 51%
copy from test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
copy to test/e2e-v2/cases/mqe/expected/baseline-OP.yml
index a08b02cad0..684c0bfd90 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/cases/mqe/expected/baseline-OP.yml
@@ -13,40 +13,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-version: '2.1'
-
-services:
- banyandb:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: banyandb
- networks:
- - e2e
-
- oap:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: oap
- environment:
- SW_STORAGE: banyandb
- SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
- ports:
- - 12800
- depends_on:
- banyandb:
- condition: service_healthy
- volumes:
- - ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
-
- provider:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: provider
- ports:
- - 9090
- depends_on:
- oap:
- condition: service_healthy
-
-networks:
- e2e:
+debuggingtrace: null
+type: TIME_SERIES_VALUES
+results:
+{{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: {{ .value }}
+ traceid: null
+ owner: null
+ {{- end}}
+{{- end}}
+error: null
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/cases/mqe/expected/baseline-label-OP.yml
similarity index 51%
copy from test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
copy to test/e2e-v2/cases/mqe/expected/baseline-label-OP.yml
index a08b02cad0..eb009303f8 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/cases/mqe/expected/baseline-label-OP.yml
@@ -13,40 +13,31 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-version: '2.1'
-
-services:
- banyandb:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: banyandb
- networks:
- - e2e
-
- oap:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: oap
- environment:
- SW_STORAGE: banyandb
- SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
- ports:
- - 12800
- depends_on:
- banyandb:
- condition: service_healthy
- volumes:
- - ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
-
- provider:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: provider
- ports:
- - 9090
- depends_on:
- oap:
- condition: service_healthy
-
-networks:
- e2e:
+debuggingtrace: null
+type: TIME_SERIES_VALUES
+results:
+{{- contains .results }}
+ - metric:
+ labels:
+ - key: p
+ value: "95"
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: 100
+ traceid: null
+ owner: null
+ {{- end}}
+ - metric:
+ labels:
+ - key: p
+ value: "99"
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: 100
+ traceid: null
+ owner: null
+ {{- end}}
+{{- end}}
+error: null
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/cases/mqe/expected/baseline-lower-OP.yml
similarity index 51%
copy from test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
copy to test/e2e-v2/cases/mqe/expected/baseline-lower-OP.yml
index a08b02cad0..b0f8cb7411 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/cases/mqe/expected/baseline-lower-OP.yml
@@ -13,40 +13,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-version: '2.1'
-
-services:
- banyandb:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: banyandb
- networks:
- - e2e
-
- oap:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: oap
- environment:
- SW_STORAGE: banyandb
- SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
- ports:
- - 12800
- depends_on:
- banyandb:
- condition: service_healthy
- volumes:
- - ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
-
- provider:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: provider
- ports:
- - 9090
- depends_on:
- oap:
- condition: service_healthy
-
-networks:
- e2e:
+debuggingtrace: null
+type: TIME_SERIES_VALUES
+results:
+{{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: 0
+ traceid: null
+ owner: null
+ {{- end}}
+{{- end}}
+error: null
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/cases/mqe/expected/baseline-upper-OP.yml
similarity index 51%
copy from test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
copy to test/e2e-v2/cases/mqe/expected/baseline-upper-OP.yml
index a08b02cad0..ab01c09318 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/cases/mqe/expected/baseline-upper-OP.yml
@@ -13,40 +13,18 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-version: '2.1'
-
-services:
- banyandb:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: banyandb
- networks:
- - e2e
-
- oap:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: oap
- environment:
- SW_STORAGE: banyandb
- SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
- ports:
- - 12800
- depends_on:
- banyandb:
- condition: service_healthy
- volumes:
- - ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
-
- provider:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: provider
- ports:
- - 9090
- depends_on:
- oap:
- condition: service_healthy
-
-networks:
- e2e:
+debuggingtrace: null
+type: TIME_SERIES_VALUES
+results:
+{{- contains .results }}
+ - metric:
+ labels: []
+ values:
+ {{- contains .values }}
+ - id: {{ notEmpty .id }}
+ value: 1000
+ traceid: null
+ owner: null
+ {{- end}}
+{{- end}}
+error: null
diff --git a/test/e2e-v2/cases/mqe/mqe-cases.yaml b/test/e2e-v2/cases/mqe/mqe-cases.yaml
index 4777a8c400..506cf4ec2b 100644
--- a/test/e2e-v2/cases/mqe/mqe-cases.yaml
+++ b/test/e2e-v2/cases/mqe/mqe-cases.yaml
@@ -108,3 +108,13 @@ cases:
# sort-label-value-OP
- query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="sort_label_values(service_percentile{p='50,75,90'},des,p)" --service-name=e2e-service-provider
expected: expected/sort-label-value-OP.yml
+
+ # baseline
+ - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="baseline(service_cpm,upper)" --service-name=e2e-service-provider
+ expected: expected/baseline-upper-OP.yml
+ - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="baseline(service_cpm,lower)" --service-name=e2e-service-provider
+ expected: expected/baseline-lower-OP.yml
+ - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="baseline(service_cpm,value)" --service-name=e2e-service-provider
+ expected: expected/baseline-OP.yml
+ - query: swctl --display yaml --base-url=http://${oap_host}:${oap_12800}/graphql metrics exec --expression="baseline(service_percentile{p='95,99'},upper)" --service-name=e2e-service-provider
+ expected: expected/baseline-label-OP.yml
diff --git a/test/e2e-v2/cases/storage/banyandb/gen-certs.sh b/test/e2e-v2/cases/storage/banyandb/gen-certs.sh
new file mode 100755
index 0000000000..fea87c6c60
--- /dev/null
+++ b/test/e2e-v2/cases/storage/banyandb/gen-certs.sh
@@ -0,0 +1,51 @@
+# 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.
+
+#!/bin/bash
+
+set -e
+
+# Number of days the certificates will be valid
+DAYS=36500 # 100 years
+DOMAIN=banyandb
+OUTDIR=tls
+
+
+pushd .
+mkdir -p ${OUTDIR}
+cd ${OUTDIR}
+
+echo "Generating the CA..."
+openssl genrsa -out ca.key 2048
+openssl req -x509 -new -nodes -key ca.key -sha256 -out ca.crt -days ${DAYS} -subj "/C=CN/ST=Test/L=Test/O=SkyWalking"
+openssl x509 -in ca.crt -text
+
+echo "Generating the BanyanDB server certificate..."
+openssl genrsa -out cert.key 2048
+openssl req -new -key cert.key -out cert.csr -subj "/C=CN/ST=Test/L=Test/O=SkyWalking/CN=${DOMAIN}"
+openssl x509 -req -extfile <(printf "subjectAltName=DNS:${DOMAIN}") -in cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out cert.crt -days ${DAYS} -sha256
+#openssl x509 -req -extfile <(printf "subjectAltName=IP:127.0.0.1,DNS:${DOMAIN}") -in cert.csr -CA ca.crt -CAkey ca.key -CAcreateserial -out cert.crt -days ${DAYS} -sha256
+#openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout key.pem -out cert.pem -subj "/CN=localhost" -extensions san -config <(echo "[req]"; echo distinguished_name=req; echo "[san]"; echo "subjectAltName=IP:127.0.0.1,DNS:localhost")
+openssl x509 -in cert.crt -text
+
+echo "Importing the certificates into a Java keystore..."
+keytool -keystore KeyStore.jks -alias tetrate -import -file cert.crt -storepass temporal -validity ${DAYS}
+
+popd
+
+echo
+echo "CA and certificates have been created."
+echo "cert.crt have been imported into KeyStore.jks."
diff --git a/test/e2e-v2/java-test-service/e2e-mock-baseline-server/pom.xml b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/pom.xml
new file mode 100644
index 0000000000..167c1bd65c
--- /dev/null
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/pom.xml
@@ -0,0 +1,134 @@
+<?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/xsd/maven-4.0.0.xsd">
+ <parent>
+ <artifactId>apache-skywalking-e2e</artifactId>
+ <groupId>org.apache.skywalking</groupId>
+ <version>2.0.0</version>
+ </parent>
+
+ <modelVersion>4.0.0</modelVersion>
+
+ <packaging>jar</packaging>
+
+ <artifactId>e2e-mock-baseline-server</artifactId>
+
+ <properties>
+ <grpc.version>1.43.2</grpc.version>
+ <os-maven-plugin.version>1.5.0.Final</os-maven-plugin.version>
+ <protobuf-maven-plugin.version>0.6.1</protobuf-maven-plugin.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-protobuf</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-stub</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-netty</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>com.google.guava</groupId>
+ <artifactId>guava</artifactId>
+ <version>23.0</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-core</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ <dependency>
+ <groupId>io.grpc</groupId>
+ <artifactId>grpc-api</artifactId>
+ <version>${grpc.version}</version>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.springframework.boot</groupId>
+ <artifactId>spring-boot-maven-plugin</artifactId>
+ <version>${spring.boot.version}</version>
+ <configuration>
+ <executable>true</executable>
+ <addResources>true</addResources>
+ <excludeDevtools>true</excludeDevtools>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>repackage</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <plugin>
+ <groupId>kr.motd.maven</groupId>
+ <artifactId>os-maven-plugin</artifactId>
+ <version>${os-maven-plugin.version}</version>
+ <executions>
+ <execution>
+ <phase>initialize</phase>
+ <goals>
+ <goal>detect</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ <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:3.19.2:exe:${os.detected.classifier}
+ </protocArtifact>
+ <pluginId>grpc-java</pluginId>
+ <pluginArtifact>io.grpc:protoc-gen-grpc-java:1.42.1:exe:${os.detected.classifier}
+ </pluginArtifact>
+ </configuration>
+ <executions>
+ <execution>
+ <goals>
+ <goal>compile</goal>
+ <goal>compile-custom</goal>
+ </goals>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </build>
+</project>
diff --git a/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/BaselineQueryServer.java b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/BaselineQueryServer.java
new file mode 100644
index 0000000000..3f59956b98
--- /dev/null
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/BaselineQueryServer.java
@@ -0,0 +1,195 @@
+/*
+ * 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.e2e;
+
+import com.google.protobuf.Empty;
+import io.grpc.stub.StreamObserver;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Random;
+import java.util.stream.Collectors;
+import lombok.Builder;
+import lombok.Data;
+import org.apache.skywalking.apm.baseline.v3.AlarmBaselineLabeledValue;
+import org.apache.skywalking.apm.baseline.v3.AlarmBaselineMetricsNames;
+import org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceGrpc;
+import org.apache.skywalking.apm.baseline.v3.AlarmBaselineValue;
+import org.apache.skywalking.apm.baseline.v3.KeyStringValuePair;
+
+public class BaselineQueryServer extends AlarmBaselineServiceGrpc.AlarmBaselineServiceImplBase {
+
+ private static final Random RANDOM = new Random(System.currentTimeMillis());
+
+ private static final Map<String, MetricConfig> VALUE_GENERATOR = new HashMap<>();
+
+ static {
+ VALUE_GENERATOR.put("service_cpm", MetricConfig.builder()
+ .single(true)
+ .singleValue(
+ MetricsValueConfig.builder().minValue(0).maxValue(1000).build()).build());
+ VALUE_GENERATOR.put("service_sla", MetricConfig.builder()
+ .single(true)
+ .singleValue(
+ MetricsValueConfig.builder().minValue(8000).maxValue(10000).build()).build());
+ VALUE_GENERATOR.put("service_apdex", MetricConfig.builder()
+ .single(true)
+ .singleValue(MetricsValueConfig.builder().minValue(8000).maxValue(10000).build()).build());
+ VALUE_GENERATOR.put("service_resp_time", MetricConfig.builder()
+ .single(true)
+ .singleValue(MetricsValueConfig.builder().minValue(1).maxValue(10).build()).build());
+ VALUE_GENERATOR.put("service_percentile", MetricConfig.builder()
+ .single(false)
+ .multiValue(new HashMap<KeyStringValuePair, MetricsValueConfig>() {
+ {
+ put(KeyStringValuePair.newBuilder().setKey("p").setValue("50").build(),
+ MetricsValueConfig.builder().minValue(0).maxValue(100).build());
+ put(KeyStringValuePair.newBuilder().setKey("p").setValue("75").build(),
+ MetricsValueConfig.builder().minValue(0).maxValue(100).build());
+ put(KeyStringValuePair.newBuilder().setKey("p").setValue("90").build(),
+ MetricsValueConfig.builder().minValue(0).maxValue(100).build());
+ put(KeyStringValuePair.newBuilder().setKey("p").setValue("95").build(),
+ MetricsValueConfig.builder().minValue(0).maxValue(100).build());
+ put(KeyStringValuePair.newBuilder().setKey("p").setValue("99").build(),
+ MetricsValueConfig.builder().minValue(0).maxValue(100).build());
+ }
+ }).build());
+ VALUE_GENERATOR.put("service_status_code", MetricConfig.builder()
+ .single(false)
+ .multiValue(new HashMap<KeyStringValuePair, MetricsValueConfig>() {
+ {
+ put(KeyStringValuePair.newBuilder().setKey("status").setValue("200").build(),
+ MetricsValueConfig.builder().minValue(10).maxValue(1000).build());
+ put(KeyStringValuePair.newBuilder().setKey("status").setValue("400").build(),
+ MetricsValueConfig.builder().minValue(10).maxValue(1000).build());
+ put(KeyStringValuePair.newBuilder().setKey("status").setValue("500").build(),
+ MetricsValueConfig.builder().minValue(10).maxValue(1000).build());
+ }
+ })
+ .build());
+ }
+
+ @Override
+ public void querySupportedMetricsNames(Empty request, StreamObserver<AlarmBaselineMetricsNames> responseObserver) {
+ responseObserver.onNext(AlarmBaselineMetricsNames.newBuilder()
+ .addAllMetricNames(VALUE_GENERATOR.keySet())
+ .build());
+ responseObserver.onCompleted();
+ }
+
+ @Override
+ public void queryPredictedMetrics(org.apache.skywalking.apm.baseline.v3.AlarmBaselineRequest request, StreamObserver<org.apache.skywalking.apm.baseline.v3.AlarmBaselineResponse> responseObserver) {
+ final List<org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceMetric> metrics = new ArrayList<>();
+ final List<Long> timeBucketRange = generateTimeBucketRange(request);
+
+ for (org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceMetricName serviceMetricName : request.getServiceMetricNamesList()) {
+ final List<org.apache.skywalking.apm.baseline.v3.AlarmBaselineMetricPrediction> predictions = new ArrayList<>();
+
+ for (String metricName : serviceMetricName.getMetricNamesList()) {
+ final List<org.apache.skywalking.apm.baseline.v3.AlarmBaselinePredicatedValue> values = timeBucketRange.stream()
+ .map(t -> VALUE_GENERATOR.get(metricName).generate(t))
+ .collect(Collectors.toList());
+
+ predictions.add(org.apache.skywalking.apm.baseline.v3.AlarmBaselineMetricPrediction.newBuilder()
+ .setName(metricName)
+ .addAllValues(values)
+ .build());
+ }
+
+ metrics.add(org.apache.skywalking.apm.baseline.v3.AlarmBaselineServiceMetric.newBuilder()
+ .setServiceName(serviceMetricName.getServiceName())
+ .addAllPredictions(predictions)
+ .build());
+ }
+
+ responseObserver.onNext(org.apache.skywalking.apm.baseline.v3.AlarmBaselineResponse.newBuilder().addAllServiceMetrics(metrics).build());
+ responseObserver.onCompleted();
+ }
+
+ private List<Long> generateTimeBucketRange(org.apache.skywalking.apm.baseline.v3.AlarmBaselineRequest request) {
+ if (request.getStep() != org.apache.skywalking.apm.baseline.v3.TimeBucketStep.HOUR) {
+ return Collections.emptyList();
+ }
+
+ final Calendar start = Calendar.getInstance();
+ start.setTimeInMillis(TimeBucket.getTimestamp(request.getStartTimeBucket(), DownSampling.Hour));
+
+ final Calendar end = Calendar.getInstance();
+ end.setTimeInMillis(TimeBucket.getTimestamp(request.getEndTimeBucket(), DownSampling.Hour));
+
+ final ArrayList<Long> result = new ArrayList<>();
+ while (start.getTimeInMillis() <= end.getTimeInMillis()) {
+ result.add(TimeBucket.getTimeBucket(start.getTimeInMillis(), DownSampling.Hour));
+ start.add(Calendar.HOUR, 1);
+ }
+ return result;
+ }
+
+ @Data
+ @Builder
+ private static class MetricConfig {
+ private boolean single;
+ private MetricsValueConfig singleValue;
+ private Map<KeyStringValuePair, MetricsValueConfig> multiValue;
+
+ public org.apache.skywalking.apm.baseline.v3.AlarmBaselinePredicatedValue generate(long timeBucket) {
+ if (single) {
+ return org.apache.skywalking.apm.baseline.v3.AlarmBaselinePredicatedValue.newBuilder()
+ .setTimeBucket(timeBucket)
+ .setSingleValue(org.apache.skywalking.apm.baseline.v3.AlarmBaselineSingleValue.newBuilder().setValue(singleValue.generateValue()))
+ .build();
+ }
+
+ final org.apache.skywalking.apm.baseline.v3.AlarmBaselinePredicatedValue.Builder builder = org.apache.skywalking.apm.baseline.v3.AlarmBaselinePredicatedValue.newBuilder();
+ builder.setTimeBucket(timeBucket);
+ builder.setLabeledValue(AlarmBaselineLabeledValue.newBuilder()
+ .addAllValues(multiValue.entrySet().stream()
+ .map(e -> AlarmBaselineLabeledValue.LabelWithValue.newBuilder()
+ .addLabels(e.getKey())
+ .setValue(e.getValue().generateValue())
+ .build())
+ .collect(Collectors.toList()))
+ .build());
+ return builder.build();
+ }
+ }
+
+ @Data
+ @Builder
+ private static class MetricsValueConfig {
+ private long minValue;
+ private long maxValue;
+
+ public AlarmBaselineValue generateValue() {
+ final AlarmBaselineValue.Builder valueBuilder = AlarmBaselineValue.newBuilder();
+ valueBuilder.setLowerValue(minValue);
+ valueBuilder.setUpperValue(maxValue);
+ valueBuilder.setValue(generateRandomValue(valueBuilder.getLowerValue(), valueBuilder.getUpperValue()));
+ return valueBuilder.build();
+ }
+ }
+
+ private static long generateRandomValue(long minValue, long maxValue) {
+ int range = Math.toIntExact(maxValue - minValue);
+ return minValue + RANDOM.nextInt(range);
+ }
+}
diff --git a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/DownSampling.java
similarity index 55%
copy from oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
copy to test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/DownSampling.java
index 3bf9818918..33ade18d5d 100644
--- a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/DownSampling.java
@@ -13,24 +13,37 @@
* 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.baseline.service;
-
-import org.apache.skywalking.oap.server.library.module.Service;
+package org.apache.skywalking.e2e;
-import java.util.List;
-
-public interface BaselineQueryService extends Service {
+public enum DownSampling {
/**
- * query supported query baseline metrics names
- * @return
+ * None downsampling is for un-time-series data.
*/
- List<String> querySupportedMetrics();
-
+ None(0, ""),
/**
- * query predict metrics
+ * Second downsampling is not for metrics, but for record, profile and top n. Those are details but don't do
+ * aggregation, and still merge into day level in the persistence.
*/
- List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket);
+ Second(1, "second"),
+ Minute(2, "minute"),
+ Hour(3, "hour"),
+ Day(4, "day");
+
+ private final int value;
+ private final String name;
+
+ DownSampling(int value, String name) {
+ this.value = value;
+ this.name = name;
+ }
+
+ public int getValue() {
+ return value;
+ }
+
+ public String getName() {
+ return name;
+ }
}
diff --git a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/KeyValue.java
similarity index 57%
copy from oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
copy to test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/KeyValue.java
index 3bf9818918..64bb447d16 100644
--- a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/KeyValue.java
@@ -6,31 +6,24 @@
* (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
+ * 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.baseline.service;
-
-import org.apache.skywalking.oap.server.library.module.Service;
+package org.apache.skywalking.e2e;
-import java.util.List;
+import lombok.Data;
+import lombok.experimental.Accessors;
-public interface BaselineQueryService extends Service {
- /**
- * query supported query baseline metrics names
- * @return
- */
- List<String> querySupportedMetrics();
+@Data
+@Accessors(chain = true)
+public class KeyValue {
- /**
- * query predict metrics
- */
- List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket);
+ private String key;
+ private String value;
}
diff --git a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/ServiceApplication.java
similarity index 55%
copy from oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
copy to test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/ServiceApplication.java
index 3bf9818918..a7febabf2e 100644
--- a/oap-server/metrics-baseline/src/main/java/org/apache/skywalking/oap/server/baseline/service/BaselineQueryService.java
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/ServiceApplication.java
@@ -16,21 +16,23 @@
*
*/
-package org.apache.skywalking.oap.server.baseline.service;
+package org.apache.skywalking.e2e;
-import org.apache.skywalking.oap.server.library.module.Service;
+import io.grpc.Server;
+import io.grpc.netty.NettyServerBuilder;
+import java.net.InetSocketAddress;
+import lombok.SneakyThrows;
-import java.util.List;
-
-public interface BaselineQueryService extends Service {
- /**
- * query supported query baseline metrics names
- * @return
- */
- List<String> querySupportedMetrics();
-
- /**
- * query predict metrics
- */
- List<PredictServiceMetrics> queryPredictMetrics(List<ServiceMetrics> serviceMetrics, long startTimeBucket, long endTimeBucket);
+public class ServiceApplication {
+ @SneakyThrows
+ public static void main(String[] args) {
+ Server server;
+ NettyServerBuilder nettyServerBuilder;
+ InetSocketAddress address = new InetSocketAddress("0.0.0.0", 18080);
+ nettyServerBuilder = NettyServerBuilder.forAddress(address);
+ nettyServerBuilder.addService(new BaselineQueryServer());
+ server = nettyServerBuilder.build();
+ server.start();
+ server.awaitTermination();
+ }
}
diff --git a/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/TimeBucket.java b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/TimeBucket.java
new file mode 100644
index 0000000000..b1d59cb07f
--- /dev/null
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/java/org/apache/skywalking/e2e/TimeBucket.java
@@ -0,0 +1,194 @@
+/*
+ * 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.e2e;
+
+import java.util.Calendar;
+
+public class TimeBucket {
+
+ /**
+ * Record time bucket format in Second Unit.
+ *
+ * @param time Timestamp
+ * @return time in second format
+ */
+ public static long getRecordTimeBucket(long time) {
+ return getTimeBucket(time, DownSampling.Second);
+ }
+
+ /**
+ * Record time bucket format in Minute Unit.
+ *
+ * @param time Timestamp
+ * @return time in minute format
+ */
+ public static long getMinuteTimeBucket(long time) {
+ return getTimeBucket(time, DownSampling.Minute);
+ }
+
+ /**
+ * Convert TimeBucket to Timestamp in millisecond.
+ *
+ * @param timeBucket long
+ * @return timestamp in millisecond unit
+ */
+ public static long getTimestamp(long timeBucket) {
+ if (isSecondBucket(timeBucket)) {
+ return getTimestamp(timeBucket, DownSampling.Second);
+ } else if (isMinuteBucket(timeBucket)) {
+ return getTimestamp(timeBucket, DownSampling.Minute);
+ } else if (isHourBucket(timeBucket)) {
+ return getTimestamp(timeBucket, DownSampling.Hour);
+ } else if (isDayBucket(timeBucket)) {
+ return getTimestamp(timeBucket, DownSampling.Day);
+ } else {
+ throw new UnsupportedOperationException("Unknown downsampling value.");
+ }
+ }
+
+ /**
+ * The format of timeBucket in minute Unit is "yyyyMMddHHmmss", so which means the TimeBucket must be between
+ * 10000000000000 and 99999999999999.
+ */
+ public static boolean isSecondBucket(long timeBucket) {
+ return timeBucket < 99999999999999L && timeBucket > 10000000000000L;
+ }
+
+ /**
+ * The format of timeBucket in minute Unit is "yyyyMMddHHmm", so which means the TimeBucket must be between
+ * 100000000000 and 999999999999.
+ */
+ public static boolean isMinuteBucket(long timeBucket) {
+ return timeBucket < 999999999999L && timeBucket > 100000000000L;
+ }
+
+ /**
+ * The format of timeBucket in hour Unit is "yyyyMMddHH", so which means the TimeBucket must be between 1000000000
+ * and 9999999999.
+ */
+ public static boolean isHourBucket(long timeBucket) {
+ return timeBucket < 9999999999L && timeBucket > 1000000000L;
+ }
+
+ /**
+ * The format of timeBucket in day Unit is "yyyyMMdd", so which means the TimeBucket must be between 10000000 and
+ * 99999999.
+ */
+ public static boolean isDayBucket(long timeBucket) {
+ return timeBucket < 99999999L && timeBucket > 10000000L;
+ }
+
+ /**
+ * Convert TimeBucket to Timestamp in millisecond.
+ *
+ * @param timeBucket long
+ * @param downsampling Downsampling
+ * @return timestamp in millisecond unit
+ */
+ public static long getTimestamp(long timeBucket, DownSampling downsampling) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(0);
+ calendar.set(Calendar.MINUTE, 0);
+ calendar.set(Calendar.HOUR_OF_DAY, 0);
+
+ switch (downsampling) {
+ case Second:
+ calendar.set(Calendar.SECOND, (int) (timeBucket % 100));
+ timeBucket /= 100;
+ // Fall through
+ case Minute:
+ calendar.set(Calendar.MINUTE, (int) (timeBucket % 100));
+ timeBucket /= 100;
+ // Fall through
+ case Hour:
+ calendar.set(Calendar.HOUR_OF_DAY, (int) (timeBucket % 100));
+ timeBucket /= 100;
+ // Fall through
+ case Day:
+ calendar.set(Calendar.DAY_OF_MONTH, (int) (timeBucket % 100));
+ timeBucket /= 100;
+ calendar.set(Calendar.MONTH, (int) (timeBucket % 100) - 1);
+ calendar.set(Calendar.YEAR, (int) (timeBucket / 100));
+ break;
+ default:
+ throw new UnsupportedOperationException("Unknown downsampling value.");
+ }
+ return calendar.getTimeInMillis();
+ }
+
+ /**
+ * Record timestamp bucket format in Downsampling Unit.
+ *
+ * @param timestamp Timestamp
+ * @param downsampling Downsampling
+ * @return timestamp in downsampling format
+ */
+ public static long getTimeBucket(long timestamp, DownSampling downsampling) {
+ Calendar calendar = Calendar.getInstance();
+ calendar.setTimeInMillis(timestamp);
+
+ long year = calendar.get(Calendar.YEAR);
+ long month = calendar.get(Calendar.MONTH) + 1;
+ long day = calendar.get(Calendar.DAY_OF_MONTH);
+ long hour = calendar.get(Calendar.HOUR_OF_DAY);
+ long minute = calendar.get(Calendar.MINUTE);
+ long second = calendar.get(Calendar.SECOND);
+
+ switch (downsampling) {
+ case Second:
+ return year * 10000000000L + month * 100000000 + day * 1000000 + hour * 10000 + minute * 100 + second;
+ case Minute:
+ return year * 100000000 + month * 1000000 + day * 10000 + hour * 100 + minute;
+ case Hour:
+ return year * 1000000 + month * 10000 + day * 100 + hour;
+ case Day:
+ return year * 10000 + month * 100 + day;
+ default:
+ throw new UnsupportedOperationException("Unknown downsampling value.");
+ }
+ }
+
+ /**
+ * Retain the minute time bucket to day time bucket. The format of timeBucket in minute format is "yyyyMMddHHmm", `HHmm` will be set to `0000`.
+ * minuteTimeBucket `202407112218` will be converted to `202407110000`.
+ * @param minuteTimeBucket minuteTimeBucket
+ * @return minute time bucket in day precision
+ */
+ public static long retainToDay4MinuteBucket(long minuteTimeBucket) {
+ if (isMinuteBucket(minuteTimeBucket)) {
+ return minuteTimeBucket / 10000 * 10000;
+ } else {
+ throw new UnsupportedOperationException("Current time bucket is not a minute time bucket");
+ }
+ }
+
+ /**
+ * Retain the minute time bucket to day time bucket. The format of timeBucket in minute format is "yyyyMMddHHmm", `HHmm` will be set to `2359`.
+ * minuteTimeBucket `202407112218` will be converted to `202407112359`.
+ * @param minuteTimeBucket minuteTimeBucket
+ * @return minute time bucket in day precision
+ */
+ public static long retainToDayLastMin4MinuteBucket(long minuteTimeBucket) {
+ if (isMinuteBucket(minuteTimeBucket)) {
+ return minuteTimeBucket / 10000 * 10000 + 2359;
+ } else {
+ throw new UnsupportedOperationException("Current time bucket is not a minute time bucket");
+ }
+ }
+}
+
diff --git a/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/proto/baseline.proto b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/proto/baseline.proto
new file mode 100644
index 0000000000..dafbd8cfbb
--- /dev/null
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/proto/baseline.proto
@@ -0,0 +1,118 @@
+/*
+ * 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.
+ *
+ */
+
+syntax = "proto3";
+package skywalking.baseline.v3;
+
+import "google/protobuf/empty.proto";
+
+option java_multiple_files = true;
+option java_package = "org.apache.skywalking.apm.baseline.v3";
+
+service AlarmBaselineService {
+ // Query the supported metrics names.
+ rpc querySupportedMetricsNames(google.protobuf.Empty) returns (AlarmBaselineMetricsNames);
+ // Query the predicted metrics of the given service.
+ rpc queryPredictedMetrics(AlarmBaselineRequest) returns (AlarmBaselineResponse);
+}
+
+message AlarmBaselineMetricsNames {
+ repeated string metricNames = 1;
+}
+
+// The request of the predicted metrics query.
+message AlarmBaselineRequest {
+ // The request service metrics names.
+ repeated AlarmBaselineServiceMetricName serviceMetricNames = 1;
+ // The request start TimeBucket.
+ int64 startTimeBucket = 2;
+ // The request end TimeBucket.
+ int64 endTimeBucket = 3;
+ // The step of the TimeBucket.
+ TimeBucketStep step = 4;
+}
+
+enum TimeBucketStep {
+ HOUR = 0;
+}
+
+message AlarmBaselineServiceMetricName {
+ // The service name.
+ string serviceName = 1;
+ // The metrics names.
+ repeated string metricNames = 2;
+}
+
+// The response of the predicted metrics query.
+message AlarmBaselineResponse {
+ repeated AlarmBaselineServiceMetric serviceMetrics = 1;
+}
+
+message AlarmBaselineServiceMetric {
+ // The service name.
+ string serviceName = 1;
+ // The service metrics.
+ repeated AlarmBaselineMetricPrediction predictions = 2;
+}
+
+// The predicted metric.
+message AlarmBaselineMetricPrediction {
+ // The metric name.
+ string name = 1;
+ // The metric predicated values(timeBucket with predicted value).
+ repeated AlarmBaselinePredicatedValue values = 2;
+}
+
+// The predicted metric sample.
+message AlarmBaselinePredicatedValue {
+ int64 timeBucket = 1;
+ oneof value {
+ AlarmBaselineSingleValue singleValue = 2;
+ AlarmBaselineLabeledValue labeledValue = 3;
+ }
+}
+
+// The predicted value. The metric values provided within this baseline are at a minute-level granularity. For example, it includes metrics such as the number of visits per minute.
+message AlarmBaselineValue {
+ // The predicted value.
+ int64 value = 1;
+ // The upper value of the predicted range.
+ int64 upperValue = 2;
+ // The lower value of the predicted range.
+ int64 lowerValue = 3;
+}
+
+// The predicted single value metric.
+message AlarmBaselineSingleValue {
+ AlarmBaselineValue value = 2;
+}
+
+// The predicted labeled value metric.
+message AlarmBaselineLabeledValue {
+ // label pairs with value.
+ message LabelWithValue {
+ repeated KeyStringValuePair labels = 1;
+ AlarmBaselineValue value = 2;
+ }
+ repeated LabelWithValue values = 1;
+}
+
+message KeyStringValuePair {
+ string key = 1;
+ string value = 2;
+}
diff --git a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/resources/application.yml
similarity index 51%
copy from test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
copy to test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/resources/application.yml
index a08b02cad0..09697dce6e 100644
--- a/test/e2e-v2/cases/alarm/banyandb/docker-compose.yml
+++ b/test/e2e-v2/java-test-service/e2e-mock-baseline-server/src/main/resources/application.yml
@@ -13,40 +13,3 @@
# See the License for the specific language governing permissions and
# limitations under the License.
-version: '2.1'
-
-services:
- banyandb:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: banyandb
- networks:
- - e2e
-
- oap:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: oap
- environment:
- SW_STORAGE: banyandb
- SW_SEARCHABLE_ALARM_TAG_KEYS: level,receivers
- ports:
- - 12800
- depends_on:
- banyandb:
- condition: service_healthy
- volumes:
- - ../alarm-settings.yml:/skywalking/config/alarm-settings.yml
-
- provider:
- extends:
- file: ../../../script/docker-compose/base-compose.yml
- service: provider
- ports:
- - 9090
- depends_on:
- oap:
- condition: service_healthy
-
-networks:
- e2e:
diff --git a/test/e2e-v2/java-test-service/pom.xml b/test/e2e-v2/java-test-service/pom.xml
index 9dd474d288..68ef442632 100644
--- a/test/e2e-v2/java-test-service/pom.xml
+++ b/test/e2e-v2/java-test-service/pom.xml
@@ -33,6 +33,7 @@
<module>e2e-mock-sender</module>
<module>e2e-protocol</module>
<module>opentelemetry-proto</module>
+ <module>e2e-mock-baseline-server</module>
</modules>
<properties>