From 0beccc81531fb7d017ac09e9d7d7275ae590971a Mon Sep 17 00:00:00 2001 From: Divij Vaidya Date: Tue, 24 Jun 2025 10:06:04 +0530 Subject: [PATCH 1/4] Emit event loop metrics provided by MicroMeter --- build.gradle | 1 + .../linecorp/armeria/common/CommonPools.java | 21 ++++++++--- .../common/metric/EventLoopMetrics.java | 1 + .../armeria/common/CommonPoolsTest.java | 35 +++++++++++++++++++ dependencies.toml | 3 ++ 5 files changed, 56 insertions(+), 5 deletions(-) create mode 100644 core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java diff --git a/build.gradle b/build.gradle index 0e00819f621..11cd9a1404f 100644 --- a/build.gradle +++ b/build.gradle @@ -270,6 +270,7 @@ configure(projectsWithFlags('java')) { testRuntimeOnly libs.checkerframework // Required by guava-testlib testImplementation libs.assertj testImplementation libs.mockito + testImplementation libs.mockito.inline testImplementation libs.apache.httpclient5 testImplementation libs.hamcrest testImplementation libs.hamcrest.library diff --git a/core/src/main/java/com/linecorp/armeria/common/CommonPools.java b/core/src/main/java/com/linecorp/armeria/common/CommonPools.java index e6302151c48..fb3d175c8cf 100644 --- a/core/src/main/java/com/linecorp/armeria/common/CommonPools.java +++ b/core/src/main/java/com/linecorp/armeria/common/CommonPools.java @@ -22,6 +22,8 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import com.google.common.annotations.VisibleForTesting; + import com.linecorp.armeria.client.ClientFactoryBuilder; import com.linecorp.armeria.common.metric.MeterIdPrefix; import com.linecorp.armeria.common.metric.MoreMeterBinders; @@ -29,6 +31,7 @@ import com.linecorp.armeria.common.util.EventLoopGroups; import com.linecorp.armeria.server.ServerBuilder; +import io.micrometer.core.instrument.binder.netty4.NettyEventExecutorMetrics; import io.netty.channel.EventLoopGroup; /** @@ -45,11 +48,7 @@ public final class CommonPools { EventLoopGroups.newEventLoopGroup(Flags.numCommonWorkers(), "armeria-common-worker", true); static { - // Bind EventLoopMetrics for the common worker group. - MoreMeterBinders - .eventLoopMetrics(WORKER_GROUP, new MeterIdPrefix("armeria.netty.common")) - .bindTo(Flags.meterRegistry()); - + bindEventLoopMetricsForWorkerGroup(WORKER_GROUP); try { final Class aClass = Class.forName("reactor.core.scheduler.Schedulers", true, CommonPools.class.getClassLoader()); @@ -65,6 +64,18 @@ public final class CommonPools { } } + @VisibleForTesting + static void bindEventLoopMetricsForWorkerGroup(EventLoopGroup evGroup) { + // Bind EventLoopMetrics for the common worker group. + MoreMeterBinders + .eventLoopMetrics(evGroup, new MeterIdPrefix("armeria.netty.common")) + .bindTo(Flags.meterRegistry()); + // Bind the common event loop metrics emitted automatically by micrometer. + // These metrics intentionally duplicate those emitted by EventLoopMetrics to preserve + // backward compatibility. + new NettyEventExecutorMetrics(evGroup).bindTo(Flags.meterRegistry()); + } + /** * Returns the default common blocking task {@link BlockingTaskExecutor} which is used for * potentially long-running tasks which may block I/O threads. diff --git a/core/src/main/java/com/linecorp/armeria/common/metric/EventLoopMetrics.java b/core/src/main/java/com/linecorp/armeria/common/metric/EventLoopMetrics.java index 760486b7b81..24af2ce7742 100644 --- a/core/src/main/java/com/linecorp/armeria/common/metric/EventLoopMetrics.java +++ b/core/src/main/java/com/linecorp/armeria/common/metric/EventLoopMetrics.java @@ -98,6 +98,7 @@ void remove(EventLoopGroup eventLoopGroup) { return result; } + @Deprecated // use the same metric with micrometer namespace instead double pendingTasks() { int result = 0; for (EventLoopGroup group : registry) { diff --git a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java new file mode 100644 index 00000000000..e72f413223a --- /dev/null +++ b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java @@ -0,0 +1,35 @@ +package com.linecorp.armeria.common; + +import static org.assertj.core.api.AssertionsForClassTypes.assertThat; +import static org.mockito.ArgumentMatchers.any; +import static org.mockito.Mockito.verify; + +import org.junit.jupiter.api.Test; +import org.mockito.MockedConstruction; +import org.mockito.Mockito; + +import com.linecorp.armeria.common.util.EventLoopGroups; + +import io.micrometer.core.instrument.binder.netty4.NettyEventExecutorMetrics; +import io.netty.channel.EventLoopGroup; + +public class CommonPoolsTest { + @Test + public void testEventLoopMetricsBinding() throws Exception { + final EventLoopGroup testGroup = EventLoopGroups.newEventLoopGroup(1); + + try { + try (MockedConstruction microMeterEventloopMetrics = + Mockito.mockConstruction(NettyEventExecutorMetrics.class)) { + CommonPools.bindEventLoopMetricsForWorkerGroup(testGroup); + + assertThat(microMeterEventloopMetrics.constructed().isEmpty()).isFalse(); + + final NettyEventExecutorMetrics instance = microMeterEventloopMetrics.constructed().get(0); + verify(instance).bindTo(any()); + } + } finally { + testGroup.shutdownNow(); + } + } +} diff --git a/dependencies.toml b/dependencies.toml index c571a296b3b..b5de5c1ecc4 100644 --- a/dependencies.toml +++ b/dependencies.toml @@ -919,6 +919,9 @@ version.ref = "mockito" [libraries.mockito-junit-jupiter] module = "org.mockito:mockito-junit-jupiter" version.ref = "mockito" +[libraries.mockito-inline] +module = "org.mockito:mockito-inline" +version.ref = "mockito" [libraries.monix-reactive_v212] module = "io.monix:monix-reactive_2.12" From 24bc1f702f0aef88adc7cb04f7665e7d66f7fd22 Mon Sep 17 00:00:00 2001 From: Divij Vaidya Date: Fri, 27 Jun 2025 15:45:53 +0530 Subject: [PATCH 2/4] Simpify test and remove dependency on mockito inline --- build.gradle | 1 - .../armeria/common/CommonPoolsTest.java | 43 +++++++++++++------ dependencies.toml | 3 -- 3 files changed, 29 insertions(+), 18 deletions(-) diff --git a/build.gradle b/build.gradle index 11cd9a1404f..0e00819f621 100644 --- a/build.gradle +++ b/build.gradle @@ -270,7 +270,6 @@ configure(projectsWithFlags('java')) { testRuntimeOnly libs.checkerframework // Required by guava-testlib testImplementation libs.assertj testImplementation libs.mockito - testImplementation libs.mockito.inline testImplementation libs.apache.httpclient5 testImplementation libs.hamcrest testImplementation libs.hamcrest.library diff --git a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java index e72f413223a..8db68bee276 100644 --- a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java +++ b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java @@ -1,16 +1,31 @@ +/* + * Copyright 2025 LINE Corporation + * + * LINE Corporation licenses this file to you under the Apache License, + * version 2.0 (the "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at: + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT + * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the + * License for the specific language governing permissions and limitations + * under the License. + */ + package com.linecorp.armeria.common; import static org.assertj.core.api.AssertionsForClassTypes.assertThat; -import static org.mockito.ArgumentMatchers.any; -import static org.mockito.Mockito.verify; + +import java.util.Map; import org.junit.jupiter.api.Test; -import org.mockito.MockedConstruction; -import org.mockito.Mockito; +import com.linecorp.armeria.common.metric.MoreMeters; import com.linecorp.armeria.common.util.EventLoopGroups; -import io.micrometer.core.instrument.binder.netty4.NettyEventExecutorMetrics; +import io.micrometer.core.instrument.binder.netty4.NettyMeters; import io.netty.channel.EventLoopGroup; public class CommonPoolsTest { @@ -19,15 +34,15 @@ public void testEventLoopMetricsBinding() throws Exception { final EventLoopGroup testGroup = EventLoopGroups.newEventLoopGroup(1); try { - try (MockedConstruction microMeterEventloopMetrics = - Mockito.mockConstruction(NettyEventExecutorMetrics.class)) { - CommonPools.bindEventLoopMetricsForWorkerGroup(testGroup); - - assertThat(microMeterEventloopMetrics.constructed().isEmpty()).isFalse(); - - final NettyEventExecutorMetrics instance = microMeterEventloopMetrics.constructed().get(0); - verify(instance).bindTo(any()); - } + CommonPools.bindEventLoopMetricsForWorkerGroup(testGroup); + + // verify that registry contains the newly added metrics + final Map registeredMeters = MoreMeters.measureAll(Flags.meterRegistry()); + assertThat(registeredMeters.keySet() + .stream() + .anyMatch(key -> key.startsWith( + NettyMeters.EVENT_EXECUTOR_TASKS_PENDING.getName()))) + .isTrue(); } finally { testGroup.shutdownNow(); } diff --git a/dependencies.toml b/dependencies.toml index b5de5c1ecc4..c571a296b3b 100644 --- a/dependencies.toml +++ b/dependencies.toml @@ -919,9 +919,6 @@ version.ref = "mockito" [libraries.mockito-junit-jupiter] module = "org.mockito:mockito-junit-jupiter" version.ref = "mockito" -[libraries.mockito-inline] -module = "org.mockito:mockito-inline" -version.ref = "mockito" [libraries.monix-reactive_v212] module = "io.monix:monix-reactive_2.12" From d3f8740c2b91f52c52b80dd798a13ad216a41cbb Mon Sep 17 00:00:00 2001 From: Divij Vaidya Date: Mon, 30 Jun 2025 15:29:57 +0530 Subject: [PATCH 3/4] add new guideline for header --- .../test/java/com/linecorp/armeria/common/CommonPoolsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java index 8db68bee276..c4806d3de35 100644 --- a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java +++ b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java @@ -1,5 +1,5 @@ /* - * Copyright 2025 LINE Corporation + * Copyright $today.year LY Corporation * * LINE Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance From 0bf2e085192a22c356aefb8e49d1bf9097aaf262 Mon Sep 17 00:00:00 2001 From: Divij Vaidya Date: Mon, 30 Jun 2025 19:52:55 +0530 Subject: [PATCH 4/4] Revert "add new guideline for header" This reverts commit d3f8740c2b91f52c52b80dd798a13ad216a41cbb. --- .../test/java/com/linecorp/armeria/common/CommonPoolsTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java index c4806d3de35..8db68bee276 100644 --- a/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java +++ b/core/src/test/java/com/linecorp/armeria/common/CommonPoolsTest.java @@ -1,5 +1,5 @@ /* - * Copyright $today.year LY Corporation + * Copyright 2025 LINE Corporation * * LINE Corporation licenses this file to you under the Apache License, * version 2.0 (the "License"); you may not use this file except in compliance