You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@skywalking.apache.org by ha...@apache.org on 2020/09/01 15:18:27 UTC
[skywalking] 02/02: Support labeled histogram and percentile
This is an automated email from the ASF dual-hosted git repository.
hanahmily pushed a commit to branch meter-histogram
in repository https://gitbox.apache.org/repos/asf/skywalking.git
commit 9d1d1c7119c07dc86c76d19f3e2a2730c2d4372d
Author: Gao Hongtao <ha...@gmail.com>
AuthorDate: Tue Sep 1 23:17:51 2020 +0800
Support labeled histogram and percentile
Signed-off-by: Gao Hongtao <ha...@gmail.com>
---
docs/en/setup/backend/backend-fetcher.md | 12 ++-
.../provider/meter/process/MeterBuilder.java | 2 +-
.../meter/function/AvgHistogramFunction.java | 11 +-
.../function/AvgHistogramPercentileFunction.java | 112 ++++++++++++++-------
.../analysis/meter/function/BucketedValues.java | 12 +--
.../analysis/meter/function/HistogramFunction.java | 2 +-
.../meter/function/PercentileFunction.java | 2 +-
.../server/core/analysis/metrics/DataTable.java | 3 +-
.../promethues/PrometheusMetricConverter.java | 25 +++--
.../metric/promethues/operation/Operation.java | 3 +
.../core/metric/promethues/rule/MetricsRule.java | 2 +
.../oap/server/core/query/type/HeatMap.java | 5 +-
.../meter/function/AvgHistogramFunctionTest.java | 13 +--
...ava => AvgHistogramPercentileFunctionTest.java} | 82 ++++-----------
.../meter/function/HistogramFunctionTest.java | 8 +-
.../meter/function/PercentileFunctionTest.java | 4 +-
16 files changed, 149 insertions(+), 149 deletions(-)
diff --git a/docs/en/setup/backend/backend-fetcher.md b/docs/en/setup/backend/backend-fetcher.md
index cff6e27..01ebf4a 100644
--- a/docs/en/setup/backend/backend-fetcher.md
+++ b/docs/en/setup/backend/backend-fetcher.md
@@ -60,6 +60,10 @@ name: <string>
scope: <string>
# The transformation operation from prometheus metrics to skywalking ones.
operation: <operation>
+# The percentile rank of percentile operation
+[percentiles: [<rank>,...]]
+# bucketUnit indicates the unit of histogram bucket, it should be one of MILLISECONDS, SECONDS, MINUTES, HOURS, DAYS
+[bucketUnit: <string>]
# The prometheus sources of the transformation operation.
sources:
# The prometheus metric family name
@@ -68,8 +72,12 @@ sources:
[counterFunction: <string> ]
# The range of a counterFunction.
[range: <duration>]
- # The percentile rank of percentile operation
- [percentiles: [<rank>,...]]
+ # Aggregate metrics group by dedicated labels
+ [groupBy: [<labelname>, ...]]
+ # Set up the scale of the analysis result
+ [scale: <integer>]
+ # Filter target metrics by dedicated labels
+ [labelFilter: [<filterRule>, ...]]
# Relabel prometheus labels to skywalking dimensions.
relabel:
service: [<labelname>, ...]
diff --git a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/meter/process/MeterBuilder.java b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/meter/process/MeterBuilder.java
index b8c61fc..aa0f421 100644
--- a/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/meter/process/MeterBuilder.java
+++ b/oap-server/analyzer/agent-analyzer/src/main/java/org/apache/skywalking/oap/server/analyzer/provider/meter/process/MeterBuilder.java
@@ -101,7 +101,7 @@ public class MeterBuilder {
final EvalData combinedHistogramData = values.combineAsSingleData();
if (combinedHistogramData instanceof EvalHistogramData) {
final EvalHistogramData histogram = (EvalHistogramData) combinedHistogramData;
- int[] buckets = new int[histogram.getBuckets().size()];
+ long[] buckets = new long[histogram.getBuckets().size()];
long[] bucketValues = new long[histogram.getBuckets().size()];
int i = 0;
for (Map.Entry<Double, Long> entry : histogram.getBuckets().entrySet()) {
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunction.java
index b8346dc..57d8a34 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunction.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunction.java
@@ -90,8 +90,8 @@ public abstract class AvgHistogramFunction extends Metrics implements Acceptable
}
final long[] values = value.getValues();
for (int i = 0; i < values.length; i++) {
- int bucket = value.getBuckets()[i];
- String bucketName = bucket == Integer.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
+ long bucket = value.getBuckets()[i];
+ String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
String key = String.format(template, bucketName);
summation.valueAccumulation(key, values[i]);
count.valueAccumulation(key, 1L);
@@ -101,13 +101,6 @@ public abstract class AvgHistogramFunction extends Metrics implements Acceptable
@Override
public void combine(final Metrics metrics) {
AvgHistogramFunction histogram = (AvgHistogramFunction) metrics;
-
- if (!summation.keysEqual(histogram.getSummation())) {
- log.warn("Incompatible input [{}}] for current HistogramFunction[{}], entity {}",
- histogram, this, entityId
- );
- return;
- }
this.summation.append(histogram.summation);
this.count.append(histogram.count);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunction.java
index 19de02c..73b2bd1 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunction.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunction.java
@@ -18,11 +18,16 @@
package org.apache.skywalking.oap.server.core.analysis.meter.function;
+import com.google.common.base.Strings;
+import io.vavr.Tuple;
+import io.vavr.Tuple2;
import java.util.Comparator;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collector;
import java.util.stream.IntStream;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -35,10 +40,14 @@ import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
import org.apache.skywalking.oap.server.core.analysis.metrics.IntList;
import org.apache.skywalking.oap.server.core.analysis.metrics.Metrics;
import org.apache.skywalking.oap.server.core.analysis.metrics.MultiIntValuesHolder;
+import org.apache.skywalking.oap.server.core.query.type.Bucket;
import org.apache.skywalking.oap.server.core.remote.grpc.proto.RemoteData;
import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.apache.skywalking.oap.server.core.storage.annotation.Column;
+import static java.util.stream.Collectors.groupingBy;
+import static java.util.stream.Collectors.mapping;
+
/**
* AvgPercentile intends to calculate percentile based on the average of raw values over the interval(minute, hour or day).
*
@@ -53,6 +62,7 @@ import org.apache.skywalking.oap.server.core.storage.annotation.Column;
@MeterFunction(functionName = "avgHistogramPercentile")
@Slf4j
public abstract class AvgHistogramPercentileFunction extends Metrics implements AcceptableValue<AvgHistogramPercentileFunction.AvgPercentileArgument>, MultiIntValuesHolder {
+ private static final String DEFAULT_GROUP = "pD";
public static final String DATASET = "dataset";
public static final String RANKS = "ranks";
public static final String VALUE = "value";
@@ -125,11 +135,17 @@ public abstract class AvgHistogramPercentileFunction extends Metrics implements
this.entityId = entity.id();
+ String template = "%s";
+ if (!Strings.isNullOrEmpty(value.getBucketedValues().getGroup())) {
+ template = value.getBucketedValues().getGroup() + ":%s";
+ }
final long[] values = value.getBucketedValues().getValues();
for (int i = 0; i < values.length; i++) {
- String bucketName = String.valueOf(value.getBucketedValues().getBuckets()[i]);
- summation.valueAccumulation(bucketName, values[i]);
- count.valueAccumulation(bucketName, 1L);
+ long bucket = value.getBucketedValues().getBuckets()[i];
+ String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
+ String key = String.format(template, bucketName);
+ summation.valueAccumulation(key, values[i]);
+ count.valueAccumulation(key, 1L);
}
this.isCalculated = false;
@@ -139,12 +155,6 @@ public abstract class AvgHistogramPercentileFunction extends Metrics implements
public void combine(final Metrics metrics) {
AvgHistogramPercentileFunction percentile = (AvgHistogramPercentileFunction) metrics;
- if (!summation.keysEqual(percentile.getSummation())) {
- log.warn("Incompatible input [{}}] for current PercentileFunction[{}], entity {}",
- percentile, this, entityId
- );
- return;
- }
if (ranks.size() > 0) {
if (this.ranks.size() != ranks.size()) {
log.warn("Incompatible ranks size = [{}}] for current PercentileFunction[{}]",
@@ -168,38 +178,64 @@ public abstract class AvgHistogramPercentileFunction extends Metrics implements
@Override
public void calculate() {
if (!isCalculated) {
- final List<String> sortedKeys = summation.sortedKeys(Comparator.comparingInt(Integer::parseInt));
- for (String key : sortedKeys) {
- dataset.put(key, summation.get(key) / count.get(key));
- }
-
- long total = dataset.sumOfValues();
-
- int[] roofs = new int[ranks.size()];
- for (int i = 0; i < ranks.size(); i++) {
- roofs[i] = Math.round(total * ranks.get(i) * 1.0f / 100);
- }
-
- int count = 0;
- int loopIndex = 0;
-
- for (int i = 0; i < sortedKeys.size(); i++) {
- String key = sortedKeys.get(i);
- final Long value = dataset.get(key);
-
- count += value;
- for (int rankIdx = loopIndex; rankIdx < roofs.length; rankIdx++) {
- int roof = roofs[rankIdx];
-
- if (count >= roof) {
- long latency = (i + 1 == sortedKeys.size()) ? Long.MAX_VALUE : Long.parseLong(sortedKeys.get(i + 1));
- percentileValues.put(String.valueOf(ranks.get(rankIdx)), latency);
- loopIndex++;
- } else {
- break;
+ final Set<String> keys = summation.keys();
+ for (String key : keys) {
+ long value = 0;
+ if (count.get(key) != 0) {
+ value = summation.get(key) / count.get(key);
+ if (value == 0L && summation.get(key) > 0L) {
+ value = 1;
}
}
+ dataset.put(key, value);
}
+ dataset.keys().stream()
+ .map(key -> {
+ if (key.contains(":")) {
+ String[] kk = key.split(":");
+ return Tuple.of(kk[0], key);
+ } else {
+ return Tuple.of(DEFAULT_GROUP, key);
+ }
+ })
+ .collect(groupingBy(Tuple2::_1, mapping(Tuple2::_2, Collector.of(
+ DataTable::new,
+ (dt, key) -> dt.put(key.contains(":") ? key.split(":")[1] : key, dataset.get(key)),
+ DataTable::append))))
+ .forEach((group, subDataset) -> {
+ long total;
+ total = subDataset.sumOfValues();
+
+ int[] roofs = new int[ranks.size()];
+ for (int i = 0; i < ranks.size(); i++) {
+ roofs[i] = Math.round(total * ranks.get(i) * 1.0f / 100);
+ }
+
+ int count = 0;
+ final List<String> sortedKeys = subDataset.sortedKeys(Comparator.comparingLong(Long::parseLong));
+
+ int loopIndex = 0;
+
+ for (String key : sortedKeys) {
+ final Long value = subDataset.get(key);
+
+ count += value;
+ for (int rankIdx = loopIndex; rankIdx < roofs.length; rankIdx++) {
+ int roof = roofs[rankIdx];
+
+ if (count >= roof) {
+ if (group.equals(DEFAULT_GROUP)) {
+ percentileValues.put(String.valueOf(ranks.get(rankIdx)), Long.parseLong(key));
+ } else {
+ percentileValues.put(String.format("%s:%s", group, ranks.get(rankIdx)), Long.parseLong(key));
+ }
+ loopIndex++;
+ } else {
+ break;
+ }
+ }
+ }
+ });
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
index 0f8f825..ab221f2 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/BucketedValues.java
@@ -40,9 +40,9 @@ public class BucketedValues {
* The element in the buckets represent the minimal value of this bucket, the max is defined by the next element.
* Such as 0, 10, 50, 100 means buckets are [0, 10), [10, 50), [50, 100), [100, infinite+).
*
- * The {@link Integer#MIN_VALUE} could be the first bucket element to indicate there is no minimal value.
+ * The {@link Long#MIN_VALUE} could be the first bucket element to indicate there is no minimal value.
*/
- private int[] buckets;
+ private long[] buckets;
/**
* {@link #buckets} and {@link #values} arrays should have the same length. The element in the values, represents
* the amount in the same index bucket.
@@ -53,7 +53,7 @@ public class BucketedValues {
* @param buckets Read {@link #buckets}
* @param values Read {@link #values}
*/
- public BucketedValues(final int[] buckets, final long[] values) {
+ public BucketedValues(final long[] buckets, final long[] values) {
if (buckets == null || values == null || buckets.length == 0 || values.length == 0) {
throw new IllegalArgumentException("buckets and values can't be null.");
}
@@ -69,13 +69,13 @@ public class BucketedValues {
*/
public boolean isCompatible(DataTable dataset) {
final List<String> sortedKeys = dataset.sortedKeys(new HeatMap.KeyComparator(true));
- int[] existedBuckets = new int[sortedKeys.size()];
+ long[] existedBuckets = new long[sortedKeys.size()];
for (int i = 0; i < sortedKeys.size(); i++) {
final String key = sortedKeys.get(i);
if (key.equals(Bucket.INFINITE_NEGATIVE)) {
- existedBuckets[i] = Integer.MIN_VALUE;
+ existedBuckets[i] = Long.MIN_VALUE;
} else {
- existedBuckets[i] = Integer.parseInt(key);
+ existedBuckets[i] = Long.parseLong(key);
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunction.java
index c6edef5..ce23f27 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunction.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunction.java
@@ -68,7 +68,7 @@ public abstract class HistogramFunction extends Metrics implements AcceptableVal
final long[] values = value.getValues();
for (int i = 0; i < values.length; i++) {
final long bucket = value.getBuckets()[i];
- String bucketName = bucket == Integer.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
+ String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
final long bucketValue = values[i];
dataset.valueAccumulation(bucketName, bucketValue);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunction.java
index 8bfc782..b7c81fd 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunction.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunction.java
@@ -113,7 +113,7 @@ public abstract class PercentileFunction extends Metrics implements AcceptableVa
final long[] values = value.getBucketedValues().getValues();
for (int i = 0; i < values.length; i++) {
final long bucket = value.getBucketedValues().getBuckets()[i];
- String bucketName = bucket == Integer.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
+ String bucketName = bucket == Long.MIN_VALUE ? Bucket.INFINITE_NEGATIVE : String.valueOf(bucket);
final long bucketValue = values[i];
dataset.valueAccumulation(bucketName, bucketValue);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java
index 2fca2da..0640d68 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/metrics/DataTable.java
@@ -141,7 +141,7 @@ public class DataTable implements StorageDataComplexObject<DataTable> {
this.append(source);
}
- public void append(DataTable dataTable) {
+ public DataTable append(DataTable dataTable) {
dataTable.data.forEach((key, value) -> {
Long current = this.data.get(key);
if (current == null) {
@@ -151,5 +151,6 @@ public class DataTable implements StorageDataComplexObject<DataTable> {
}
this.data.put(key, current);
});
+ return this;
}
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
index 02b3395..ce192e1 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/PrometheusMetricConverter.java
@@ -98,6 +98,9 @@ public class PrometheusMetricConverter {
lastRuleName.set(rule.getName());
return;
}
+ if (rule.getBucketUnit().toMillis(1L) < 1L) {
+ throw new IllegalArgumentException("Bucket unit should be equals or more than MILLISECOND");
+ }
service.create(formatMetricName(rule.getName()), rule.getOperation(), rule.getScope());
lastRuleName.set(rule.getName());
});
@@ -138,7 +141,7 @@ public class PrometheusMetricConverter {
.peek(tuple -> log.debug("Mapped rules to metrics: {}", tuple))
.map(Function1.liftTry(tuple -> {
String serviceName = composeEntity(tuple._3.getRelabel().getService().stream(), tuple._4.getLabels());
- Operation o = new Operation(tuple._1.getOperation(), tuple._1.getName(), tuple._1.getScope(), tuple._1.getPercentiles());
+ Operation o = new Operation(tuple._1.getOperation(), tuple._1.getName(), tuple._1.getScope(), tuple._1.getPercentiles(), tuple._1.getBucketUnit());
MetricSource.MetricSourceBuilder sb = MetricSource.builder();
sb.promMetricName(tuple._2)
.timestamp(tuple._4.getTimestamp())
@@ -199,12 +202,12 @@ public class PrometheusMetricConverter {
Map.Entry<MetricSource, List<Metric>> smm = sources.entrySet().iterator().next();
smm.getValue().stream()
- .collect(groupingBy(m -> Optional.ofNullable(smm.getKey().getGroupBy()).orElse(DEFAULT_GROUP_LIST).stream().map(m.getLabels()::get).collect(Collectors.joining("-"))))
+ .collect(groupingBy(m -> Optional.ofNullable(smm.getKey().getGroupBy()).orElse(DEFAULT_GROUP_LIST).stream().map(m.getLabels()::get).collect(Collectors.joining(":"))))
.forEach((group, mm) -> {
Histogram h = (Histogram) sum(mm);
long[] vv = new long[h.getBuckets().size()];
- int[] bb = new int[h.getBuckets().size()];
+ long[] bb = new long[h.getBuckets().size()];
long v = 0L;
int i = 0;
for (Map.Entry<Double, Long> entry : h.getBuckets().entrySet()) {
@@ -214,20 +217,20 @@ public class PrometheusMetricConverter {
v = entry.getValue();
if (i + 1 < h.getBuckets().size()) {
- bb[i + 1] = BigDecimal.valueOf(entry.getKey()).multiply(SECOND_TO_MILLISECOND).intValue();
+ bb[i + 1] = BigDecimal.valueOf(entry.getKey())
+ .multiply(BigDecimal.valueOf(operation.getBucketUnit().toMillis(1L)))
+ .longValue();
}
-
i++;
}
-
+ BucketedValues bv = new BucketedValues(bb, vv);
+ if (!group.equals(DEFAULT_GROUP)) {
+ bv.setGroup(group);
+ }
if (operation.getName().equals(AVG_HISTOGRAM)) {
AcceptableValue<BucketedValues> heatmapMetrics = service.buildMetrics(
formatMetricName(operation.getMetricName()), BucketedValues.class);
heatmapMetrics.setTimeBucket(TimeBucket.getMinuteTimeBucket(smm.getKey().getTimestamp()));
- BucketedValues bv = new BucketedValues(bb, vv);
- if (!group.equals(DEFAULT_GROUP)) {
- bv.setGroup(group);
- }
heatmapMetrics.accept(smm.getKey().getEntity(), bv);
service.doStreamingCalculation(heatmapMetrics);
} else {
@@ -235,7 +238,7 @@ public class PrometheusMetricConverter {
service.buildMetrics(formatMetricName(operation.getMetricName()), AvgHistogramPercentileFunction.AvgPercentileArgument.class);
percentileMetrics.setTimeBucket(TimeBucket.getMinuteTimeBucket(smm.getKey().getTimestamp()));
percentileMetrics.accept(smm.getKey().getEntity(),
- new AvgHistogramPercentileFunction.AvgPercentileArgument(new BucketedValues(bb, vv), operation.getPercentiles().stream().mapToInt(Integer::intValue).toArray()));
+ new AvgHistogramPercentileFunction.AvgPercentileArgument(bv, operation.getPercentiles().stream().mapToInt(Integer::intValue).toArray()));
service.doStreamingCalculation(percentileMetrics);
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/Operation.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/Operation.java
index 42334e3..4d7cc64 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/Operation.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/operation/Operation.java
@@ -19,6 +19,7 @@
package org.apache.skywalking.oap.server.core.metric.promethues.operation;
import java.util.List;
+import java.util.concurrent.TimeUnit;
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@@ -39,4 +40,6 @@ public class Operation {
private final List<Integer> percentiles;
+ private final TimeUnit bucketUnit;
+
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/MetricsRule.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/MetricsRule.java
index 6b9b713..143a804 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/MetricsRule.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/metric/promethues/rule/MetricsRule.java
@@ -20,6 +20,7 @@ package org.apache.skywalking.oap.server.core.metric.promethues.rule;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.TimeUnit;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.apache.skywalking.oap.server.core.analysis.meter.ScopeType;
@@ -31,5 +32,6 @@ public class MetricsRule {
private ScopeType scope;
private String operation;
private List<Integer> percentiles;
+ private TimeUnit bucketUnit = TimeUnit.SECONDS;
private Map<String, PrometheusMetric> sources;
}
diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
index c10fcb0..24dd802 100644
--- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
+++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/query/type/HeatMap.java
@@ -18,6 +18,7 @@
package org.apache.skywalking.oap.server.core.query.type;
+import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
@@ -149,10 +150,10 @@ public class HeatMap {
} else if (Bucket.INFINITE_NEGATIVE.equals(key2) || Bucket.INFINITE_POSITIVE.equals(key1)) {
result = 1;
} else {
- result = Integer.parseInt(key1) - Integer.parseInt(key2);
+ result = new BigInteger(key1).subtract(new BigInteger(key2)).signum();
}
- return asc ? result : 0 - result;
+ return asc ? result : -result;
}
private String[] parseKey(String key) {
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunctionTest.java
index 1b02499..6238218 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunctionTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramFunctionTest.java
@@ -33,22 +33,15 @@ import static org.apache.skywalking.oap.server.core.analysis.meter.function.AvgL
import static org.apache.skywalking.oap.server.core.analysis.meter.function.AvgLabeledFunction.SUMMATION;
public class AvgHistogramFunctionTest {
- private static final int[] BUCKETS = new int[] {
+ private static final long[] BUCKETS = new long[] {
0,
50,
100,
250
};
- private static final int[] BUCKETS_2ND = new int[] {
- 0,
- 51,
- 100,
- 250
- };
-
- private static final int[] INFINITE_BUCKETS = new int[] {
- Integer.MIN_VALUE,
+ private static final long[] INFINITE_BUCKETS = new long[] {
+ Long.MIN_VALUE,
-5,
0,
10
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunctionTest.java
similarity index 67%
copy from oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java
copy to oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunctionTest.java
index 6409d7b..ca9c4dd 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/AvgHistogramPercentileFunctionTest.java
@@ -26,17 +26,11 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder;
import org.junit.Assert;
import org.junit.Test;
-public class PercentileFunctionTest {
- private static final int[] BUCKETS = new int[] {
- 0,
- 50,
- 100,
- 250
- };
+public class AvgHistogramPercentileFunctionTest {
- private static final int[] BUCKETS_2ND = new int[] {
+ private static final long[] BUCKETS = new long[] {
0,
- 51,
+ 50,
100,
250
};
@@ -51,7 +45,7 @@ public class PercentileFunctionTest {
PercentileFunctionInst inst = new PercentileFunctionInst();
inst.accept(
MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
+ new AvgHistogramPercentileFunction.AvgPercentileArgument(
new BucketedValues(
BUCKETS,
new long[] {
@@ -67,7 +61,7 @@ public class PercentileFunctionTest {
inst.accept(
MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
+ new AvgHistogramPercentileFunction.AvgPercentileArgument(
new BucketedValues(
BUCKETS,
new long[] {
@@ -86,10 +80,10 @@ public class PercentileFunctionTest {
/**
* Expected percentile dataset
* <pre>
- * 0 , 20
- * 50 , 40
- * 100, 60 <- P50
- * 250, 80 <- P90
+ * 0 , 10
+ * 50 , 20
+ * 100, 30 <- P50
+ * 250, 40 <- P90
* </pre>
*/
Assert.assertArrayEquals(new int[] {
@@ -98,48 +92,12 @@ public class PercentileFunctionTest {
}, values);
}
- @Test(expected = IllegalArgumentException.class)
- public void testIncompatible() {
- PercentileFunctionInst inst = new PercentileFunctionInst();
- inst.accept(
- MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
- new BucketedValues(
- BUCKETS,
- new long[] {
- 10,
- 20,
- 30,
- 40
- }
- ),
- RANKS
- )
- );
-
- inst.accept(
- MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
- new BucketedValues(
- BUCKETS_2ND,
- new long[] {
- 10,
- 20,
- 30,
- 40
- }
- ),
- RANKS
- )
- );
- }
-
@Test
public void testSerialization() {
PercentileFunctionInst inst = new PercentileFunctionInst();
inst.accept(
MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
+ new AvgHistogramPercentileFunction.AvgPercentileArgument(
new BucketedValues(
BUCKETS,
new long[] {
@@ -168,7 +126,7 @@ public class PercentileFunctionTest {
PercentileFunctionInst inst = new PercentileFunctionInst();
inst.accept(
MeterEntity.newService("service-test"),
- new PercentileFunction.PercentileArgument(
+ new AvgHistogramPercentileFunction.AvgPercentileArgument(
new BucketedValues(
BUCKETS,
new long[] {
@@ -187,11 +145,13 @@ public class PercentileFunctionTest {
// Simulate the storage layer do, convert the datatable to string.
final Map map = storageBuilder.data2Map(inst);
- map.put(PercentileFunction.DATASET, ((DataTable) map.get(PercentileFunction.DATASET)).toStorageData());
- map.put(PercentileFunction.VALUE, ((DataTable) map.get(PercentileFunction.VALUE)).toStorageData());
- map.put(PercentileFunction.RANKS, ((IntList) map.get(PercentileFunction.RANKS)).toStorageData());
+ map.put(AvgHistogramPercentileFunction.COUNT, ((DataTable) map.get(AvgHistogramPercentileFunction.COUNT)).toStorageData());
+ map.put(AvgHistogramPercentileFunction.SUMMATION, ((DataTable) map.get(AvgHistogramPercentileFunction.SUMMATION)).toStorageData());
+ map.put(AvgHistogramPercentileFunction.DATASET, ((DataTable) map.get(AvgHistogramPercentileFunction.DATASET)).toStorageData());
+ map.put(AvgHistogramPercentileFunction.VALUE, ((DataTable) map.get(AvgHistogramPercentileFunction.VALUE)).toStorageData());
+ map.put(AvgHistogramPercentileFunction.RANKS, ((IntList) map.get(AvgHistogramPercentileFunction.RANKS)).toStorageData());
- final PercentileFunction inst2 = (PercentileFunction) storageBuilder.map2Data(map);
+ final AvgHistogramPercentileFunction inst2 = (AvgHistogramPercentileFunction) storageBuilder.map2Data(map);
Assert.assertEquals(inst, inst2);
// HistogramFunction equal doesn't include dataset.
Assert.assertEquals(inst.getDataset(), inst2.getDataset());
@@ -199,10 +159,10 @@ public class PercentileFunctionTest {
Assert.assertEquals(inst.getRanks(), inst2.getRanks());
}
- private static class PercentileFunctionInst extends PercentileFunction {
+ private static class PercentileFunctionInst extends AvgHistogramPercentileFunction {
@Override
- public AcceptableValue<PercentileArgument> createNew() {
- return new PercentileFunctionInst();
+ public AcceptableValue<AvgHistogramPercentileFunction.AvgPercentileArgument> createNew() {
+ return new AvgHistogramPercentileFunctionTest.PercentileFunctionInst();
}
}
-}
+}
\ No newline at end of file
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunctionTest.java
index 2bceedb..e9f61c8 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunctionTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/HistogramFunctionTest.java
@@ -31,22 +31,22 @@ import org.junit.Test;
import static org.apache.skywalking.oap.server.core.analysis.meter.function.HistogramFunction.DATASET;
public class HistogramFunctionTest {
- private static final int[] BUCKETS = new int[] {
+ private static final long[] BUCKETS = new long[] {
0,
50,
100,
250
};
- private static final int[] BUCKETS_2ND = new int[] {
+ private static final long[] BUCKETS_2ND = new long[] {
0,
51,
100,
250
};
- private static final int[] INFINITE_BUCKETS = new int[] {
- Integer.MIN_VALUE,
+ private static final long[] INFINITE_BUCKETS = new long[] {
+ Long.MIN_VALUE,
-5,
0,
10
diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java
index 6409d7b..3c7870a 100644
--- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java
+++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/PercentileFunctionTest.java
@@ -27,14 +27,14 @@ import org.junit.Assert;
import org.junit.Test;
public class PercentileFunctionTest {
- private static final int[] BUCKETS = new int[] {
+ private static final long[] BUCKETS = new long[] {
0,
50,
100,
250
};
- private static final int[] BUCKETS_2ND = new int[] {
+ private static final long[] BUCKETS_2ND = new long[] {
0,
51,
100,