You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@activemq.apache.org by mi...@apache.org on 2020/03/07 21:16:08 UTC
[activemq-artemis] 02/03: ARTEMIS-2476: implemented
MQTTRetainMessageManagerTest
This is an automated email from the ASF dual-hosted git repository.
michaelpearce pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/activemq-artemis.git
commit 2ce8f019119ea65c7991e6010060bda9cf902e04
Author: Assen Sharlandjiev <as...@gmail.com>
AuthorDate: Mon Sep 16 15:02:04 2019 +0300
ARTEMIS-2476: implemented MQTTRetainMessageManagerTest
---
artemis-protocols/artemis-mqtt-protocol/pom.xml | 41 ++++
.../mqtt/MQTTRetainMessageManagerTest.java | 265 +++++++++++++++++++++
.../core/protocol/mqtt/MqttClientService.java | 126 ++++++++++
.../resources/embedded-artemis-server-mqtt.xml | 34 +++
.../src/test/resources/logging.properties | 61 +++++
5 files changed, 527 insertions(+)
diff --git a/artemis-protocols/artemis-mqtt-protocol/pom.xml b/artemis-protocols/artemis-mqtt-protocol/pom.xml
index 188d5dd..24a1fd3 100644
--- a/artemis-protocols/artemis-mqtt-protocol/pom.xml
+++ b/artemis-protocols/artemis-mqtt-protocol/pom.xml
@@ -95,6 +95,47 @@
<groupId>org.osgi</groupId>
<artifactId>osgi.cmpn</artifactId>
</dependency>
+ <dependency>
+ <groupId>org.apache.activemq</groupId>
+ <artifactId>artemis-junit</artifactId>
+ <version>${project.version}</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.eclipse.paho</groupId>
+ <artifactId>org.eclipse.paho.client.mqttv3</artifactId>
+ <version>1.2.0</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>com.github.javafaker</groupId>
+ <artifactId>javafaker</artifactId>
+ <version>0.15</version>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>org.awaitility</groupId>
+ <artifactId>awaitility</artifactId>
+ <version>4.0.1</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
+ <repositories>
+ <repository>
+ <id>bintray</id>
+ <url>https://jcenter.bintray.com</url>
+ <releases>
+ <enabled>true</enabled>
+ </releases>
+ <snapshots>
+ <enabled>false</enabled>
+ </snapshots>
+ </repository>
+ </repositories>
</project>
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManagerTest.java b/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManagerTest.java
new file mode 100644
index 0000000..a2a6f23
--- /dev/null
+++ b/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MQTTRetainMessageManagerTest.java
@@ -0,0 +1,265 @@
+/*
+ * 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.core.protocol.mqtt;
+
+import static java.util.Objects.nonNull;
+import static org.awaitility.Awaitility.await;
+import static org.awaitility.Durations.FIVE_HUNDRED_MILLISECONDS;
+import static org.awaitility.Durations.TEN_SECONDS;
+import static org.junit.Assert.assertArrayEquals;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.fail;
+
+import java.nio.charset.StandardCharsets;
+import java.util.concurrent.atomic.AtomicInteger;
+import java.util.concurrent.atomic.AtomicReference;
+import java.util.stream.IntStream;
+
+import org.apache.activemq.artemis.api.core.Message;
+import org.apache.activemq.artemis.core.config.WildcardConfiguration;
+import org.apache.activemq.artemis.core.server.MessageReference;
+import org.apache.activemq.artemis.core.server.Queue;
+import org.apache.activemq.artemis.junit.EmbeddedJMSResource;
+import org.apache.activemq.artemis.utils.collections.LinkedListIterator;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.jboss.logging.Logger;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.RuleChain;
+
+import com.github.javafaker.ChuckNorris;
+import com.github.javafaker.Faker;
+
+@SuppressWarnings("deprecation")
+public class MQTTRetainMessageManagerTest {
+
+ private Logger log = Logger.getLogger(MQTTRetainMessageManagerTest.class);
+
+ public EmbeddedJMSResource jmsServer = new EmbeddedJMSResource("embedded-artemis-server-mqtt.xml");
+
+ private MqttClientService mqttPublisher;
+
+ private MqttClientService mqttConsumerCount;
+ private MqttClientService mqttConsumerBeforePublish;
+ private MqttClientService mqttConsumerAfterPublish;
+ private MqttClientService mqttConsumerAfterPublish2;
+
+ private final AtomicInteger publishCount = new AtomicInteger(0);
+
+ private final AtomicInteger arrivedCountBeforePublish = new AtomicInteger();
+ private final AtomicInteger arrivedCountAferPublish = new AtomicInteger();
+ private final AtomicInteger arrivedCountAferPublish2 = new AtomicInteger();
+
+ private final AtomicReference<MqttMessage> lastMessagePublished = new AtomicReference<>();
+ private final AtomicReference<MqttMessage> lastMessageArrivedOnConsumerBeforePublish = new AtomicReference<>();
+ private final AtomicReference<MqttMessage> lastMessageArrivedOnConsumerAfterPublish = new AtomicReference<>();
+ private final AtomicReference<MqttMessage> lastMessageArrivedOnConsumerAfterPublish2 = new AtomicReference<>();
+
+ private final String topic = "fact";
+
+ private final ChuckNorris chuckNorris = (new Faker()).chuckNorris();
+
+ private final int numberOfMessages = 1000;
+ private final int numberOfTests = 10;
+
+ @Rule
+ public RuleChain rulechain = RuleChain.outerRule(jmsServer);
+
+ @Before
+ public void beforeEach() throws MqttException {
+ publishCount.set(0);
+ mqttPublisher = new MqttClientService("publisher", null);
+ mqttPublisher.init();
+
+ final MqttMessage clearRetainedMessage = new MqttMessage(new byte[] {});
+ clearRetainedMessage.setRetained(true);
+ clearRetainedMessage.setQos(1);
+ mqttPublisher.publish(topic, clearRetainedMessage);
+
+ mqttConsumerCount = new MqttClientService("consumer-count", null);
+ mqttConsumerCount.init();
+ mqttConsumerCount.setMessageConsumer(message -> publishCount.incrementAndGet());
+
+ arrivedCountBeforePublish.set(0);
+ mqttConsumerBeforePublish = new MqttClientService("consumer-before",
+ message -> {
+ final String payload = new String(message.getPayload());
+ lastMessageArrivedOnConsumerBeforePublish.set(message);
+ arrivedCountBeforePublish.incrementAndGet();
+ log.debugf("[MQTT][before ][retained: %s][duplicate: %s][qos: %s] %s",
+ message.isRetained(), message.isDuplicate(), message.getQos(), payload);
+ });
+ mqttConsumerBeforePublish.init();
+
+ arrivedCountAferPublish.set(0);
+ arrivedCountAferPublish2.set(0);
+ mqttConsumerAfterPublish = new MqttClientService("consumer-after",
+ message -> {
+ final String payload = new String(message.getPayload());
+ lastMessageArrivedOnConsumerAfterPublish.set(message);
+ arrivedCountAferPublish.incrementAndGet();
+ log.infof("[MQTT][after ][retained: %s][duplicate: %s][qos: %s] %s",
+ message.isRetained(), message.isDuplicate(), message.getQos(), payload);
+ });
+ mqttConsumerAfterPublish2 = new MqttClientService("consumer-after2",
+ message -> {
+ final String payload = new String(message.getPayload());
+ lastMessageArrivedOnConsumerAfterPublish2.set(message);
+ arrivedCountAferPublish2.incrementAndGet();
+ log.infof("[MQTT][after2 ][retained: %s][duplicate: %s][qos: %s] %s",
+ message.isRetained(), message.isDuplicate(), message.getQos(), payload);
+ });
+ mqttConsumerAfterPublish.init();
+ mqttConsumerAfterPublish2.init();
+ }
+
+ @After
+ public void afterEach() throws MqttException {
+ mqttPublisher.destroy();
+
+ mqttConsumerCount.unsubsribe(topic);
+ mqttConsumerCount.destroy();
+
+ mqttConsumerBeforePublish.unsubsribe(topic);
+ mqttConsumerBeforePublish.destroy();
+
+ mqttConsumerAfterPublish.unsubsribe(topic);
+ mqttConsumerAfterPublish.destroy();
+
+ mqttConsumerAfterPublish2.unsubsribe(topic);
+ mqttConsumerAfterPublish2.destroy();
+ }
+
+ @Test
+ public void testAtMostOnce() throws MqttException {
+ IntStream.of(numberOfTests).forEach(i -> actAndAssert(i, 0));
+ }
+
+ @Test
+ public void testAtLeastOnce() throws MqttException {
+ IntStream.of(numberOfTests).forEach(i -> actAndAssert(i, 1));
+ }
+
+ @Test
+ public void testExactlyOnce() throws MqttException {
+ IntStream.of(numberOfTests).forEach(i -> actAndAssert(i, 2));
+ }
+
+ private void actAndAssert(int i, int qos) {
+ try {
+ // Act
+ mqttConsumerBeforePublish.subscribe(topic, qos);
+ publish(qos);
+ logAftePublish(i, qos);
+ logRetainedMessagesQueue();
+ mqttConsumerAfterPublish.subscribe(topic, qos);
+ mqttConsumerAfterPublish2.subscribe(topic, qos);
+ awaitUntilLastMessageArrivedOnConsumerAfterPublish();
+ awaitUntilLastMessageArrivedOnConsumerAfterPublish2();
+
+ // Assert
+ assertEquals(1, arrivedCountAferPublish.get());
+ assertLastMessageOnConsumerBeforePublishArrivedEqualsLastMessagePublished();
+ assertLastMessageOnConsumerAfterPublishArrivedEqualsLastMessagePublished();
+ } catch (MqttException e) {
+ fail(e.getMessage());
+ }
+ }
+
+ protected void publish(final int qos) throws MqttException {
+ mqttConsumerCount.subscribe(topic, qos);
+ IntStream.range(0, numberOfMessages).forEach(i -> {
+ final String fact = String.format("[%s] %s", i, chuckNorris.fact());
+ final MqttMessage message = message(fact, qos, true);
+ mqttPublisher.publish(topic, message);
+ lastMessagePublished.set(message);
+ });
+ awaitUntilPiblishCount();
+ }
+
+ protected MqttMessage message(final String payload, final int qos, final boolean retained) {
+ final MqttMessage message = new MqttMessage();
+ message.setQos(qos);
+ message.setRetained(retained);
+ message.setPayload(payload.getBytes());
+ return message;
+ }
+
+ private void awaitUntilPiblishCount() {
+ await()
+ .with()
+ .pollDelay(FIVE_HUNDRED_MILLISECONDS)
+ .atMost(TEN_SECONDS)
+ .until(() -> publishCount.get() >= numberOfMessages);
+ }
+
+ private void awaitUntilLastMessageArrivedOnConsumerAfterPublish() {
+ await()
+ .pollDelay(FIVE_HUNDRED_MILLISECONDS)
+ .atMost(TEN_SECONDS)
+ .until(() -> nonNull(lastMessageArrivedOnConsumerAfterPublish.get()));
+ }
+
+ private void awaitUntilLastMessageArrivedOnConsumerAfterPublish2() {
+ await()
+ .pollDelay(FIVE_HUNDRED_MILLISECONDS)
+ .atMost(TEN_SECONDS)
+ .until(() -> nonNull(lastMessageArrivedOnConsumerAfterPublish2.get()));
+ }
+
+ private void assertLastMessageOnConsumerBeforePublishArrivedEqualsLastMessagePublished() {
+ assertArrayEquals(String.format(
+ "\nMessage arrived on consumer subscribed before the publish is different from the last published message!\nPublished: %s\nArrived : %s\n",
+ new String(lastMessagePublished.get().getPayload()), new String(lastMessageArrivedOnConsumerAfterPublish.get().getPayload())),
+ lastMessagePublished.get().getPayload(), lastMessageArrivedOnConsumerBeforePublish.get().getPayload());
+ }
+
+ private void assertLastMessageOnConsumerAfterPublishArrivedEqualsLastMessagePublished() {
+ assertArrayEquals(String.format(
+ "\nMessage arrived on consumer subscribed after the publish is different from the last published message!\nPublished: %s\nArrived : %s\n",
+ new String(lastMessagePublished.get().getPayload()), new String(lastMessageArrivedOnConsumerAfterPublish.get().getPayload())),
+ lastMessagePublished.get().getPayload(), lastMessageArrivedOnConsumerAfterPublish.get().getPayload());
+ assertArrayEquals(String.format(
+ "\nMessage arrived on consumer subscribed after the publish (2) is different from the last published message!\nPublished: %s\nArrived : %s\n",
+ new String(lastMessagePublished.get().getPayload()), new String(lastMessageArrivedOnConsumerAfterPublish.get().getPayload())),
+ lastMessagePublished.get().getPayload(), lastMessageArrivedOnConsumerAfterPublish2.get().getPayload());
+ }
+
+ private void logAftePublish(int i, int qos) {
+ log.infof("--- QoS: %s --- %s/%s---", qos, i, numberOfTests);
+ log.infof("[MQTT][publish][retained: %s][duplicate: %s][qos: %s] %s",
+ lastMessagePublished.get().isRetained(), lastMessagePublished.get().isDuplicate(), lastMessagePublished.get().getQos(), lastMessagePublished.get());
+ log.infof("[MQTT][before ][retained: %s][duplicate: %s][qos: %s] %s",
+ lastMessageArrivedOnConsumerBeforePublish.get().isRetained(),
+ lastMessageArrivedOnConsumerBeforePublish.get().isDuplicate(),
+ lastMessageArrivedOnConsumerBeforePublish.get().getQos(),
+ new String(lastMessageArrivedOnConsumerBeforePublish.get().getPayload()));
+ }
+
+ private void logRetainedMessagesQueue() {
+ final WildcardConfiguration wildcardConfiguration = new WildcardConfiguration();
+ final String retainAddress = MQTTUtil.convertMQTTAddressFilterToCoreRetain(topic, wildcardConfiguration);
+ final Queue queue = jmsServer.getDestinationQueue(retainAddress);
+ final LinkedListIterator<MessageReference> browserIterator = queue.browserIterator();
+ browserIterator.forEachRemaining(messageReference -> {
+ final Message message = messageReference.getMessage();
+ final String body = message.getBuffer().toString(StandardCharsets.UTF_8);
+ log.infof("[MQTT][%s][%s][%s]", retainAddress, message, body);
+ });
+ }
+}
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MqttClientService.java b/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MqttClientService.java
new file mode 100644
index 0000000..cd80056
--- /dev/null
+++ b/artemis-protocols/artemis-mqtt-protocol/src/test/java/org/apache/activemq/artemis/core/protocol/mqtt/MqttClientService.java
@@ -0,0 +1,126 @@
+/*
+ * 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.core.protocol.mqtt;
+
+import static java.util.Objects.nonNull;
+import static org.eclipse.paho.client.mqttv3.MqttConnectOptions.MQTT_VERSION_3_1_1;
+
+import java.util.concurrent.ScheduledExecutorService;
+import java.util.concurrent.ScheduledThreadPoolExecutor;
+import java.util.concurrent.ThreadFactory;
+import java.util.concurrent.ThreadPoolExecutor;
+import java.util.function.Consumer;
+
+import javax.annotation.PostConstruct;
+import javax.annotation.PreDestroy;
+
+import org.eclipse.paho.client.mqttv3.IMqttDeliveryToken;
+import org.eclipse.paho.client.mqttv3.MqttCallback;
+import org.eclipse.paho.client.mqttv3.MqttClient;
+import org.eclipse.paho.client.mqttv3.MqttConnectOptions;
+import org.eclipse.paho.client.mqttv3.MqttException;
+import org.eclipse.paho.client.mqttv3.MqttMessage;
+import org.eclipse.paho.client.mqttv3.persist.MemoryPersistence;
+import org.jboss.logging.Logger;
+
+import io.netty.util.concurrent.DefaultThreadFactory;
+
+public class MqttClientService implements MqttCallback {
+
+ private final String clientId;
+
+ private Consumer<MqttMessage> messageConsumer;
+
+ private MqttClient mqttClient;
+
+ private MemoryPersistence persistence = new MemoryPersistence();
+ private ScheduledExecutorService executorService;
+ private int corePoolSize = 5;
+
+ private Logger log = Logger.getLogger(MqttClientService.class);
+
+ public MqttClientService() {
+ this("producer", null);
+ }
+
+ public MqttClientService(final String clientId, Consumer<MqttMessage> messageConsumer) {
+ this.clientId = clientId;
+ this.messageConsumer = messageConsumer;
+ }
+
+ @PostConstruct
+ public void init() throws MqttException {
+ final String serverURI = "tcp://localhost:1883";
+ final MqttConnectOptions options = new MqttConnectOptions();
+ options.setAutomaticReconnect(true);
+ options.setCleanSession(false);
+ options.setMaxInflight(10);
+ options.setServerURIs(new String[] {serverURI});
+ options.setMqttVersion(MQTT_VERSION_3_1_1);
+
+ final ThreadFactory threadFactory = new DefaultThreadFactory("mqtt-client-exec");
+ executorService = new ScheduledThreadPoolExecutor(corePoolSize, threadFactory, new ThreadPoolExecutor.CallerRunsPolicy());
+ mqttClient = new MqttClient(serverURI, clientId, persistence, executorService);
+ mqttClient.setTimeToWait(-1);
+ mqttClient.connect(options);
+ mqttClient.setCallback(this);
+ log.debugf("[MQTT][Connected][client: %s]", clientId);
+ }
+
+ @PreDestroy
+ public void destroy() throws MqttException {
+ mqttClient.disconnect();
+ executorService.shutdownNow();
+ log.debugf("[MQTT][Disconnected][client: %s]", clientId);
+ }
+
+ @Override
+ public void connectionLost(Throwable cause) {
+ log.errorf("[MQTT][connectionLost][%s]", cause.getMessage());
+ }
+
+ @Override
+ public void messageArrived(String topic, MqttMessage message) {
+ log.debugf("[MQTT][messageArrived][client: %s][topic: %s][message: %s]", clientId, topic, message);
+ if (nonNull(messageConsumer)) {
+ messageConsumer.accept(message);
+ }
+ }
+
+ @Override
+ public void deliveryComplete(IMqttDeliveryToken token) {
+ log.tracef("[MQTT][deliveryComplete][token: %s]", token);
+ }
+
+ public void publish(final String topic, final MqttMessage message) {
+ try {
+ mqttClient.publish(topic, message);
+ } catch (final MqttException e) {
+ log.error(e.getMessage(), e);
+ }
+ }
+
+ public void subscribe(final String topicFilter, int qos) throws MqttException {
+ mqttClient.subscribe(topicFilter, qos);
+ }
+
+ public void unsubsribe(final String topicFilter) throws MqttException {
+ mqttClient.unsubscribe(topicFilter);
+ }
+
+ public void setMessageConsumer(Consumer<MqttMessage> messageConsumer) {
+ this.messageConsumer = messageConsumer;
+ }
+}
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/test/resources/embedded-artemis-server-mqtt.xml b/artemis-protocols/artemis-mqtt-protocol/src/test/resources/embedded-artemis-server-mqtt.xml
new file mode 100644
index 0000000..b0b65e0
--- /dev/null
+++ b/artemis-protocols/artemis-mqtt-protocol/src/test/resources/embedded-artemis-server-mqtt.xml
@@ -0,0 +1,34 @@
+<!--
+ 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.
+-->
+<configuration xmlns="urn:activemq"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="
+ urn:activemq /schema/artemis-server.xsd
+ urn:activemq:core /schema/artemis-configuration.xsd">
+ <core xmlns="urn:activemq:core">
+ <persistence-enabled>false</persistence-enabled>
+ <security-enabled>false</security-enabled>
+
+ <!-- Acceptors -->
+ <acceptors>
+ <!-- In VM acceptor -->
+ <acceptor name="in-vm">vm://0</acceptor>
+ <acceptor name="mqtt">tcp://127.0.0.1:1883?protocols=MQTT&useEpoll=false&useKQueue=false</acceptor>
+ </acceptors>
+
+ </core>
+</configuration>
diff --git a/artemis-protocols/artemis-mqtt-protocol/src/test/resources/logging.properties b/artemis-protocols/artemis-mqtt-protocol/src/test/resources/logging.properties
new file mode 100644
index 0000000..29a4b47
--- /dev/null
+++ b/artemis-protocols/artemis-mqtt-protocol/src/test/resources/logging.properties
@@ -0,0 +1,61 @@
+#
+# 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.
+#
+
+# Additional logger names to configure (root logger is always configured)
+# Root logger option
+loggers=org.jboss.logging,org.apache.activemq.artemis.core.server,org.apache.activemq.artemis.utils,org.apache.activemq.artemis.journal,org.apache.activemq.artemis.jms,org.apache.activemq.artemis.ra,org.apache.activemq.artemis.tests.unit,org.apache.activemq.artemis.tests.integration,org.apache.activemq.artemis.jms.tests
+
+# Root logger level
+logger.level=INFO
+# ActiveMQ Artemis logger levels
+logger.org.apache.activemq.artemis.core.server.level=INFO
+logger.org.apache.activemq.artemis.journal.level=INFO
+logger.org.apache.activemq.artemis.utils.level=INFO
+logger.org.apache.activemq.artemis.jms.level=INFO
+logger.org.apache.activemq.artemis.ra.level=INFO
+logger.org.apache.activemq.artemis.tests.unit.level=INFO
+logger.org.apache.activemq.artemis.tests.integration.level=DEBUG
+logger.org.apache.activemq.artemis.jms.tests.level=INFO
+
+# Root logger handlers
+logger.handlers=CONSOLE,TEST
+#logger.handlers=CONSOLE,FILE
+
+# Console handler configuration
+handler.CONSOLE=org.jboss.logmanager.handlers.ConsoleHandler
+handler.CONSOLE.properties=autoFlush
+handler.CONSOLE.level=FINE
+handler.CONSOLE.autoFlush=true
+handler.CONSOLE.formatter=PATTERN
+
+# File handler configuration
+handler.FILE=org.jboss.logmanager.handlers.FileHandler
+handler.FILE.level=FINE
+handler.FILE.properties=autoFlush,fileName
+handler.FILE.autoFlush=true
+handler.FILE.fileName=target/activemq.log
+handler.FILE.formatter=PATTERN
+
+# Console handler configuration
+handler.TEST=org.apache.activemq.artemis.logs.AssertionLoggerHandler
+handler.TEST.level=TRACE
+handler.TEST.formatter=PATTERN
+
+# Formatter pattern configuration
+formatter.PATTERN=org.jboss.logmanager.formatters.PatternFormatter
+formatter.PATTERN.properties=pattern
+formatter.PATTERN.pattern=[%t] %d{HH:mm:ss,SSS} %-5p [%c] %s%E%n