diff --git a/.github/workflows/plugins-jdk17-test.1.yaml b/.github/workflows/plugins-jdk17-test.1.yaml index 21449a7861..d469d4c2ef 100644 --- a/.github/workflows/plugins-jdk17-test.1.yaml +++ b/.github/workflows/plugins-jdk17-test.1.yaml @@ -59,6 +59,7 @@ jobs: - resteasy-6.x-scenario - gateway-4.x-scenario - httpexchange-scenario + - activemq-artemis-2.x-scenario steps: - uses: actions/checkout@v2 with: diff --git a/CHANGES.md b/CHANGES.md index 9bdff5f5a7..14032134e8 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -14,6 +14,7 @@ Release Notes. * Support tracing for async producing, batch sync consuming, and batch async consuming in rocketMQ-client-java-5.x-plugin. * Convert the Redisson span into an async span. * Rename system env name from `sw_plugin_kafka_producer_config` to `SW_PLUGIN_KAFKA_PRODUCER_CONFIG`. +* Support for ActiveMQ-Artemis messaging tracing. #### Documentation diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml new file mode 100644 index 0000000000..cc6a9f1ae2 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/pom.xml @@ -0,0 +1,48 @@ + + + + + + apm-sdk-plugin + org.apache.skywalking + 9.2.0-SNAPSHOT + + 4.0.0 + + apm-activemq-artemis-jakarta-client-2.x-plugin + activemq-artemis-jakarta-client-2.x-plugin + jar + + + 1.8 + UTF-8 + UTF-8 + 2.31.2 + + + + org.apache.activemq + artemis-jakarta-client + ${artemis-jakarta-client.version} + provided + + + + + diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerConstructorInterceptor.java new file mode 100644 index 0000000000..f8be4dad40 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerConstructorInterceptor.java @@ -0,0 +1,49 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client; + +import java.util.Map; +import org.apache.activemq.artemis.jms.client.ActiveMQConnection; +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.EnhanceInfo; + +/** + * {@link MessageConsumerConstructorInterceptor} get enhance data from the constructor of {@link org.apache.activemq.artemis.jms.client.ActiveMQMessageConsumer} + */ +public class MessageConsumerConstructorInterceptor implements InstanceConstructorInterceptor { + private static final String DEFAULT_HOST = "localhost"; + private static final String DEFAULT_PORT = "61616"; + private static final String HOST_KEY = "host"; + private static final String PORT_KEY = "port"; + + @Override + public void onConstruct(final EnhancedInstance objInst, final Object[] allArguments) throws Throwable { + ActiveMQConnection connection = (ActiveMQConnection) allArguments[1]; + ActiveMQDestination destination = (ActiveMQDestination) allArguments[5]; + Map paramMap = connection.getSessionFactory().getConnectorConfiguration().getParams(); + EnhanceInfo enhanceInfo = new EnhanceInfo(); + enhanceInfo.setBrokerUrl(paramMap.getOrDefault(HOST_KEY, DEFAULT_HOST) + ":" + paramMap.getOrDefault(PORT_KEY + , DEFAULT_PORT)); + enhanceInfo.setName(destination.getName()); + enhanceInfo.setAddress(destination.getAddress()); + enhanceInfo.setType(destination.getType()); + objInst.setSkyWalkingDynamicField(enhanceInfo); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerInterceptor.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerInterceptor.java new file mode 100644 index 0000000000..82f371221e --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageConsumerInterceptor.java @@ -0,0 +1,117 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client; + +import java.lang.reflect.Method; +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; +import org.apache.activemq.artemis.jms.client.ActiveMQMessage; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.EnhanceInfo; + +/** + * {@link MessageConsumerInterceptor} create entry span when the method {@link org.apache.activemq.artemis.jms.client.ActiveMQMessageConsumer#getMessage(long, boolean)} execute + */ +public class MessageConsumerInterceptor implements InstanceMethodsAroundInterceptor { + private static final String OPERATION_NAME_PREFIX = "ActiveMQ/"; + private static final String CONSUMER_OPERATION_NAME_SUFFIX = "/Consumer"; + public static final StringTag MQ_MESSAGE_ID = new StringTag("mq.message.id"); + private static final String QUEUE = "Queue"; + private static final String TOPIC = "Topic"; + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] classes, + final MethodInterceptResult methodInterceptResult) throws Throwable { + } + + @Override + public Object afterMethod(final EnhancedInstance objInst, + final Method method, + final Object[] objects, + final Class[] classes, + final Object ret) throws Throwable { + ActiveMQMessage message = (ActiveMQMessage) ret; + if (message == null) { + return ret; + } + ContextCarrier contextCarrier = getContextCarrierFromMessage(message); + EnhanceInfo enhanceInfo = (EnhanceInfo) objInst.getSkyWalkingDynamicField(); + boolean queue = isQueue(enhanceInfo.getType()); + AbstractSpan activeSpan = ContextManager.createEntrySpan( + buildOperationName(queue, enhanceInfo.getName()), + contextCarrier + ); + Tags.MQ_BROKER.set(activeSpan, enhanceInfo.getBrokerUrl()); + if (queue) { + Tags.MQ_QUEUE.set(activeSpan, enhanceInfo.getName()); + } else { + Tags.MQ_TOPIC.set(activeSpan, enhanceInfo.getName()); + } + activeSpan.tag(MQ_MESSAGE_ID, message.getJMSMessageID()); + activeSpan.setPeer(enhanceInfo.getBrokerUrl()); + activeSpan.setComponent(ComponentsDefine.ACTIVEMQ_CONSUMER); + SpanLayer.asMQ(activeSpan); + ContextManager.stopSpan(activeSpan); + return ret; + } + + @Override + public void handleMethodException(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] objects, + final Class[] classes, + final Throwable t) { + ContextManager.activeSpan().log(t); + } + + private ContextCarrier getContextCarrierFromMessage(ActiveMQMessage message) { + ContextCarrier contextCarrier = new ContextCarrier(); + + CarrierItem next = contextCarrier.items(); + while (next.hasNext()) { + next = next.next(); + next.setHeadValue(message.getCoreMessage().getStringProperty(next.getHeadKey().replace("-", "_"))); + } + + return contextCarrier; + } + + private boolean isQueue(ActiveMQDestination.TYPE type) { + return ActiveMQDestination.TYPE.QUEUE.equals(type) || ActiveMQDestination.TYPE.TEMP_QUEUE.equals(type); + } + + private String buildOperationName(boolean isQueue, String name) { + if (isQueue) { + return OPERATION_NAME_PREFIX + QUEUE + "/" + name + CONSUMER_OPERATION_NAME_SUFFIX; + } else { + return OPERATION_NAME_PREFIX + TOPIC + "/" + name + CONSUMER_OPERATION_NAME_SUFFIX; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerConstructorInterceptor.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerConstructorInterceptor.java new file mode 100644 index 0000000000..4a8f548fd4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerConstructorInterceptor.java @@ -0,0 +1,49 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client; + +import java.util.Map; +import org.apache.activemq.artemis.jms.client.ActiveMQConnection; +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceConstructorInterceptor; +import org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.EnhanceInfo; + +/** + * {@link MessageProducerConstructorInterceptor} get enhance data from the constructor of {@link org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer} + */ +public class MessageProducerConstructorInterceptor implements InstanceConstructorInterceptor { + private static final String DEFAULT_HOST = "localhost"; + private static final String DEFAULT_PORT = "61616"; + private static final String HOST_KEY = "host"; + private static final String PORT_KEY = "port"; + + @Override + public void onConstruct(final EnhancedInstance objInst, final Object[] allArguments) throws Throwable { + ActiveMQConnection connection = (ActiveMQConnection) allArguments[0]; + Map paramMap = connection.getSessionFactory().getConnectorConfiguration().getParams(); + ActiveMQDestination destination = (ActiveMQDestination) allArguments[2]; + EnhanceInfo enhanceInfo = new EnhanceInfo(); + enhanceInfo.setBrokerUrl(paramMap.getOrDefault(HOST_KEY, DEFAULT_HOST) + ":" + paramMap.getOrDefault(PORT_KEY + , DEFAULT_PORT)); + enhanceInfo.setName(destination.getName()); + enhanceInfo.setAddress(destination.getAddress()); + enhanceInfo.setType(destination.getType()); + objInst.setSkyWalkingDynamicField(enhanceInfo); + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerInterceptor.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerInterceptor.java new file mode 100644 index 0000000000..08687d6e92 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/MessageProducerInterceptor.java @@ -0,0 +1,111 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client; + +import jakarta.jms.Message; +import java.lang.reflect.Method; +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; +import org.apache.skywalking.apm.agent.core.context.CarrierItem; +import org.apache.skywalking.apm.agent.core.context.ContextCarrier; +import org.apache.skywalking.apm.agent.core.context.ContextManager; +import org.apache.skywalking.apm.agent.core.context.tag.StringTag; +import org.apache.skywalking.apm.agent.core.context.tag.Tags; +import org.apache.skywalking.apm.agent.core.context.trace.AbstractSpan; +import org.apache.skywalking.apm.agent.core.context.trace.SpanLayer; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.EnhancedInstance; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.InstanceMethodsAroundInterceptor; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.MethodInterceptResult; +import org.apache.skywalking.apm.network.trace.component.ComponentsDefine; +import org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.EnhanceInfo; + +/** + * {@link MessageProducerInterceptor} create exit span when the method {@link org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer#doSendx} + * execute + */ +public class MessageProducerInterceptor implements InstanceMethodsAroundInterceptor { + private static final String OPERATION_NAME_PREFIX = "ActiveMQ/"; + private static final String PRODUCER_OPERATION_NAME_SUFFIX = "/Producer"; + private static final StringTag MQ_MESSAGE_ID = new StringTag("mq.message.id"); + private static final String QUEUE = "Queue"; + private static final String TOPIC = "Topic"; + + @Override + public void beforeMethod(final EnhancedInstance objInst, + final Method method, + final Object[] allArguments, + final Class[] classes, + final MethodInterceptResult methodInterceptResult) throws Throwable { + ContextCarrier contextCarrier = new ContextCarrier(); + Message message = (Message) allArguments[1]; + EnhanceInfo enhanceInfo = (EnhanceInfo) objInst.getSkyWalkingDynamicField(); + boolean queue = isQueue(enhanceInfo.getType()); + AbstractSpan activeSpan = ContextManager.createExitSpan( + buildOperationName(queue, enhanceInfo.getName()), + contextCarrier, enhanceInfo.getBrokerUrl() + ); + contextCarrier.extensionInjector().injectSendingTimestamp(); + Tags.MQ_BROKER.set(activeSpan, enhanceInfo.getBrokerUrl()); + if (queue) { + Tags.MQ_QUEUE.set(activeSpan, enhanceInfo.getName()); + } else { + Tags.MQ_TOPIC.set(activeSpan, enhanceInfo.getName()); + } + SpanLayer.asMQ(activeSpan); + activeSpan.setComponent(ComponentsDefine.ACTIVEMQ_PRODUCER); + CarrierItem next = contextCarrier.items(); + + while (next.hasNext()) { + next = next.next(); + message.setStringProperty(next.getHeadKey().replace("-", "_"), next.getHeadValue()); + } + } + + @Override + public Object afterMethod(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] allArguments, + final Class[] classes, + final Object ret) throws Throwable { + AbstractSpan activeSpan = ContextManager.activeSpan(); + Message message = (Message) allArguments[1]; + activeSpan.tag(MQ_MESSAGE_ID, message.getJMSMessageID()); + ContextManager.stopSpan(); + return ret; + } + + @Override + public void handleMethodException(final EnhancedInstance enhancedInstance, + final Method method, + final Object[] objects, + final Class[] classes, + final Throwable t) { + ContextManager.activeSpan().log(t); + } + + private boolean isQueue(ActiveMQDestination.TYPE type) { + return ActiveMQDestination.TYPE.QUEUE.equals(type) || ActiveMQDestination.TYPE.TEMP_QUEUE.equals(type); + } + + private String buildOperationName(boolean isQueue, String name) { + if (isQueue) { + return OPERATION_NAME_PREFIX + QUEUE + "/" + name + PRODUCER_OPERATION_NAME_SUFFIX; + } else { + return OPERATION_NAME_PREFIX + TOPIC + "/" + name + PRODUCER_OPERATION_NAME_SUFFIX; + } + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/EnhanceInfo.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/EnhanceInfo.java new file mode 100644 index 0000000000..81ccc14576 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/EnhanceInfo.java @@ -0,0 +1,89 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client.define; + +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; + +/** + * {@link EnhanceInfo} saves the brokerUrl/name/address/TYPE properties. + */ +public class EnhanceInfo { + private String brokerUrl; + private String name; + private String address; + private ActiveMQDestination.TYPE type; + + public EnhanceInfo() { + } + + /** + * get the brokerUrl of ActiveMQ + */ + public String getBrokerUrl() { + return brokerUrl; + } + + /** + * set the brokerUrl of ActiveMQ + */ + public void setBrokerUrl(final String brokerUrl) { + this.brokerUrl = brokerUrl; + } + + /** + * get the type of destination(Queue/Topic) + */ + public ActiveMQDestination.TYPE getType() { + return type; + } + + /** + * set the type of destination(Queue/Topic) + */ + public void setType(final ActiveMQDestination.TYPE type) { + this.type = type; + } + + /** + * get the name of destination + */ + public String getName() { + return name; + } + + /** + * set the name of destination + */ + public void setName(final String name) { + this.name = name; + } + + /** + * get the address of destination + */ + public String getAddress() { + return address; + } + + /** + * set the address of destination + */ + public void setAddress(final String address) { + this.address = address; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageConsumerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageConsumerInstrumentation.java new file mode 100644 index 0000000000..e6e2c5d918 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageConsumerInstrumentation.java @@ -0,0 +1,80 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class MessageConsumerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "org.apache.activemq.artemis.jms.client.ActiveMQMessageConsumer"; + private static final String ENHANCE_METHOD = "getMessage"; + private static final String CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.MessageConsumerConstructorInterceptor"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.MessageConsumerInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[] { + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(8); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[] { + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD).and(takesArguments(2)); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageProducerInstrumentation.java b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageProducerInstrumentation.java new file mode 100644 index 0000000000..b0fa3766b4 --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/java/org/apache/skywalking/apm/plugin/activemq/artemis/jakarta/client/define/MessageProducerInstrumentation.java @@ -0,0 +1,80 @@ +/* + * 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.skywalking.apm.plugin.activemq.artemis.jakarta.client.define; + +import net.bytebuddy.description.method.MethodDescription; +import net.bytebuddy.matcher.ElementMatcher; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.ConstructorInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.InstanceMethodsInterceptPoint; +import org.apache.skywalking.apm.agent.core.plugin.interceptor.enhance.ClassInstanceMethodsEnhancePluginDefine; +import org.apache.skywalking.apm.agent.core.plugin.match.ClassMatch; + +import static net.bytebuddy.matcher.ElementMatchers.named; +import static net.bytebuddy.matcher.ElementMatchers.takesArguments; +import static org.apache.skywalking.apm.agent.core.plugin.match.NameMatch.byName; + +public class MessageProducerInstrumentation extends ClassInstanceMethodsEnhancePluginDefine { + private static final String ENHANCE_CLASS = "org.apache.activemq.artemis.jms.client.ActiveMQMessageProducer"; + private static final String ENHANCE_METHOD = "doSendx"; + private static final String CONSTRUCTOR_INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.MessageProducerConstructorInterceptor"; + private static final String INTERCEPTOR_CLASS = "org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.MessageProducerInterceptor"; + + @Override + protected ClassMatch enhanceClass() { + return byName(ENHANCE_CLASS); + } + + @Override + public ConstructorInterceptPoint[] getConstructorsInterceptPoints() { + return new ConstructorInterceptPoint[]{ + new ConstructorInterceptPoint() { + @Override + public ElementMatcher getConstructorMatcher() { + return takesArguments(5); + } + + @Override + public String getConstructorInterceptor() { + return CONSTRUCTOR_INTERCEPTOR_CLASS; + } + } + }; + } + + @Override + public InstanceMethodsInterceptPoint[] getInstanceMethodsInterceptPoints() { + return new InstanceMethodsInterceptPoint[]{ + new InstanceMethodsInterceptPoint() { + @Override + public ElementMatcher getMethodsMatcher() { + return named(ENHANCE_METHOD); + } + + @Override + public String getMethodsInterceptor() { + return INTERCEPTOR_CLASS; + } + + @Override + public boolean isOverrideArgs() { + return false; + } + } + }; + } +} diff --git a/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/resources/skywalking-plugin.def b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/resources/skywalking-plugin.def new file mode 100644 index 0000000000..55ef5fd11b --- /dev/null +++ b/apm-sniffer/apm-sdk-plugin/activemq-artemis-jakarta-client-2.x-plugin/src/main/resources/skywalking-plugin.def @@ -0,0 +1,18 @@ +# 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. + +activemq-artemis-jakarta-client-2.x=org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.MessageProducerInstrumentation +activemq-artemis-jakarta-client-2.x=org.apache.skywalking.apm.plugin.activemq.artemis.jakarta.client.define.MessageConsumerInstrumentation \ No newline at end of file diff --git a/apm-sniffer/apm-sdk-plugin/pom.xml b/apm-sniffer/apm-sdk-plugin/pom.xml index 6300be177a..bfb4f47444 100644 --- a/apm-sniffer/apm-sdk-plugin/pom.xml +++ b/apm-sniffer/apm-sdk-plugin/pom.xml @@ -136,6 +136,7 @@ websphere-liberty-23.x-plugin aerospike-plugin rocketMQ-client-java-5.x-plugin + activemq-artemis-jakarta-client-2.x-plugin pom diff --git a/docs/en/setup/service-agent/java-agent/Plugin-list.md b/docs/en/setup/service-agent/java-agent/Plugin-list.md index 3c0f2fed45..16136fce70 100644 --- a/docs/en/setup/service-agent/java-agent/Plugin-list.md +++ b/docs/en/setup/service-agent/java-agent/Plugin-list.md @@ -175,3 +175,4 @@ - spring-cloud-gateway-4.x - spring-webflux-6.x - spring-webflux-6.x-webclient +- activemq-artemis-jakarta-client-2.x diff --git a/docs/en/setup/service-agent/java-agent/Supported-list.md b/docs/en/setup/service-agent/java-agent/Supported-list.md index 35ee22b092..9e69ad72b4 100644 --- a/docs/en/setup/service-agent/java-agent/Supported-list.md +++ b/docs/en/setup/service-agent/java-agent/Supported-list.md @@ -81,6 +81,7 @@ metrics based on the tracing data. * [RabbitMQ](https://www.rabbitmq.com/) 3.x-> 5.x * [Pulsar](http://pulsar.apache.org) 2.2.x -> 2.9.x * [NATS](https://github.com/nats-io/nats.java) 2.14.x -> 2.15.x + * [ActiveMQ-Artemis](https://github.com/apache/activemq) 2.30.0 -> 2.31.2 * Aliyun ONS 1.x (Optional¹) * NoSQL * [aerospike](https://github.com/aerospike/aerospike-client-java) 3.x -> 6.x diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/bin/startup.sh b/test/plugin/scenarios/activemq-artemis-2.x-scenario/bin/startup.sh new file mode 100644 index 0000000000..6282faed60 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/bin/startup.sh @@ -0,0 +1,21 @@ +#!/bin/bash +# +# 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. + +home="$(cd "$(dirname $0)"; pwd)" + +java -Dspring.artemis.broker-url=${BROKERURL} -Dspring.artemis.user=${USER} -Dspring.artemis.password=${PASSWORD} -jar ${agent_opts} ${home}/../libs/activemq-artemis-2.x-scenario.jar & \ No newline at end of file diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/config/expectedData.yaml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/config/expectedData.yaml new file mode 100644 index 0000000000..bf12411067 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/config/expectedData.yaml @@ -0,0 +1,192 @@ +# 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. +segmentItems: + - serviceName: activemq-artemis-2.x-scenario + segmentSize: ge 6 + segments: + - segmentId: not null + spans: + - operationName: ActiveMQ/Queue/QueueDemo/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 46 + isError: false + spanType: Entry + peer: not blank + skipAnalysis: false + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + refs: + - {parentEndpoint: 'GET:/activemq-artemis-scenario/testcase/activemq-artemis-scenario', + networkAddress: not blank, refType: CrossProcess, parentSpanId: 1, + parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: activemq-artemis-2.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: ActiveMQ/Topic/TopicDemo/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 46 + isError: false + spanType: Entry + peer: not blank + skipAnalysis: false + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.topic, value: not blank} + - {key: mq.message.id, value: not null} + refs: + - {parentEndpoint: 'GET:/activemq-artemis-scenario/testcase/activemq-artemis-scenario', + networkAddress: not blank, refType: CrossProcess, parentSpanId: 2, + parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: activemq-artemis-2.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: ActiveMQ/Queue/QueueDemo2/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 46 + isError: false + spanType: Entry + peer: not blank + skipAnalysis: false + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + refs: + - {parentEndpoint: 'GET:/activemq-artemis-scenario/testcase/activemq-artemis-scenario', + networkAddress: not blank, refType: CrossProcess, parentSpanId: 3, + parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: activemq-artemis-2.x-scenario, + traceId: not null} + - segmentId: not null + spans: + - operationName: ActiveMQ/Queue/QueueDemo/Producer + parentSpanId: 0 + spanId: 1 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 45 + isError: false + spanType: Exit + peer: not blank + skipAnalysis: false + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + - operationName: ActiveMQ/Topic/TopicDemo/Producer + parentSpanId: 0 + spanId: 2 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 45 + isError: false + spanType: Exit + peer: not blank + skipAnalysis: false + tags: + - {key: mq.broker, value: not blank} + - {key: mq.topic, value: not blank} + - {key: mq.message.id, value: not null} + - operationName: ActiveMQ/Queue/QueueDemo2/Producer + parentSpanId: 0 + spanId: 3 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 45 + isError: false + spanType: Exit + peer: not blank + skipAnalysis: false + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + - operationName: ActiveMQ/Queue/QueueDemo3/Producer + parentSpanId: 0 + spanId: 4 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 45 + isError: false + spanType: Exit + peer: not blank + skipAnalysis: false + tags: + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + - operationName: GET:/activemq-artemis-scenario/testcase/activemq-artemis-scenario + parentSpanId: -1 + spanId: 0 + spanLayer: Http + startTime: nq 0 + endTime: nq 0 + componentId: 1 + isError: false + spanType: Entry + peer: '' + skipAnalysis: false + tags: + - {key: url, value: 'http://localhost:8080/activemq-artemis-scenario/testcase/activemq-artemis-scenario'} + - {key: http.method, value: GET} + - {key: http.status_code, value: '200'} + - segmentId: not null + spans: + - operationName: ActiveMQ/Queue/QueueDemo3/Consumer + parentSpanId: -1 + spanId: 0 + spanLayer: MQ + startTime: nq 0 + endTime: nq 0 + componentId: 46 + isError: false + spanType: Entry + peer: not blank + skipAnalysis: false + tags: + - {key: transmission.latency, value: ge 0} + - {key: mq.broker, value: not blank} + - {key: mq.queue, value: not blank} + - {key: mq.message.id, value: not null} + refs: + - {parentEndpoint: 'GET:/activemq-artemis-scenario/testcase/activemq-artemis-scenario', + networkAddress: not blank, refType: CrossProcess, parentSpanId: 4, + parentTraceSegmentId: not null, + parentServiceInstance: not null, parentService: activemq-artemis-2.x-scenario, + traceId: not null} \ No newline at end of file diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/configuration.yml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/configuration.yml new file mode 100644 index 0000000000..1ecda1486a --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/configuration.yml @@ -0,0 +1,31 @@ +# 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. + +type: jvm +entryService: http://localhost:8080/activemq-artemis-scenario/testcase/activemq-artemis-scenario +healthCheck: http://localhost:8080/activemq-artemis-scenario/testcase/healthCheck +startScript: ./bin/startup.sh +environment: + - BROKERURL=tcp://activemq-server:61616 + - USER=artemis + - PASSWORD=artemis +dependencies: + activemq-server: + image: apache/activemq-artemis:2.31.2 + hostname: activemq-server + expose: + - 8161 + - 61616 \ No newline at end of file diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/pom.xml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/pom.xml new file mode 100644 index 0000000000..57fda8bf62 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/pom.xml @@ -0,0 +1,140 @@ + + + + 4.0.0 + com.example + activemq-artemis-2.x-scenario + 0.0.1-SNAPSHOT + activemq-artemis-2.x-scenario + activemq-artemis-2.x-scenario + + 17 + UTF-8 + UTF-8 + 2.31.2 + 3.0.0 + 1.18.20 + ${test.framework.version} + 3.8.1 + 3.5.0.Final + 6.0.2 + + + + org.springframework.boot + spring-boot-starter-web + ${spring-boot.version} + + + org.springframework.boot + spring-boot-starter-logging + + + + + org.springframework + spring-jms + ${spring-jms.version} + + + org.apache.activemq + artemis-jakarta-client + ${test.framework.version} + + + org.apache.activemq + artemis-core-client + ${test.framework.version} + + + org.apache.activemq + artemis-commons + ${test.framework.version} + + + org.apache.activemq + artemis-selector + ${test.framework.version} + + + org.springframework.boot + spring-boot-starter-log4j2 + ${spring-boot.version} + + + org.projectlombok + lombok + ${lombok.version} + provided + + + org.jboss.logging + jboss-logging + ${jboss-logging.version} + + + + + activemq-artemis-2.x-scenario + + + org.springframework.boot + spring-boot-maven-plugin + ${spring-boot.version} + + + + repackage + + + + + + maven-compiler-plugin + ${maven-compiler-plugin.version} + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + + + + org.apache.maven.plugins + maven-assembly-plugin + + + assemble + package + + single + + + + src/main/assembly/assembly.xml + + ./target/ + + + + + + + + diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/assembly/assembly.xml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/assembly/assembly.xml new file mode 100644 index 0000000000..d61a5c3cc1 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/assembly/assembly.xml @@ -0,0 +1,41 @@ + + + + + zip + + + + + ./bin + 0775 + + + + + + ${project.build.directory}/activemq-artemis-2.x-scenario.jar + ./libs + 0775 + + + diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/Application.java b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/Application.java new file mode 100644 index 0000000000..81702b310b --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/Application.java @@ -0,0 +1,32 @@ +/* + * 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.skywalking.apm.testcase.activemq.artemis; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.jms.annotation.EnableJms; + +@EnableJms +@SpringBootApplication +public class Application { + + public static void main(String[] args) { + SpringApplication.run(Application.class, args); + } + +} diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/config/ActiveMQConfig.java b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/config/ActiveMQConfig.java new file mode 100644 index 0000000000..b2798b9ca3 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/config/ActiveMQConfig.java @@ -0,0 +1,36 @@ +/* + * 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.skywalking.apm.testcase.activemq.artemis.config; + +import jakarta.jms.ConnectionFactory; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.jms.config.DefaultJmsListenerContainerFactory; +import org.springframework.jms.config.JmsListenerContainerFactory; + +@Configuration +public class ActiveMQConfig { + + @Bean + public JmsListenerContainerFactory jmsListenerContainerTopic(ConnectionFactory activeMQConnectionFactory) { + DefaultJmsListenerContainerFactory bean = new DefaultJmsListenerContainerFactory(); + bean.setPubSubDomain(true); + bean.setConnectionFactory(activeMQConnectionFactory); + return bean; + } +} diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/controller/CaseController.java b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/controller/CaseController.java new file mode 100644 index 0000000000..99a4418f6d --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/controller/CaseController.java @@ -0,0 +1,47 @@ +/* + * 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.skywalking.apm.testcase.activemq.artemis.controller; + +import org.apache.skywalking.apm.testcase.activemq.artemis.service.MessagingService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +@RestController +@RequestMapping("/testcase") +public class CaseController { + private static final String SUCCESS = "Success"; + + @Autowired + private MessagingService messagingService; + + @GetMapping("/activemq-artemis-scenario") + public String demo() throws Exception { + messagingService.sendMessage("hello world"); + messagingService.sendTopicMessage("hello world"); + messagingService.sendAndReceiveMessage("hello world"); + messagingService.convertAndSendMessage("hello world"); + return SUCCESS; + } + + @GetMapping("/healthCheck") + public String healthCheck() { + return SUCCESS; + } +} diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingListener.java b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingListener.java new file mode 100644 index 0000000000..2052579930 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingListener.java @@ -0,0 +1,49 @@ +/* + * 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.skywalking.apm.testcase.activemq.artemis.service; + +import jakarta.jms.Message; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.jms.annotation.JmsListener; +import org.springframework.stereotype.Component; + +@Component +public class MessagingListener { + final Logger logger = LoggerFactory.getLogger(getClass()); + + @JmsListener(destination = "QueueDemo", concurrency = "10") + public void onMessageReceived(Message message) throws Exception { + logger.info("received normal message: " + message); + } + + @JmsListener(destination = "TopicDemo", concurrency = "1", containerFactory = "jmsListenerContainerTopic") + public void onSelfMessageReceived(Message message) throws Exception { + logger.info("received self message: " + message); + } + + @JmsListener(destination = "QueueDemo2", concurrency = "1") + public void onSendReceiveMessageReceived(Message message) throws Exception { + logger.info("received send and receive message: " + message); + } + + @JmsListener(destination = "QueueDemo3", concurrency = "1") + public void onConvertSendMessageReceived(Message message) throws Exception { + logger.info("received convert and send message: " + message); + } +} diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingService.java b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingService.java new file mode 100644 index 0000000000..e4f5011342 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/java/org/apache/skywalking/apm/testcase/activemq/artemis/service/MessagingService.java @@ -0,0 +1,69 @@ +/* + * 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.skywalking.apm.testcase.activemq.artemis.service; + +import jakarta.jms.JMSException; +import jakarta.jms.Message; +import jakarta.jms.Session; +import org.apache.activemq.artemis.jms.client.ActiveMQDestination; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.jms.core.JmsTemplate; +import org.springframework.jms.core.MessageCreator; +import org.springframework.stereotype.Component; + +@Component +public class MessagingService { + @Autowired + private JmsTemplate jmsTemplate; + + public void sendMessage(String text) throws Exception { + jmsTemplate.send("QueueDemo", new MessageCreator() { + @Override + public Message createMessage(Session session) throws JMSException { + return session.createTextMessage(text); + } + }); + } + + public void sendTopicMessage(String text) throws Exception { + ActiveMQDestination destination = ActiveMQDestination.createDestination( + "TopicDemo", ActiveMQDestination.TYPE.TOPIC); + jmsTemplate.send(destination, new MessageCreator() { + @Override + public Message createMessage(final Session session) throws JMSException { + return session.createTextMessage(text); + } + }); + } + + public void sendAndReceiveMessage(String text) throws Exception { + jmsTemplate.setReceiveTimeout(500); + jmsTemplate.sendAndReceive("QueueDemo2", new MessageCreator() { + @Override + public Message createMessage(Session session) throws JMSException { + return session.createTextMessage(text); + } + }); + } + + public void convertAndSendMessage(String text) throws Exception { + ActiveMQDestination destination = ActiveMQDestination.createDestination( + "QueueDemo3", ActiveMQDestination.TYPE.QUEUE); + jmsTemplate.convertAndSend(destination, text); + } +} \ No newline at end of file diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/application.yaml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/application.yaml new file mode 100644 index 0000000000..4298edec40 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/application.yaml @@ -0,0 +1,31 @@ +# +# 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. +# +# +server: + port: 8080 + servlet: + context-path: /activemq-artemis-scenario +spring: + jms: + pub-sub-domain: false + artemis: + mode: native +logging: + config: classpath:log4j2.xml + + + diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/log4j2.xml b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/log4j2.xml new file mode 100644 index 0000000000..9849ed5a8a --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/src/main/resources/log4j2.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/test/plugin/scenarios/activemq-artemis-2.x-scenario/support-version.list b/test/plugin/scenarios/activemq-artemis-2.x-scenario/support-version.list new file mode 100644 index 0000000000..06a4c47be4 --- /dev/null +++ b/test/plugin/scenarios/activemq-artemis-2.x-scenario/support-version.list @@ -0,0 +1,32 @@ +# 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. + +# lists your version here (Contains only the last version number of each minor version.) +2.17.0 +2.18.0 +2.19.1 +2.20.0 +2.21.0 +2.22.0 +2.23.1 +2.24.0 +2.25.0 +2.26.0 +2.27.1 +2.28.0 +2.29.0 +2.30.0 +2.31.2 \ No newline at end of file