Provide labeled meter when receive meter (#5659)
This commit is contained in:
parent
45e02ec106
commit
7b2a0b4dac
|
|
@ -49,6 +49,9 @@ meters:
|
|||
operation: <string>
|
||||
# Meter value parse groovy script.
|
||||
value: <string>
|
||||
# Aggregate metrics group by dedicated labels
|
||||
groupBy:
|
||||
- <labelName>
|
||||
# <Optional> Appoint percentiles if using avgHistogramPercentile operation.
|
||||
percentile:
|
||||
- <rank>
|
||||
|
|
@ -56,7 +59,7 @@ meters:
|
|||
|
||||
#### Meter transform operation
|
||||
|
||||
The available operations are `avg`, `avgHistogram` and `avgHistogramPercentile`. The `avg` and `avgXXX` mean to average
|
||||
The available operations are `avg`, `avgLabeled`, `avgHistogram` and `avgHistogramPercentile`. The `avg` and `avgXXX` mean to average
|
||||
the raw received metrics.
|
||||
|
||||
When you specify `avgHistogram` and `avgHistogramPercentile`, the source should be the type of `histogram`.
|
||||
|
|
|
|||
|
|
@ -42,4 +42,9 @@ public class MeterDataConfig {
|
|||
*/
|
||||
private List<Integer> percentile;
|
||||
|
||||
/**
|
||||
* Aggregate meter group by dedicated labels
|
||||
*/
|
||||
private List<String> groupBy;
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -22,8 +22,12 @@ import io.vavr.Function2;
|
|||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static java.util.stream.Collectors.groupingBy;
|
||||
|
||||
/**
|
||||
* Combined meter data, has multiple meter data. Support batch process the express on meter
|
||||
*/
|
||||
|
|
@ -122,6 +126,21 @@ public class EvalMultipleData extends EvalData<EvalMultipleData> {
|
|||
return dataList.stream().reduce(EvalData::combine).orElseThrow(IllegalArgumentException::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* Combine all of the meter and group by labeled names
|
||||
* @return Same labeled names and values
|
||||
*/
|
||||
Map<String, EvalData> combineAndGroupBy(List<String> labelNames) {
|
||||
return dataList.stream()
|
||||
// group by label
|
||||
.collect(groupingBy(m -> labelNames.stream().map(l -> m.getLabels().getOrDefault(l, "")).map(Objects::toString).collect(Collectors.joining("-"))))
|
||||
.entrySet().stream().collect(
|
||||
// combine labeled values
|
||||
Collectors.toMap(
|
||||
e -> e.getKey(),
|
||||
e -> e.getValue().stream().reduce(EvalData::combine).orElse(null)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Append data to ready eval list
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -28,8 +28,12 @@ import org.apache.skywalking.oap.server.core.analysis.meter.MeterSystem;
|
|||
import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
|
||||
import org.apache.skywalking.oap.server.core.analysis.meter.function.AvgHistogramPercentileFunction;
|
||||
import org.apache.skywalking.oap.server.core.analysis.meter.function.BucketedValues;
|
||||
import org.apache.skywalking.oap.server.core.analysis.metrics.DataTable;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
|
|
@ -42,6 +46,9 @@ public class MeterBuilder {
|
|||
private final MeterConfig config;
|
||||
private final MeterSystem meterSystem;
|
||||
|
||||
private final static String DEFAULT_GROUP = "default";
|
||||
private final static List<String> DEFAULT_GROUP_LIST = Collections.singletonList(DEFAULT_GROUP);
|
||||
|
||||
/**
|
||||
* Current meter has init finished.
|
||||
*/
|
||||
|
|
@ -96,36 +103,49 @@ public class MeterBuilder {
|
|||
log.warn("avg function not support histogram value, please check meter:{}", combinedSingleAvgData.getName());
|
||||
}
|
||||
break;
|
||||
case "avgLabeled":
|
||||
final DataTable dt = new DataTable();
|
||||
values.combineAndGroupBy(Optional.ofNullable(config.getMeter().getGroupBy()).orElse(DEFAULT_GROUP_LIST)).entrySet().stream()
|
||||
.forEach(e -> dt.put(e.getKey(), (long) ((EvalSingleData) e.getValue()).getValue()));
|
||||
AcceptableValue<DataTable> value = meterSystem.buildMetrics(metricsName, DataTable.class);
|
||||
value.accept(entity, dt);
|
||||
value.setTimeBucket(TimeBucket.getMinuteTimeBucket(processor.timestamp()));
|
||||
meterSystem.doStreamingCalculation(value);
|
||||
break;
|
||||
case "avgHistogram":
|
||||
case "avgHistogramPercentile":
|
||||
final EvalData combinedHistogramData = values.combineAsSingleData();
|
||||
if (combinedHistogramData instanceof EvalHistogramData) {
|
||||
final EvalHistogramData histogram = (EvalHistogramData) combinedHistogramData;
|
||||
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()) {
|
||||
buckets[i] = entry.getKey().intValue();
|
||||
bucketValues[i] = entry.getValue();
|
||||
i++;
|
||||
}
|
||||
values.combineAndGroupBy(Optional.ofNullable(config.getMeter().getGroupBy()).orElse(DEFAULT_GROUP_LIST)).entrySet().stream()
|
||||
.forEach(e -> {
|
||||
final String group = e.getKey();
|
||||
final EvalData combinedHistogramData = e.getValue();
|
||||
if (combinedHistogramData instanceof EvalHistogramData) {
|
||||
final EvalHistogramData histogram = (EvalHistogramData) combinedHistogramData;
|
||||
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()) {
|
||||
buckets[i] = entry.getKey().intValue();
|
||||
bucketValues[i] = entry.getValue();
|
||||
i++;
|
||||
}
|
||||
|
||||
if (config.getMeter().getOperation().equals("avgHistogram")) {
|
||||
AcceptableValue<BucketedValues> avgHistogramValue = meterSystem.buildMetrics(metricsName, BucketedValues.class);
|
||||
avgHistogramValue.accept(entity, new BucketedValues(buckets, bucketValues));
|
||||
avgHistogramValue.setTimeBucket(TimeBucket.getMinuteTimeBucket(processor.timestamp()));
|
||||
meterSystem.doStreamingCalculation(avgHistogramValue);
|
||||
} else {
|
||||
final AcceptableValue<AvgHistogramPercentileFunction.AvgPercentileArgument> percentileValue =
|
||||
meterSystem.buildMetrics(metricsName, AvgHistogramPercentileFunction.AvgPercentileArgument.class);
|
||||
percentileValue.accept(entity, new AvgHistogramPercentileFunction.AvgPercentileArgument(new BucketedValues(buckets, bucketValues),
|
||||
config.getMeter().getPercentile().stream().mapToInt(Integer::intValue).toArray()));
|
||||
percentileValue.setTimeBucket(TimeBucket.getMinuteTimeBucket(processor.timestamp()));
|
||||
meterSystem.doStreamingCalculation(percentileValue);
|
||||
}
|
||||
} else {
|
||||
log.warn(config.getMeter().getOperation() + " function not support single value, please check meter:{}", combinedHistogramData.getName());
|
||||
}
|
||||
final BucketedValues bucketedValues = new BucketedValues(buckets, bucketValues);
|
||||
bucketedValues.setGroup(group);
|
||||
if (config.getMeter().getOperation().equals("avgHistogram")) {
|
||||
AcceptableValue<BucketedValues> avgHistogramValue = meterSystem.buildMetrics(metricsName, BucketedValues.class);
|
||||
avgHistogramValue.accept(entity, bucketedValues);
|
||||
avgHistogramValue.setTimeBucket(TimeBucket.getMinuteTimeBucket(processor.timestamp()));
|
||||
meterSystem.doStreamingCalculation(avgHistogramValue);
|
||||
} else {
|
||||
final AcceptableValue<AvgHistogramPercentileFunction.AvgPercentileArgument> percentileValue =
|
||||
meterSystem.buildMetrics(metricsName, AvgHistogramPercentileFunction.AvgPercentileArgument.class);
|
||||
percentileValue.accept(entity, new AvgHistogramPercentileFunction.AvgPercentileArgument(bucketedValues,
|
||||
config.getMeter().getPercentile().stream().mapToInt(Integer::intValue).toArray()));
|
||||
percentileValue.setTimeBucket(TimeBucket.getMinuteTimeBucket(processor.timestamp()));
|
||||
meterSystem.doStreamingCalculation(percentileValue);
|
||||
}
|
||||
}
|
||||
});
|
||||
break;
|
||||
default:
|
||||
log.warn("Cannot support function:{}", config.getMeter().getOperation());
|
||||
|
|
|
|||
|
|
@ -19,13 +19,15 @@
|
|||
package org.apache.skywalking.oap.server.analyzer.provider.meter.process;
|
||||
|
||||
import io.vavr.Function2;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class EvalMultipleDataTest extends EvalDataBaseTest {
|
||||
|
||||
private EvalMultipleData singleMultiple;
|
||||
|
|
@ -104,6 +106,30 @@ public class EvalMultipleDataTest extends EvalDataBaseTest {
|
|||
Assert.assertEquals(35, combinedHistogramData.getBuckets().get(10d).longValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCombineAndGroupBy() {
|
||||
final Map<String, EvalData> singleValueCombineAndGroupBy = singleMultiple.combineAndGroupBy(Arrays.asList("k1"));
|
||||
Assert.assertEquals(3, singleValueCombineAndGroupBy.size());
|
||||
Assert.assertEquals(10d, ((EvalSingleData) singleValueCombineAndGroupBy.get("v1")).getValue(), 0.0);
|
||||
Assert.assertEquals(20d, ((EvalSingleData) singleValueCombineAndGroupBy.get("v2")).getValue(), 0.0);
|
||||
Assert.assertEquals(30d, ((EvalSingleData) singleValueCombineAndGroupBy.get("v3")).getValue(), 0.0);
|
||||
|
||||
final Map<String, EvalData> histogramCombineAndGroupBy = histogramMultiple.combineAndGroupBy(Arrays.asList("k1"));
|
||||
Assert.assertEquals(3, histogramCombineAndGroupBy.size());
|
||||
Assert.assertEquals(10, ((EvalHistogramData) histogramCombineAndGroupBy.get("v1")).getBuckets().get(1d).longValue());
|
||||
Assert.assertEquals(20, ((EvalHistogramData) histogramCombineAndGroupBy.get("v1")).getBuckets().get(5d).longValue());
|
||||
Assert.assertEquals(3, ((EvalHistogramData) histogramCombineAndGroupBy.get("v1")).getBuckets().get(10d).longValue());
|
||||
|
||||
Assert.assertEquals(5, ((EvalHistogramData) histogramCombineAndGroupBy.get("v2")).getBuckets().get(1d).longValue());
|
||||
Assert.assertEquals(10, ((EvalHistogramData) histogramCombineAndGroupBy.get("v2")).getBuckets().get(5d).longValue());
|
||||
Assert.assertEquals(7, ((EvalHistogramData) histogramCombineAndGroupBy.get("v2")).getBuckets().get(10d).longValue());
|
||||
|
||||
Assert.assertEquals(15, ((EvalHistogramData) histogramCombineAndGroupBy.get("v3")).getBuckets().get(1d).longValue());
|
||||
Assert.assertEquals(20, ((EvalHistogramData) histogramCombineAndGroupBy.get("v3")).getBuckets().get(5d).longValue());
|
||||
Assert.assertEquals(25, ((EvalHistogramData) histogramCombineAndGroupBy.get("v3")).getBuckets().get(10d).longValue());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify the multiple data operation
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.analyzer.provider.meter.process;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import org.apache.skywalking.oap.server.core.analysis.IDManager;
|
||||
import org.apache.skywalking.oap.server.core.analysis.TimeBucket;
|
||||
import org.apache.skywalking.oap.server.core.analysis.meter.function.AcceptableValue;
|
||||
|
|
@ -35,6 +33,9 @@ import org.powermock.core.classloader.annotations.PowerMockIgnore;
|
|||
import org.powermock.modules.junit4.PowerMockRunner;
|
||||
import org.powermock.reflect.Whitebox;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static org.mockito.Matchers.any;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.doCallRealMethod;
|
||||
|
|
|
|||
|
|
@ -18,8 +18,6 @@
|
|||
|
||||
package org.apache.skywalking.oap.server.analyzer.provider.trace;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import org.apache.skywalking.oap.server.analyzer.provider.AnalyzerModuleProvider;
|
||||
import org.apache.skywalking.oap.server.configuration.api.ConfigChangeWatcher;
|
||||
import org.apache.skywalking.oap.server.configuration.api.ConfigTable;
|
||||
|
|
@ -30,6 +28,9 @@ import org.junit.Test;
|
|||
import org.junit.runner.RunWith;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.hamcrest.CoreMatchers.is;
|
||||
import static org.hamcrest.MatcherAssert.assertThat;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue