diff --git a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java index 3d06d8603..85f1582e3 100644 --- a/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java +++ b/oap-server/server-core/src/main/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunction.java @@ -192,21 +192,31 @@ public abstract class AvgHistogramPercentileFunction extends Metrics implements dataset.put(key, value); } dataset.keys().stream() - .map(key -> { - if (key.contains(":")) { - int index = key.lastIndexOf(":"); - return Tuple.of(key.substring(0, index), key.substring(index + 1)); - } 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(); + .map(key -> { + if (key.contains(":")) { + int index = key.lastIndexOf(":"); + return Tuple.of(key.substring(0, index), key); + } else { + return Tuple.of(DEFAULT_GROUP, key); + } + }) + .collect(groupingBy(Tuple2::_1, mapping(Tuple2::_2, Collector.of( + DataTable::new, + (dt, key) -> { + String v; + if (key.contains(":")) { + int index = key.lastIndexOf(":"); + v = key.substring(index + 1); + } else { + v = key; + } + dt.put(v, 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++) { diff --git a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunctionTest.java b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunctionTest.java index 78e349643..0777f9660 100644 --- a/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunctionTest.java +++ b/oap-server/server-core/src/test/java/org/apache/skywalking/oap/server/core/analysis/meter/function/avg/AvgHistogramPercentileFunctionTest.java @@ -29,6 +29,8 @@ import org.apache.skywalking.oap.server.core.storage.StorageBuilder; import org.junit.Assert; import org.junit.Test; +import static org.junit.Assert.assertEquals; + public class AvgHistogramPercentileFunctionTest { private static final long[] BUCKETS = new long[] { @@ -117,11 +119,11 @@ public class AvgHistogramPercentileFunctionTest { PercentileFunctionInst inst2 = new PercentileFunctionInst(); inst2.deserialize(inst.serialize().build()); - Assert.assertEquals(inst, inst2); + assertEquals(inst, inst2); // HistogramFunction equal doesn't include dataset. - Assert.assertEquals(inst.getDataset(), inst2.getDataset()); - Assert.assertEquals(inst.getRanks(), inst2.getRanks()); - Assert.assertEquals(0, inst2.getPercentileValues().size()); + assertEquals(inst.getDataset(), inst2.getDataset()); + assertEquals(inst.getRanks(), inst2.getRanks()); + assertEquals(0, inst2.getPercentileValues().size()); } @Test @@ -148,18 +150,88 @@ public class AvgHistogramPercentileFunctionTest { // Simulate the storage layer do, convert the datatable to string. final Map map = storageBuilder.data2Map(inst); - 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()); + 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 AvgHistogramPercentileFunction inst2 = (AvgHistogramPercentileFunction) storageBuilder.map2Data(map); - Assert.assertEquals(inst, inst2); + assertEquals(inst, inst2); // HistogramFunction equal doesn't include dataset. - Assert.assertEquals(inst.getDataset(), inst2.getDataset()); - Assert.assertEquals(inst.getPercentileValues(), inst2.getPercentileValues()); - Assert.assertEquals(inst.getRanks(), inst2.getRanks()); + assertEquals(inst.getDataset(), inst2.getDataset()); + assertEquals(inst.getPercentileValues(), inst2.getPercentileValues()); + assertEquals(inst.getRanks(), inst2.getRanks()); + } + + @Test + public void testFunctionWhenGroupContainsColon() { + BucketedValues valuesA = new BucketedValues( + BUCKETS, + new long[] { + 10, + 20, + 30, + 40 + } + ); + valuesA.setGroup("localhost:3306/swtest"); + + PercentileFunctionInst inst = new PercentileFunctionInst(); + inst.accept( + MeterEntity.newService("service-test"), + new PercentileArgument( + valuesA, + RANKS + ) + ); + BucketedValues valuesB = new BucketedValues( + BUCKETS, + new long[] { + 10, + 20, + 30, + 40 + } + ); + valuesA.setGroup("localhost:3306/swtest"); + + inst.accept( + MeterEntity.newService("service-test"), + new PercentileArgument( + valuesB, + RANKS + ) + ); + + inst.calculate(); + final DataTable values = inst.getPercentileValues(); + /** + * Expected percentile dataset + *
+ * 0 , 10 + * 50 , 20 + * 100, 30 <- P50 + * 250, 40 <- P90 + *+ */ + assertEquals(new Long(100), values.get("localhost:3306/swtest:50")); + assertEquals(new Long(250), values.get("localhost:3306/swtest:90")); } private static class PercentileFunctionInst extends AvgHistogramPercentileFunction {