This is an automated email from the ASF dual-hosted git repository.

abhishekrb pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new e0baddd1edb Gracefully handle negative counter values for 
prometheus-emitter & update metric types for `sys/disk/*` metrics (#18719)
e0baddd1edb is described below

commit e0baddd1edb76fa2c16b7a180b2a9a9aee2a9d24
Author: aho135 <[email protected]>
AuthorDate: Mon Nov 17 15:45:19 2025 -0800

    Gracefully handle negative counter values for prometheus-emitter & update 
metric types for `sys/disk/*` metrics (#18719)
    
    Graceful handling of prometheus counter values when a negative value is 
encountered.
    Update the OshiSysMonitor DiskStats sys/disk/* delta metrics from counter 
to gauge type for prometheus-emitter, dropwizard-emitter and statsd-emitter.
---
 .../main/resources/defaultMetricDimensions.json    | 12 +++++-----
 .../emitter/prometheus/PrometheusEmitter.java      |  9 +++++--
 .../src/main/resources/defaultMetrics.json         | 16 ++++++-------
 .../emitter/prometheus/PrometheusEmitterTest.java  | 28 +++++++++++++++-------
 .../main/resources/defaultMetricDimensions.json    | 12 +++++-----
 5 files changed, 47 insertions(+), 30 deletions(-)

diff --git 
a/extensions-contrib/dropwizard-emitter/src/main/resources/defaultMetricDimensions.json
 
b/extensions-contrib/dropwizard-emitter/src/main/resources/defaultMetricDimensions.json
index 623cce0e3e8..8e24ff49683 100644
--- 
a/extensions-contrib/dropwizard-emitter/src/main/resources/defaultMetricDimensions.json
+++ 
b/extensions-contrib/dropwizard-emitter/src/main/resources/defaultMetricDimensions.json
@@ -449,33 +449,33 @@
     "dimensions": [
       "fsDevName"
     ],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/disk/read/count": {
     "dimensions": [
       "fsDevName"
     ],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/disk/write/size": {
     "dimensions": [
       "fsDevName"
     ],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/disk/read/size": {
     "dimensions": [
       "fsDevName"
     ],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/net/write/size": {
     "dimensions": [],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/net/read/size": {
     "dimensions": [],
-    "type": "counter"
+    "type": "gauge"
   },
   "sys/fs/used": {
     "dimensions": [
diff --git 
a/extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
 
b/extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
index 4cad38a511a..60af27fcd4d 100644
--- 
a/extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
+++ 
b/extensions-contrib/prometheus-emitter/src/main/java/org/apache/druid/emitter/prometheus/PrometheusEmitter.java
@@ -179,8 +179,13 @@ public class PrometheusEmitter implements Emitter
       }
 
       if (metric.getCollector() instanceof Counter) {
-        ((Counter) 
metric.getCollector()).labels(labelValues).inc(value.doubleValue());
-        metric.resetLastUpdateTime(Arrays.asList(labelValues));
+        double metricValue = value.doubleValue();
+        if (metricValue >= 0) {
+          ((Counter) 
metric.getCollector()).labels(labelValues).inc(metricValue);
+          metric.resetLastUpdateTime(Arrays.asList(labelValues));
+        } else {
+          log.warn("Counter increment amount must be non-negative, but got 
value[%f] for metric[%s]. If this is valid, metric should be defined as a gauge 
instead of counter.", metricValue, name);
+        }
       } else if (metric.getCollector() instanceof Gauge) {
         ((Gauge) 
metric.getCollector()).labels(labelValues).set(value.doubleValue());
         metric.resetLastUpdateTime(Arrays.asList(labelValues));
diff --git 
a/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json 
b/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
index a4fa1e83f92..82ced1e9abb 100644
--- 
a/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
+++ 
b/extensions-contrib/prometheus-emitter/src/main/resources/defaultMetrics.json
@@ -223,16 +223,16 @@
   "sys/swap/max" : { "dimensions" : [], "type" : "gauge", "help": "Max swap"},
   "sys/swap/pageIn" : { "dimensions" : [], "type" : "gauge", "help": "Paged in 
swap"},
   "sys/swap/pageOut" : { "dimensions" : [], "type" : "gauge", "help": "Paged 
out swap"},
-  "sys/disk/write/count" : { "dimensions" : ["diskName"], "type" : "count", 
"help": "Writes to disk."},
-  "sys/disk/read/count" : { "dimensions" : ["diskName"], "type" : "count", 
"help": "Reads from disk."},
-  "sys/disk/write/size" : { "dimensions" : ["diskName"], "type" : "count", 
"help": "Bytes written to disk. Can we used to determine how much paging is 
occurring with regards to segments."},
-  "sys/disk/read/size" : { "dimensions" : ["diskName"], "type" : "count", 
"help": "Bytes read from disk. Can we used to determine how much paging is 
occurring with regards to segments."},
+  "sys/disk/write/count" : { "dimensions" : ["diskName"], "type" : "gauge", 
"help": "Writes to disk."},
+  "sys/disk/read/count" : { "dimensions" : ["diskName"], "type" : "gauge", 
"help": "Reads from disk."},
+  "sys/disk/write/size" : { "dimensions" : ["diskName"], "type" : "gauge", 
"help": "Bytes written to disk. Can we used to determine how much paging is 
occurring with regards to segments."},
+  "sys/disk/read/size" : { "dimensions" : ["diskName"], "type" : "gauge", 
"help": "Bytes read from disk. Can we used to determine how much paging is 
occurring with regards to segments."},
   "sys/disk/queue" : { "dimensions" : ["diskName"], "type" : "gauge", "help": 
"Disk queue length."},
   "sys/disk/transferTime" : { "dimensions" : ["diskName"], "type" : "timer", 
"help": "Transfer time to read from or write to disk"},
-  "sys/net/write/size" : { "dimensions" : [], "type" : "count", "help": "Bytes 
written to the network."},
-  "sys/net/read/size" : { "dimensions" : [], "type" : "count", "help":  "Bytes 
read from the network."},
-  "sys/net/read/packets" : { "dimensions" : [], "type" : "count", "help": 
"Total packets read from the network"},
-  "sys/net/write/packets" : { "dimensions" : [], "type" : "count", "help": 
"Total packets written to the network"},
+  "sys/net/write/size" : { "dimensions" : [], "type" : "gauge", "help": "Bytes 
written to the network."},
+  "sys/net/read/size" : { "dimensions" : [], "type" : "gauge", "help":  "Bytes 
read from the network."},
+  "sys/net/read/packets" : { "dimensions" : [], "type" : "gauge", "help": 
"Total packets read from the network"},
+  "sys/net/write/packets" : { "dimensions" : [], "type" : "gauge", "help": 
"Total packets written to the network"},
   "sys/net/read/errors" : { "dimensions" : [], "type" : "gauge", "help": 
"Total network read errors"},
   "sys/net/write/errors" : { "dimensions" : [], "type" : "gauge", "help": 
"Total network write errors"},
   "sys/net/read/dropped" : { "dimensions" : [], "type" : "gauge", "help": 
"Total packets dropped coming from network"},
diff --git 
a/extensions-contrib/prometheus-emitter/src/test/java/org/apache/druid/emitter/prometheus/PrometheusEmitterTest.java
 
b/extensions-contrib/prometheus-emitter/src/test/java/org/apache/druid/emitter/prometheus/PrometheusEmitterTest.java
index 88ce81629c4..2158260afb3 100644
--- 
a/extensions-contrib/prometheus-emitter/src/test/java/org/apache/druid/emitter/prometheus/PrometheusEmitterTest.java
+++ 
b/extensions-contrib/prometheus-emitter/src/test/java/org/apache/druid/emitter/prometheus/PrometheusEmitterTest.java
@@ -28,6 +28,7 @@ import 
org.apache.druid.java.util.common.concurrent.ScheduledExecutors;
 import org.apache.druid.java.util.emitter.core.Emitter;
 import org.apache.druid.java.util.emitter.service.ServiceMetricEvent;
 import org.easymock.EasyMock;
+import org.junit.After;
 import org.junit.Assert;
 import org.junit.Test;
 
@@ -49,7 +50,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithServiceLabel()
   {
-    CollectorRegistry.defaultRegistry.clear();
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, null, null, 
0, null, false, true, 60, null, false, null);
     PrometheusEmitterModule prometheusEmitterModule = new 
PrometheusEmitterModule();
     Emitter emitter = prometheusEmitterModule.getEmitter(config);
@@ -70,7 +70,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithServiceAndHostLabel()
   {
-    CollectorRegistry.defaultRegistry.clear();
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, null, null, 
0, null, true, true, 60, null, false, null);
     PrometheusEmitterModule prometheusEmitterModule = new 
PrometheusEmitterModule();
     Emitter emitter = prometheusEmitterModule.getEmitter(config);
@@ -91,7 +90,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithExtraLabels()
   {
-    CollectorRegistry.defaultRegistry.clear();
     Map<String, String> extraLabels = new HashMap<>();
     extraLabels.put("labelName", "labelValue");
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, null, null, 
0, null, false, false, 60, extraLabels, false, null);
@@ -113,7 +111,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithServiceLabelAndExtraLabel()
   {
-    CollectorRegistry.defaultRegistry.clear();
     Map<String, String> extraLabels = new HashMap<>();
     extraLabels.put("labelName", "labelValue");
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, null, null, 
0, null, false, true, 60, extraLabels, false, null);
@@ -135,7 +132,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithEmptyExtraLabels()
   {
-    CollectorRegistry.defaultRegistry.clear();
     Map<String, String> extraLabels = new HashMap<>();
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, null, null, 
0, null, false, true, 60, extraLabels, false, null);
     PrometheusEmitterModule prometheusEmitterModule = new 
PrometheusEmitterModule();
@@ -156,7 +152,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithMultipleExtraLabels()
   {
-    CollectorRegistry.defaultRegistry.clear();
     Map<String, String> extraLabels = new HashMap<>();
     extraLabels.put("labelName1", "labelValue1");
     extraLabels.put("labelName2", "labelValue2");
@@ -179,7 +174,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterWithLabelCollision()
   {
-    CollectorRegistry.defaultRegistry.clear();
     // ExtraLabels contains a label that collides with a service label
     Map<String, String> extraLabels = new HashMap<>();
     extraLabels.put("server", "collisionLabelValue");
@@ -209,7 +203,6 @@ public class PrometheusEmitterTest
   @Test
   public void testEmitterMetric()
   {
-    CollectorRegistry.defaultRegistry.clear();
     PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.pushgateway, 
"namespace", null, 0, "pushgateway", true, true, 60, null, false, null);
     PrometheusEmitterModule prometheusEmitterModule = new 
PrometheusEmitterModule();
     Emitter emitter = prometheusEmitterModule.getEmitter(config);
@@ -598,4 +591,23 @@ public class PrometheusEmitterTest
     Assert.assertEquals(1, metric.getLabelValuesToStopwatch().size());
     emitter.close();
   }
+
+  @Test
+  public void testCounterWithNegativeValue()
+  {
+    PrometheusEmitterConfig config = new 
PrometheusEmitterConfig(PrometheusEmitterConfig.Strategy.exporter, "test", 
null, 0, null, true, true, null, null, false, null);
+    PrometheusEmitter emitter = new PrometheusEmitter(config);
+    ServiceMetricEvent event = ServiceMetricEvent.builder()
+            .setMetric("segment/moveSkipped/count", -1)
+            .setDimension("server", "historical1")
+            .build(ImmutableMap.of("service", "historical", "host", 
"druid.test.cn"));
+    emitter.emit(event);
+    emitter.close();
+  }
+
+  @After
+  public void tearDown()
+  {
+    CollectorRegistry.defaultRegistry.clear();
+  }
 }
diff --git 
a/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
 
b/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
index bc28ace0b04..4da2d27a2b0 100644
--- 
a/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
+++ 
b/extensions-contrib/statsd-emitter/src/main/resources/defaultMetricDimensions.json
@@ -137,12 +137,12 @@
   "sys/swap/max" : { "dimensions" : [], "type" : "gauge"},
   "sys/swap/pageIn" : { "dimensions" : [], "type" : "gauge"},
   "sys/swap/pageOut" : { "dimensions" : [], "type" : "gauge"},
-  "sys/disk/write/count" : { "dimensions" : ["fsDevName"], "type" : "count"},
-  "sys/disk/read/count" : { "dimensions" : ["fsDevName"], "type" : "count"},
-  "sys/disk/write/size" : { "dimensions" : ["fsDevName"], "type" : "count"},
-  "sys/disk/read/size" : { "dimensions" : ["fsDevName"], "type" : "count"},
-  "sys/net/write/size" : { "dimensions" : [], "type" : "count"},
-  "sys/net/read/size" : { "dimensions" : [], "type" : "count"},
+  "sys/disk/write/count" : { "dimensions" : ["fsDevName"], "type" : "gauge"},
+  "sys/disk/read/count" : { "dimensions" : ["fsDevName"], "type" : "gauge"},
+  "sys/disk/write/size" : { "dimensions" : ["fsDevName"], "type" : "gauge"},
+  "sys/disk/read/size" : { "dimensions" : ["fsDevName"], "type" : "gauge"},
+  "sys/net/write/size" : { "dimensions" : [], "type" : "gauge"},
+  "sys/net/read/size" : { "dimensions" : [], "type" : "gauge"},
   "sys/fs/used" : { "dimensions" : ["fsDevName", "fsDirName", "fsTypeName", 
"fsSysTypeName", "fsOptions"], "type" : "gauge"},
   "sys/fs/max" : { "dimensions" : ["fsDevName", "fsDirName", "fsTypeName", 
"fsSysTypeName", "fsOptions"], "type" : "gauge"},
   "sys/mem/used" : { "dimensions" : [], "type" : "gauge"},


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to