diff --git a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/impl/WeightedSnapshot.java b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/impl/WeightedSnapshot.java index ac145db9636..4c9f3bbfb8f 100644 --- a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/impl/WeightedSnapshot.java +++ b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/impl/WeightedSnapshot.java @@ -183,9 +183,10 @@ public PercentileValue[] percentileValues() { @Override public HistogramBucket[] bucketValues() { Double[] buckets = configurationProperties.bucketValues(); + Arrays.sort(buckets); HistogramBucket[] histogramBuckets = new HistogramBucket[buckets.length]; for (int i = 0; i < buckets.length; i++) { - histogramBuckets[i] = new HistogramBucket(buckets[i], i); + histogramBuckets[i] = new HistogramBucket(buckets[i], 0); } return histogramBuckets; } @@ -214,6 +215,10 @@ private double getValue(double quantile) { return values[posx]; } + + public long[] getValues() { + return values; + } /** diff --git a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporter.java b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporter.java index 1a201c10110..b40ff4fd5b4 100644 --- a/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporter.java +++ b/appserver/payara-appserver-modules/microprofile/metrics/src/main/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporter.java @@ -42,6 +42,7 @@ import static fish.payara.microprofile.metrics.MetricUnitsUtils.scaleToBaseUnit; import fish.payara.microprofile.metrics.impl.HistogramImpl; +import fish.payara.microprofile.metrics.impl.TimerImpl; import fish.payara.microprofile.metrics.impl.WeightedSnapshot; import java.io.PrintWriter; import java.io.Writer; @@ -166,7 +167,6 @@ private void exportSampling(MetricID metricID, Sampling sampling, LongSupplier c String summary = globalName(metricID, metadata); appendHELP(summary, metadata); - Snapshot.PercentileValue[] percentileValues = snapshot.percentileValues(); if (snapshot instanceof WeightedSnapshot) { WeightedSnapshot w = (WeightedSnapshot) snapshot; @@ -174,8 +174,8 @@ private void exportSampling(MetricID metricID, Sampling sampling, LongSupplier c if (w.bucketValues() != null && w.bucketValues().length > 0) { appendTYPE(summary, OpenMetricsType.histogram); printCustomPercentile(percentileValues, summary, tags, metadata); - printBuckets(snapshot.bucketValues(), globalName(metricID, metadata, "_bucket"), - tags, metadata, sampling); + printBuckets(snapshot.bucketValues(), globalName(metricID, metadata, "_bucket"), + tags, metadata, sampling, count); } else { appendTYPE(summary, OpenMetricsType.summary); printCustomPercentile(percentileValues, summary, tags, metadata); @@ -189,8 +189,8 @@ private void exportSampling(MetricID metricID, Sampling sampling, LongSupplier c printMedian(percentileValues, summary, tags, metadata); } - appendValue(globalName(metricID, metadata, "_count"), tags, count.getAsLong()); - appendValue(globalName(metricID, metadata, "_sum"), tags, sum.get()); + appendValue(globalName(metricID, metadata, "_count"), tags, ((double) count.getAsLong())); + appendValue(globalName(metricID, metadata, "_sum"), tags, (sum.get()).doubleValue()); } public void printCustomPercentile(Snapshot.PercentileValue[] pencentileValues, String summary, Tag[] tags, Metadata metadata) { @@ -200,12 +200,10 @@ public void printCustomPercentile(Snapshot.PercentileValue[] pencentileValues, S } public void printBuckets(Snapshot.HistogramBucket[] buckets, String summary, Tag[] tags, Metadata metadata, - Sampling sampling) { - int counter = 0; + Sampling sampling, LongSupplier count) { if (sampling != null && sampling instanceof HistogramImpl) { for (Snapshot.HistogramBucket b : buckets) { - appendValue(summary, tags("le", Double.toString(b.getBucket()), tags), b.getCount()); - counter++; + appendValue(summary, tags("le", Double.toString(b.getBucket()), tags), ((double) evaluateBucketCount(b.getBucket(), sampling))); } } else { List bucketsList = Stream.of(buckets) @@ -214,11 +212,26 @@ public void printBuckets(Snapshot.HistogramBucket[] buckets, String summary, Tag for (long b : bucketsList) { double seconds = b / 1000.0; - appendValue(summary, tags("le", Double.toString(seconds), tags), buckets[counter].getCount()); - counter++; + appendValue(summary, tags("le", Double.toString(seconds), tags), ((double) evaluateBucketCount(seconds, sampling))); } } - appendValue(summary, tags("le", "+Inf", tags), Double.parseDouble(Integer.toString(counter))); + appendValue(summary, tags("le", "+Inf", tags), ((double) count.getAsLong())); + } + + public long evaluateBucketCount(double bucket, Sampling sampling) { + Snapshot snapshot = sampling.getSnapshot(); + if (snapshot instanceof WeightedSnapshot) { + WeightedSnapshot weightedSnapshot = (WeightedSnapshot) snapshot; + double[] conversionArray = null; + long[] values = weightedSnapshot.getValues(); + if (sampling instanceof TimerImpl) { + conversionArray = Arrays.stream(values).mapToDouble(l -> l / 1000000000D).toArray(); + } else { + conversionArray = Arrays.stream(values).mapToDouble(l -> Long.valueOf(l).doubleValue()).toArray(); + } + return Arrays.stream(conversionArray).filter(s -> s <= bucket).count(); + } + return 0L; } public void printMedian(Snapshot.PercentileValue[] pencentileValues, String summary, Tag[] tags, Metadata metadata) { @@ -307,9 +320,6 @@ private void appendValue(String globalName, Tag[] tags, double value) { protected String roundValue(Number value) { String valString = value.toString(); - if (valString.endsWith(".0")) { - valString = valString.substring(0, valString.length() - 2); // avoid decimal NNN.0 => NNN - } if (valString.endsWith("000000001")) { valString = valString.substring(0, valString.length() - 9); // cut off double representation error } diff --git a/appserver/payara-appserver-modules/microprofile/metrics/src/test/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporterTest.java b/appserver/payara-appserver-modules/microprofile/metrics/src/test/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporterTest.java index 3f4cbed86ab..a67e53bf6d6 100644 --- a/appserver/payara-appserver-modules/microprofile/metrics/src/test/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporterTest.java +++ b/appserver/payara-appserver-modules/microprofile/metrics/src/test/java/fish/payara/microprofile/metrics/writer/OpenMetricsExporterTest.java @@ -249,7 +249,7 @@ public void tagValuesAreEscaped() { .withName(metricID.getName()) .build(); assertOutputEquals("# TYPE test5_total counter\n" + - "# HELP test5_total \n"+"test5_total{key=\"escape\\\\and\\\"and\\n\"} 13\n", metricID, counter, metadata); + "# HELP test5_total \n"+"test5_total{key=\"escape\\\\and\\\"and\\n\"} 13.0\n", metricID, counter, metadata); } @Test @@ -261,7 +261,7 @@ public void namesAreadyEndingWithSuffixAvoidAppendingSuffixAgain() { .withName(metricID.getName()) .build(); assertOutputEquals("# TYPE my_total counter\n" + - "# HELP my_total \n"+"my_total 13\n", metricID, counter, metadata); + "# HELP my_total \n"+"my_total 13.0\n", metricID, counter, metadata); } @Test @@ -322,27 +322,27 @@ public void emptyDescriptionDoesNotPrintHelpLine() { .withDescription("") .build(); assertOutputEquals("# TYPE test1_total counter\n" + - "# HELP test1_total \n"+"test1_total 13\n", metricID, counter, metadata); + "# HELP test1_total \n"+"test1_total 13.0\n", metricID, counter, metadata); } @Test public void unitAnyBitsHasBaseUnitBytes() { assertUnitConversion(MetricUnits.BITS, 1, "bytes", "0.125"); - assertUnitConversion(MetricUnits.BITS, 64, "bytes", "8"); + assertUnitConversion(MetricUnits.BITS, 64, "bytes", "8.0"); // those that scale with 1000 - assertUnitConversion(MetricUnits.KILOBITS, 1, "bytes", "125"); - assertUnitConversion(MetricUnits.KILOBITS, 1000, "bytes", "125000"); - assertUnitConversion(MetricUnits.KILOBITS, 1024, "bytes", "128000"); - assertUnitConversion(MetricUnits.KILOBITS, 1000, "bytes", "125000"); - assertUnitConversion(MetricUnits.KILOBITS, 999, "bytes", "124875"); - assertUnitConversion(MetricUnits.MEGABITS, 5, "bytes", "625000"); + assertUnitConversion(MetricUnits.KILOBITS, 1, "bytes", "125.0"); + assertUnitConversion(MetricUnits.KILOBITS, 1000, "bytes", "125000.0"); + assertUnitConversion(MetricUnits.KILOBITS, 1024, "bytes", "128000.0"); + assertUnitConversion(MetricUnits.KILOBITS, 1000, "bytes", "125000.0"); + assertUnitConversion(MetricUnits.KILOBITS, 999, "bytes", "124875.0"); + assertUnitConversion(MetricUnits.MEGABITS, 5, "bytes", "625000.0"); assertUnitConversion(MetricUnits.MEGABITS, 1024, "bytes", "1.28E8"); assertUnitConversion(MetricUnits.GIGABITS, 2, "bytes", "2.5E8"); // those that scale with 1024 - assertUnitConversion(MetricUnits.MEBIBITS, 1, "bytes", "131072"); - assertUnitConversion(MetricUnits.MEBIBITS, 23, "bytes", "3014656"); + assertUnitConversion(MetricUnits.MEBIBITS, 1, "bytes", "131072.0"); + assertUnitConversion(MetricUnits.MEBIBITS, 23, "bytes", "3014656.0"); assertUnitConversion(MetricUnits.GIBIBITS, 1, "bytes", "1.34217728E8"); assertUnitConversion(MetricUnits.GIBIBITS, 42, "bytes", "5.637144576E9"); } @@ -351,10 +351,10 @@ public void unitAnyBitsHasBaseUnitBytes() { public void unitAnyBytesHasBaseUnitBytes() { assertUnitConversion(MetricUnits.BYTES, 1, "bytes", "1"); assertUnitConversion(MetricUnits.BYTES, 555, "bytes", "555"); - assertUnitConversion(MetricUnits.KILOBYTES, 1, "bytes", "1000"); - assertUnitConversion(MetricUnits.KILOBYTES, 23, "bytes", "23000"); - assertUnitConversion(MetricUnits.MEGABYTES, 1, "bytes", "1000000"); - assertUnitConversion(MetricUnits.MEGABYTES, 0.5d, "bytes", "500000"); + assertUnitConversion(MetricUnits.KILOBYTES, 1, "bytes", "1000.0"); + assertUnitConversion(MetricUnits.KILOBYTES, 23, "bytes", "23000.0"); + assertUnitConversion(MetricUnits.MEGABYTES, 1, "bytes", "1000000.0"); + assertUnitConversion(MetricUnits.MEGABYTES, 0.5d, "bytes", "500000.0"); } @Test @@ -363,9 +363,9 @@ public void unitAnyTimeHasBaseUnitSeconds() { assertUnitConversion(MetricUnits.MICROSECONDS, 50400000, "seconds", "50.4"); assertUnitConversion(MetricUnits.MILLISECONDS, 123, "seconds", "0.123"); assertUnitConversion(MetricUnits.SECONDS, 42, "seconds", "42"); - assertUnitConversion(MetricUnits.MINUTES, 1, "seconds", "60"); - assertUnitConversion(MetricUnits.HOURS, 2, "seconds", "7200"); - assertUnitConversion(MetricUnits.DAYS, 1, "seconds", "86400"); + assertUnitConversion(MetricUnits.MINUTES, 1, "seconds", "60.0"); + assertUnitConversion(MetricUnits.HOURS, 2, "seconds", "7200.0"); + assertUnitConversion(MetricUnits.DAYS, 1, "seconds", "86400.0"); } private static final AtomicInteger nextNameId = new AtomicInteger(10); diff --git a/appserver/payara-appserver-modules/microprofile/metrics/src/test/resources/examples/GaugeTags.txt b/appserver/payara-appserver-modules/microprofile/metrics/src/test/resources/examples/GaugeTags.txt index 318276c8d6b..119df2f2541 100644 --- a/appserver/payara-appserver-modules/microprofile/metrics/src/test/resources/examples/GaugeTags.txt +++ b/appserver/payara-appserver-modules/microprofile/metrics/src/test/resources/examples/GaugeTags.txt @@ -3,6 +3,6 @@ fooVal_seconds{store="webshop"} 12.345 # TYPE barVal_bytes gauge # HELP barVal_bytes -barVal_bytes{component="backend",store="webshop"} 42000 +barVal_bytes{component="backend",store="webshop"} 42000.0 # HELP barVal_bytes -barVal_bytes{component="frontend",store="webshop"} 63000 +barVal_bytes{component="frontend",store="webshop"} 63000.0