Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Log4j2Metrics creates more MetricsFilter instances than needed #5818

Merged
merged 1 commit into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -31,9 +31,9 @@
import org.apache.logging.log4j.core.filter.AbstractFilter;
import org.apache.logging.log4j.core.filter.CompositeFilter;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;

import static java.util.Collections.emptyList;

Expand Down Expand Up @@ -61,7 +61,7 @@ public class Log4j2Metrics implements MeterBinder, AutoCloseable {

private final LoggerContext loggerContext;

private final List<MetricsFilter> metricsFilters = new ArrayList<>();
private final ConcurrentMap<MeterRegistry, MetricsFilter> metricsFilters = new ConcurrentHashMap<>();

public Log4j2Metrics() {
this(emptyList());
Expand All @@ -80,7 +80,7 @@ public Log4j2Metrics(Iterable<Tag> tags, LoggerContext loggerContext) {
public void bindTo(MeterRegistry registry) {
Configuration configuration = loggerContext.getConfiguration();
LoggerConfig rootLoggerConfig = configuration.getRootLogger();
rootLoggerConfig.addFilter(createMetricsFilterAndStart(registry));
rootLoggerConfig.addFilter(getOrCreateMetricsFilterAndStart(registry));

loggerContext.getConfiguration()
.getLoggers()
Expand All @@ -102,25 +102,26 @@ public void bindTo(MeterRegistry registry) {
if (logFilter instanceof MetricsFilter) {
return;
}
loggerConfig.addFilter(createMetricsFilterAndStart(registry));
loggerConfig.addFilter(getOrCreateMetricsFilterAndStart(registry));
});

loggerContext.updateLoggers(configuration);
}

private MetricsFilter createMetricsFilterAndStart(MeterRegistry registry) {
MetricsFilter metricsFilter = new MetricsFilter(registry, tags);
metricsFilter.start();
metricsFilters.add(metricsFilter);
return metricsFilter;
private MetricsFilter getOrCreateMetricsFilterAndStart(MeterRegistry registry) {
return metricsFilters.computeIfAbsent(registry, r -> {
MetricsFilter metricsFilter = new MetricsFilter(r, tags);
metricsFilter.start();
return metricsFilter;
});
}

@Override
public void close() {
if (!metricsFilters.isEmpty()) {
Configuration configuration = loggerContext.getConfiguration();
LoggerConfig rootLoggerConfig = configuration.getRootLogger();
metricsFilters.forEach(rootLoggerConfig::removeFilter);
metricsFilters.values().forEach(rootLoggerConfig::removeFilter);

loggerContext.getConfiguration()
.getLoggers()
Expand All @@ -129,12 +130,13 @@ public void close() {
.filter(loggerConfig -> !loggerConfig.isAdditive())
.forEach(loggerConfig -> {
if (loggerConfig != rootLoggerConfig) {
metricsFilters.forEach(loggerConfig::removeFilter);
metricsFilters.values().forEach(loggerConfig::removeFilter);
}
});

loggerContext.updateLoggers(configuration);
metricsFilters.forEach(MetricsFilter::stop);
metricsFilters.values().forEach(MetricsFilter::stop);
metricsFilters.clear();
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.core.Filter;
import org.apache.logging.log4j.core.LoggerContext;
import org.apache.logging.log4j.core.config.Configuration;
import org.apache.logging.log4j.core.config.ConfigurationSource;
Expand All @@ -34,6 +35,7 @@

import java.io.IOException;
import java.time.Duration;
import java.util.Iterator;

import static java.util.Collections.emptyList;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -184,4 +186,47 @@ void asyncLogShouldNotBeDuplicated() throws IOException {
.until(() -> registry.get("log4j2.events").tags("level", "info").counter().count() == 3);
}

@Test
void metricsFilterIsReused() {
LoggerContext loggerContext = new LoggerContext("test");

LoggerConfig loggerConfig = new LoggerConfig("com.test", Level.INFO, false);
Configuration configuration = loggerContext.getConfiguration();
configuration.addLogger("com.test", loggerConfig);
loggerContext.setConfiguration(configuration);
loggerContext.updateLoggers();

Logger logger1 = loggerContext.getLogger("com.test.log1");
loggerContext.getLogger("com.test.log2");

new Log4j2Metrics(emptyList(), loggerContext).bindTo(registry);
Iterator<Filter> rootFilters = loggerContext.getRootLogger().getFilters();
Log4j2Metrics.MetricsFilter rootFilter = (Log4j2Metrics.MetricsFilter) rootFilters.next();
assertThat(rootFilters.hasNext()).isFalse();

Log4j2Metrics.MetricsFilter logger1Filter = (Log4j2Metrics.MetricsFilter) loggerContext.getConfiguration()
.getLoggerConfig(logger1.getName())
.getFilter();
assertThat(logger1Filter).isEqualTo(rootFilter);
}

@Test
void multipleRegistriesCanBeBound() {
MeterRegistry registry2 = new SimpleMeterRegistry();

Log4j2Metrics log4j2Metrics = new Log4j2Metrics(emptyList());
log4j2Metrics.bindTo(registry);

Logger logger = LogManager.getLogger(Log4j2MetricsTest.class);
Configurator.setLevel(logger, Level.INFO);
logger.info("Hello, world!");
assertThat(registry.get("log4j2.events").tags("level", "info").counter().count()).isEqualTo(1);

log4j2Metrics.bindTo(registry2);
logger.info("Hello, world!");
assertThat(registry.get("log4j2.events").tags("level", "info").counter().count()).isEqualTo(2);
assertThat(registry2.get("log4j2.events").tags("level", "info").counter().count()).isEqualTo(1);

}

}
Loading