[
https://issues.apache.org/jira/browse/ZOOKEEPER-4324?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=18083318#comment-18083318
]
David Smiley commented on ZOOKEEPER-4324:
-----------------------------------------
I explored the matter with AI and produced the following summary/proposal:
h3. Root cause confirmed
The static field
[{{DEFAULT_METRICS_FOR_TESTS}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/ServerMetrics.java#L46]
in
[{{ServerMetrics}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/ServerMetrics.java]
unconditionally constructs a
[{{DefaultMetricsProvider}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/metrics/impl/DefaultMetricsProvider.java].
The {{ServerMetrics}} constructor then eagerly registers ~80 metrics, many via
{{{}getSummary(name, ADVANCED){}}}, which builds an
[{{AvgMinMaxPercentileCounter}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/metric/AvgMinMaxPercentileCounter.java]
whose [constructor instantiates
{{com.codahale.metrics.Histogram}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/metric/AvgMinMaxPercentileCounter.java#L106].
Class linking forces Dropwizard {{metrics-core}} onto the classpath the moment
{{ServerMetrics}} is loaded.
Setting {{metricsProvider.className=NullMetricsProvider}} does not help:
{{DEFAULT_METRICS_FOR_TESTS}} is initialized before
{{MetricsProviderBootstrap}} runs.
h3. Proposed fix
A grep shows {{DEFAULT_METRICS_FOR_TESTS}} is *never referenced by name*
anywhere in the tree — its only use is to seed [{{CURRENT}} at line
52|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/ServerMetrics.java#L52].
We can delete it and install the real provider from the test base class.
*1.* In
[{{ServerMetrics}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/server/ServerMetrics.java],
seed {{CURRENT}} with a {{{}NullMetricsProvider{}}}-backed instance and drop
{{{}DEFAULT_METRICS_FOR_TESTS{}}}:
{code:java}
private static volatile ServerMetrics CURRENT =
new ServerMetrics(NullMetricsProvider.INSTANCE);
{code}
The constructor still runs, but every {{{}getCounter{}}}/{{{}getSummary{}}}
call returns a [{{Null*}}
singleton|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/main/java/org/apache/zookeeper/metrics/impl/NullMetricsProvider.java]
— no Dropwizard classes touched.
*2.* In
[{{ZKTestCase}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/test/java/org/apache/zookeeper/ZKTestCase.java],
install the real provider:
{code:java}
static {
ServiceUtils.setSystemExitProcedure(ServiceUtils.LOG_ONLY);
ServerMetrics.metricsProviderInitialized(new DefaultMetricsProvider());
}
{code}
{{ZKTestCase}} is the universal root —
[{{ClientBase}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/test/java/org/apache/zookeeper/test/ClientBase.java]
and
[{{QuorumPeerTestBase}}|https://github.com/apache/zookeeper/blob/master/zookeeper-server/src/test/java/org/apache/zookeeper/server/quorum/QuorumPeerTestBase.java]
both extend it, covering essentially every test that reads or resets metric
values.
h3. Result
* Production: Dropwizard {{metrics-core}} is only loaded when an operator
actually configures
{{{}metricsProvider.className=...DefaultMetricsProvider{}}}. With
{{NullMetricsProvider}} (or any non-Dropwizard provider, e.g. Prometheus), the
JAR is no longer needed at runtime.
* Tests: behavior unchanged — {{ServerMetrics.getMetrics()}} returns a
{{{}DefaultMetricsProvider{}}}-backed instance from the first test class load
onward.
* A handful of standalone tests (e.g. {{{}ServerConfigTest{}}},
{{{}NettyOptionalArchTest{}}}) don't extend {{{}ZKTestCase{}}}, but they don't
assert on metric values, so {{Null*}} metrics are acceptable.
> Hard dependency on io.dropwizard.metrics:metrics-core cannot be avoided
> -----------------------------------------------------------------------
>
> Key: ZOOKEEPER-4324
> URL: https://issues.apache.org/jira/browse/ZOOKEEPER-4324
> Project: ZooKeeper
> Issue Type: Bug
> Components: metric system
> Affects Versions: 3.6.3
> Reporter: Ron Dagostino
> Priority: Major
>
> The metrics subsystem has a hard dependency on
> io.dropwizard.metrics:metrics-core that cannot be avoided because of this
> code:
> public final class ServerMetrics {
> /**
> * Dummy instance useful for tests.
> */
> public static final ServerMetrics DEFAULT_METRICS_FOR_TESTS = new
> ServerMetrics(new DefaultMetricsProvider());
> Even if the config
> metricsProvider.className=org.apache.zookeeper.metrics.impl.NullMetricsProvider
> is set the above code will still execute and create the dependency.
> It would be best to make the dependency optional by removing the above code.
> Another option is to change the dependency scope from the current value of
> "provided" to be "compile" instead.
--
This message was sent by Atlassian Jira
(v8.20.10#820010)