diff --git a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetrics.java b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetrics.java index ff8cbae995..9bb7da9b95 100644 --- a/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetrics.java +++ b/micrometer-core/src/main/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetrics.java @@ -17,6 +17,7 @@ import io.micrometer.common.lang.NonNullApi; import io.micrometer.common.lang.NonNullFields; +import io.micrometer.core.instrument.FunctionCounter; import io.micrometer.core.instrument.Gauge; import io.micrometer.core.instrument.MeterRegistry; import io.micrometer.core.instrument.Tag; @@ -66,6 +67,10 @@ public void bindTo(MeterRegistry registry) { .description("The current number of live threads including both daemon and non-daemon threads") .baseUnit(BaseUnits.THREADS).register(registry); + FunctionCounter.builder("jvm.threads.started", threadBean, ThreadMXBean::getTotalStartedThreadCount).tags(tags) + .description("The total number of application threads started in the JVM").baseUnit(BaseUnits.THREADS) + .register(registry); + try { threadBean.getAllThreadIds(); for (Thread.State state : Thread.State.values()) { diff --git a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetricsTest.java b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetricsTest.java index e55adeab7a..0eafad2e78 100644 --- a/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetricsTest.java +++ b/micrometer-core/src/test/java/io/micrometer/core/instrument/binder/jvm/JvmThreadMetricsTest.java @@ -39,18 +39,20 @@ class JvmThreadMetricsTest { void threadMetrics() { MeterRegistry registry = new SimpleMeterRegistry(); new JvmThreadMetrics().bindTo(registry); + double initialThreadCount = registry.get("jvm.threads.started").functionCounter().count(); - assertThat(registry.get("jvm.threads.live").gauge().value()).isGreaterThan(0); - assertThat(registry.get("jvm.threads.daemon").gauge().value()).isGreaterThan(0); - assertThat(registry.get("jvm.threads.peak").gauge().value()).isGreaterThan(0); - assertThat(registry.get("jvm.threads.states").tag("state", "runnable").gauge().value()).isGreaterThan(0); + assertThat(registry.get("jvm.threads.live").gauge().value()).isPositive(); + assertThat(registry.get("jvm.threads.daemon").gauge().value()).isPositive(); + assertThat(registry.get("jvm.threads.peak").gauge().value()).isPositive(); + assertThat(registry.get("jvm.threads.states").tag("state", "runnable").gauge().value()).isPositive(); createBlockedThread(); - assertThat(registry.get("jvm.threads.states").tag("state", "blocked").gauge().value()).isGreaterThan(0); - assertThat(registry.get("jvm.threads.states").tag("state", "waiting").gauge().value()).isGreaterThan(0); + assertThat(registry.get("jvm.threads.states").tag("state", "blocked").gauge().value()).isPositive(); + assertThat(registry.get("jvm.threads.states").tag("state", "waiting").gauge().value()).isPositive(); createTimedWaitingThread(); - assertThat(registry.get("jvm.threads.states").tag("state", "timed-waiting").gauge().value()).isGreaterThan(0); + assertThat(registry.get("jvm.threads.states").tag("state", "timed-waiting").gauge().value()).isPositive(); + assertThat(registry.get("jvm.threads.started").functionCounter().count()).isGreaterThan(initialThreadCount); } @Test