diff --git a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java index 1a6a8f47e75..0fe9cd90bb2 100644 --- a/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java +++ b/artemis-core-client/src/main/java/org/apache/activemq/artemis/api/config/ActiveMQDefaultConfiguration.java @@ -676,6 +676,9 @@ public static String getDefaultHapolicyBackupStrategy() { // Whether or not to report uptime metrics private static final boolean DEFAULT_UPTIME_METRICS = false; + // Whether or not to report logging metrics + private static final boolean DEFAULT_LOGGING_METRICS = false; + // How often (in ms) to scan for expired MQTT sessions private static long DEFAULT_MQTT_SESSION_SCAN_INTERVAL = 500; @@ -1865,6 +1868,13 @@ public static Boolean getDefaultUptimeMetrics() { return DEFAULT_UPTIME_METRICS; } + /** + * Whether or not to report logging metrics + */ + public static Boolean getDefaultLoggingMetrics() { + return DEFAULT_LOGGING_METRICS; + } + /** * How often (in ms) to scan for expired MQTT sessions */ diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/MetricsConfiguration.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/MetricsConfiguration.java index aa1173048e3..566b1a25bde 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/MetricsConfiguration.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/config/MetricsConfiguration.java @@ -30,6 +30,7 @@ public class MetricsConfiguration implements Serializable { private boolean fileDescriptors = ActiveMQDefaultConfiguration.getDefaultFileDescriptorsMetrics(); private boolean processor = ActiveMQDefaultConfiguration.getDefaultProcessorMetrics(); private boolean uptime = ActiveMQDefaultConfiguration.getDefaultUptimeMetrics(); + private boolean logging = ActiveMQDefaultConfiguration.getDefaultLoggingMetrics(); private ActiveMQMetricsPlugin plugin; public boolean isJvmMemory() { @@ -95,6 +96,15 @@ public MetricsConfiguration setUptime(boolean uptime) { return this; } + public boolean isLogging() { + return logging; + } + + public MetricsConfiguration setLogging(boolean logging) { + this.logging = logging; + return this; + } + public ActiveMQMetricsPlugin getPlugin() { return plugin; } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java index 7ec64918f4c..527afd5f378 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/deployers/impl/FileConfigurationParser.java @@ -1012,6 +1012,8 @@ private void parseMetrics(final Element e, final Configuration config) { metricsConfiguration.setProcessor(XMLUtil.parseBoolean(child)); } else if (child.getNodeName().equals("uptime")) { metricsConfiguration.setUptime(XMLUtil.parseBoolean(child)); + } else if (child.getNodeName().equals("logging")) { + metricsConfiguration.setLogging(XMLUtil.parseBoolean(child)); } else if (child.getNodeName().equals("plugin")) { metricsConfiguration.setPlugin(parseMetricsPlugin(child, config)); } diff --git a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/metrics/MetricsManager.java b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/metrics/MetricsManager.java index 5d2ca011d21..bc688f99cc2 100644 --- a/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/metrics/MetricsManager.java +++ b/artemis-server/src/main/java/org/apache/activemq/artemis/core/server/metrics/MetricsManager.java @@ -32,6 +32,7 @@ import io.micrometer.core.instrument.binder.jvm.JvmGcMetrics; import io.micrometer.core.instrument.binder.jvm.JvmMemoryMetrics; import io.micrometer.core.instrument.binder.jvm.JvmThreadMetrics; +import io.micrometer.core.instrument.binder.logging.Log4j2Metrics; import io.micrometer.core.instrument.binder.system.FileDescriptorMetrics; import io.micrometer.core.instrument.binder.system.ProcessorMetrics; import io.micrometer.core.instrument.binder.system.UptimeMetrics; @@ -86,6 +87,9 @@ public MetricsManager(String brokerName, if (metricsConfiguration.isUptime()) { new UptimeMetrics().bindTo(meterRegistry); } + if (metricsConfiguration.isLogging()) { + new Log4j2Metrics().bindTo(meterRegistry); + } } } diff --git a/artemis-server/src/main/resources/schema/artemis-configuration.xsd b/artemis-server/src/main/resources/schema/artemis-configuration.xsd index 7355fdbeed6..7bca911b289 100644 --- a/artemis-server/src/main/resources/schema/artemis-configuration.xsd +++ b/artemis-server/src/main/resources/schema/artemis-configuration.xsd @@ -4836,6 +4836,14 @@ + + + + whether or not to report logging metrics + + + + diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DefaultsFileConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DefaultsFileConfigurationTest.java index 67047637529..4bed395d56f 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DefaultsFileConfigurationTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/DefaultsFileConfigurationTest.java @@ -147,6 +147,8 @@ public void testDefaults() { Assert.assertEquals(ActiveMQDefaultConfiguration.getDefaultProcessorMetrics(), conf.getMetricsConfiguration().isProcessor()); Assert.assertEquals(ActiveMQDefaultConfiguration.getDefaultUptimeMetrics(), conf.getMetricsConfiguration().isUptime()); + + Assert.assertEquals(ActiveMQDefaultConfiguration.getDefaultLoggingMetrics(), conf.getMetricsConfiguration().isLogging()); } // Protected --------------------------------------------------------------------------------------------- diff --git a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java index 48516272d55..60a6a0e2d96 100644 --- a/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java +++ b/artemis-server/src/test/java/org/apache/activemq/artemis/core/config/impl/FileConfigurationTest.java @@ -584,6 +584,7 @@ public void testDefaults() { assertTrue(metricsConfiguration.isFileDescriptors()); assertTrue(metricsConfiguration.isProcessor()); assertTrue(metricsConfiguration.isUptime()); + assertTrue(metricsConfiguration.isLogging()); } private void verifyAddresses() { diff --git a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml index 704cb58e0bd..137ddfa4c68 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-full-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-full-config.xml @@ -384,6 +384,7 @@ true true true + true diff --git a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml index 44961398dea..6193b1086cf 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-xinclude-config.xml @@ -265,6 +265,7 @@ true true true + true diff --git a/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config-metrics.xml b/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config-metrics.xml index 98b815ec198..d396cdcaa0e 100644 --- a/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config-metrics.xml +++ b/artemis-server/src/test/resources/ConfigurationTest-xinclude-schema-config-metrics.xml @@ -22,6 +22,7 @@ true true true + true diff --git a/artemis-server/src/test/resources/metrics.xml b/artemis-server/src/test/resources/metrics.xml index c4277e22495..671407fe9f1 100644 --- a/artemis-server/src/test/resources/metrics.xml +++ b/artemis-server/src/test/resources/metrics.xml @@ -27,6 +27,7 @@ true true true + true diff --git a/docs/user-manual/metrics.adoc b/docs/user-manual/metrics.adoc index dcae56ecd54..4930eb8edc8 100644 --- a/docs/user-manual/metrics.adoc +++ b/docs/user-manual/metrics.adoc @@ -118,13 +118,23 @@ Uptime:: Gauges process start time and uptime. + Disabled by default. +Logging:: +Counts the number of logging events per logging category (e.g. `WARN`, `ERROR`, etc.). ++ +Disabled by default. ++ +[WARNING] +==== +This works _exclusively_ with Log4j2 (i.e the default logging implementation shipped with the broker). +If you're embedding the broker and using a different logging implementation (e.g. Log4j 1.x, JUL, Logback, etc.) and you enable these metrics then the broker will fail to start with a `java.lang.NoClassDefFoundError` as it attempts to locate Log4j2 classes that don't exist on the classpath. +==== == Configuration Metrics for all addresses and queues are enabled by default. If you want to disable metrics for a particular address or set of addresses you can do so by setting the `enable-metrics` `address-setting` to `false`. -In `broker.xml` use the `metrics` element to configure which JVM metrics are reported and to configure the plugin itself. +In `broker.xml` use the `metrics` element to configure which general broker and JVM metrics are reported and to configure the plugin itself. Here's a configuration with all optional metrics: [,xml] @@ -137,6 +147,7 @@ Here's a configuration with all optional metrics: true true true + true ---- diff --git a/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/LoggingMetricsTest.java b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/LoggingMetricsTest.java new file mode 100644 index 00000000000..3c8a9f76b0a --- /dev/null +++ b/tests/integration-tests/src/test/java/org/apache/activemq/artemis/tests/integration/plugin/LoggingMetricsTest.java @@ -0,0 +1,99 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF 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 + * + * http://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 org.apache.activemq.artemis.tests.integration.plugin; + +import java.lang.invoke.MethodHandles; + +import io.micrometer.core.instrument.Meter; +import io.micrometer.core.instrument.Tag; +import io.micrometer.core.instrument.Tags; +import org.apache.activemq.artemis.core.config.MetricsConfiguration; +import org.apache.activemq.artemis.core.server.ActiveMQServer; +import org.apache.activemq.artemis.core.server.metrics.plugins.SimpleMetricsPlugin; +import org.apache.activemq.artemis.tests.util.ActiveMQTestBase; +import org.apache.logging.log4j.Level; +import org.apache.logging.log4j.core.config.Configurator; +import org.junit.Before; +import org.junit.Test; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class LoggingMetricsTest extends ActiveMQTestBase { + + @Override + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @Test + public void testLoggingMetrics() throws Exception { + final String idName = "log4j2.events"; + final Tag brokerTag = Tag.of("broker", "localhost"); + final String levelName = "level"; + int start = 0; + String message = ""; + ActiveMQServer server = createServer(false, createDefaultInVMConfig() + .setMetricsConfiguration(new MetricsConfiguration() + .setPlugin(new SimpleMetricsPlugin().init(null)) + .setLogging(true))); + server.start(); + + Configurator.setLevel(MethodHandles.lookup().lookupClass(), Level.TRACE); + final Logger logger = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); + + Meter.Id trace = new Meter.Id(idName, Tags.of(brokerTag, Tag.of(levelName, "trace")), null, null, null); + assertTrue(MetricsPluginTest.getMetrics(server).containsKey(trace)); + start = MetricsPluginTest.getMetrics(server).get(trace).intValue(); + logger.trace(message); + logger.trace(message); + logger.trace(message); + assertEquals(3, MetricsPluginTest.getMetrics(server).get(trace).intValue() - start); + + Meter.Id debug = new Meter.Id(idName, Tags.of(brokerTag, Tag.of(levelName, "debug")), null, null, null); + assertTrue(MetricsPluginTest.getMetrics(server).containsKey(debug)); + start = MetricsPluginTest.getMetrics(server).get(debug).intValue(); + logger.debug(message); + logger.debug(message); + logger.debug(message); + assertEquals(3, MetricsPluginTest.getMetrics(server).get(debug).intValue() - start); + + Meter.Id info = new Meter.Id(idName, Tags.of(brokerTag, Tag.of(levelName, "info")), null, null, null); + assertTrue(MetricsPluginTest.getMetrics(server).containsKey(info)); + start = MetricsPluginTest.getMetrics(server).get(info).intValue(); + logger.info(message); + logger.info(message); + logger.info(message); + assertEquals(3, MetricsPluginTest.getMetrics(server).get(info).intValue() - start); + + Meter.Id warn = new Meter.Id(idName, Tags.of(brokerTag, Tag.of(levelName, "warn")), null, null, null); + assertTrue(MetricsPluginTest.getMetrics(server).containsKey(warn)); + start = MetricsPluginTest.getMetrics(server).get(warn).intValue(); + logger.warn(message); + logger.warn(message); + logger.warn(message); + assertEquals(3, MetricsPluginTest.getMetrics(server).get(warn).intValue() - start); + + Meter.Id error = new Meter.Id(idName, Tags.of(brokerTag, Tag.of(levelName, "error")), null, null, null); + assertTrue(MetricsPluginTest.getMetrics(server).containsKey(error)); + start = MetricsPluginTest.getMetrics(server).get(error).intValue(); + logger.error(message); + logger.error(message); + logger.error(message); + assertEquals(3, MetricsPluginTest.getMetrics(server).get(error).intValue() - start); + } +}