Skip to content

Commit

Permalink
remove metrics from MeterRegistry when shutting down InstrumentedQueu…
Browse files Browse the repository at this point in the history
…edThreadPool

fixes micrometer-metrics#4000
  • Loading branch information
wakingrufus committed Jul 27, 2023
1 parent 11a9f8d commit 95fff2b
Show file tree
Hide file tree
Showing 2 changed files with 121 additions and 0 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -15,11 +15,15 @@
*/
package io.micrometer.core.instrument.binder.jetty;

import io.micrometer.core.instrument.Meter;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import org.eclipse.jetty.util.thread.QueuedThreadPool;

import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.BlockingQueue;
import java.util.stream.Stream;

/**
* A {@link QueuedThreadPool} that binds metrics about the Jetty server thread pool. This
Expand Down Expand Up @@ -116,4 +120,18 @@ protected void doStart() throws Exception {
threadPoolMetrics.bindTo(registry);
}

@Override
protected void doStop() throws Exception {
Set<Tag> tagSet = new HashSet<>();
tags.forEach(tagSet::add);
Stream
.of("jetty.threads.config.min", "jetty.threads.config.max", "jetty.threads.busy", "jetty.threads.jobs",
"jetty.threads.current", "jetty.threads.idle")
.flatMap(name -> registry.find(name).meters().stream())
.map(Meter::getId)
.filter(id -> new HashSet<>(id.getTags()).containsAll(tagSet))
.forEach(registry::remove);
super.doStop();
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
/*
* Copyright 2019 VMware, Inc.
*
* Licensed 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 io.micrometer.core.instrument.binder.jetty;

import io.micrometer.core.instrument.Gauge;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Tag;
import io.micrometer.core.instrument.simple.SimpleMeterRegistry;
import org.assertj.core.api.ListAssert;
import org.eclipse.jetty.util.thread.QueuedThreadPool;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Collections;
import java.util.function.BiFunction;
import java.util.stream.Collectors;

import static org.assertj.core.api.Assertions.assertThat;

class InstrumentedQueuedThreadPoolTest {

@Test
void test_metrics() throws Exception {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
QueuedThreadPool instance = new InstrumentedQueuedThreadPool(meterRegistry,
Collections.singletonList(Tag.of("pool", "1")));

instance.start();

assertThatMetricsExist(meterRegistry);

Gauge jobsGauge = meterRegistry.find("jetty.threads.jobs").gauge();

assertThat(jobsGauge.getId().getTags()).as("ensure metrics have thread pool tag").contains(Tag.of("pool", "1"));

instance.stop();

assertThatMetricsDontExist(meterRegistry);
}

@Test
void test_multiple_pools() throws Exception {
MeterRegistry meterRegistry = new SimpleMeterRegistry();
QueuedThreadPool pool1 = new InstrumentedQueuedThreadPool(meterRegistry,
Collections.singletonList(Tag.of("pool", "1")));

QueuedThreadPool pool2 = new InstrumentedQueuedThreadPool(meterRegistry,
Collections.singletonList(Tag.of("pool", "2")));

pool1.start();
pool2.start();

assertThatMetricsExist(meterRegistry);

assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "1").gauge()).as("pool 1 gauge exists")
.isNotNull();
assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "2").gauge()).as("pool 2 gauge exists")
.isNotNull();

pool1.stop();

assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "1").gauge())
.as("pool 1 gauge no longer exists")
.isNull();
assertThat(meterRegistry.find("jetty.threads.jobs").tag("pool", "2").gauge()).as("pool 2 gauge exists")
.isNotNull();

pool2.stop();

assertThatMetricsDontExist(meterRegistry);
}

private void assertThatMetricsExist(MeterRegistry meterRegistry) {
assertThatMetrics(meterRegistry, (l, a) -> a.containsAll(l));
}

private void assertThatMetricsDontExist(MeterRegistry meterRegistry) {
assertThatMetrics(meterRegistry, (l, a) -> a.doesNotContainAnyElementsOf(l));
}

private void assertThatMetrics(MeterRegistry meterRegistry,
BiFunction<Iterable<String>, ListAssert<String>, ListAssert<String>> assertFunction) {
assertFunction.apply(
Arrays.asList("jetty.threads.jobs", "jetty.threads.busy", "jetty.threads.idle",
"jetty.threads.config.max", "jetty.threads.config.min", "jetty.threads.current"),
assertThat(
meterRegistry.getMeters().stream().map(m -> m.getId().getName()).collect(Collectors.toList())));
}

}

0 comments on commit 95fff2b

Please sign in to comment.