co.elastic.apm.agent.tracer.configuration.MessagingConfiguration Maven / Gradle / Ivy
/*
* Licensed to Elasticsearch B.V. under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch B.V. 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 co.elastic.apm.agent.tracer.configuration;
import co.elastic.apm.agent.premain.common.util.WildcardMatcher;
import co.elastic.apm.agent.tracer.configuration.WildcardMatcherValueConverter;
import org.stagemonitor.configuration.ConfigurationOption;
import org.stagemonitor.configuration.ConfigurationOptionProvider;
import org.stagemonitor.configuration.converter.ListValueConverter;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class MessagingConfiguration extends ConfigurationOptionProvider {
private static final String MESSAGING_CATEGORY = "Messaging";
private static final String MESSAGE_POLLING_TRANSACTION_STRATEGY = "message_polling_transaction_strategy";
private static final String MESSAGE_BATCH_STRATEGY = "message_batch_strategy";
private ConfigurationOption messagePollingTransactionStrategy = ConfigurationOption.enumOption(JmsStrategy.class)
.key(MESSAGE_POLLING_TRANSACTION_STRATEGY)
.configurationCategory(MESSAGING_CATEGORY)
.tags("internal")
.description("Determines whether the agent should create transactions for the polling action itself (e.g. `javax.jms.MessageConsumer#receive`/`jakarta.jms.MessageConsumer#receive`), \n" +
"attempt to create a transaction for the message handling code occurring if the polling method returns a message, \n" +
"or both. Valid options are: `POLLING`, `HANDLING` and `BOTH`. \n" +
"\n" +
"This option is case-insensitive and is only relevant for JMS.")
.dynamic(true)
.buildWithDefault(JmsStrategy.HANDLING);
private ConfigurationOption messageBatchStrategy = ConfigurationOption.enumOption(BatchStrategy.class)
.key(MESSAGE_BATCH_STRATEGY)
.configurationCategory(MESSAGING_CATEGORY)
.tags("internal")
.description("Determines whether Spring messaging system libraries should create a batch for the processing of the entire \n" +
"message/record batch, or one transaction for each message/record processing, typically by wrapping the message batch data \n" +
"structure. Valid options are `SINGLE_HANDLING` and `BATCH_HANDLING`. \n" +
"\n" +
"This option is case-insensitive and is only relevant for Spring messaging system libraries that support batch processing.")
.dynamic(true)
.buildWithDefault(BatchStrategy.BATCH_HANDLING);
private ConfigurationOption collectQueueAddress = ConfigurationOption.booleanOption()
.key("collect_queue_address")
.configurationCategory(MESSAGING_CATEGORY)
.tags("internal")
.description("Determines whether the agent should collect destination address and port, as this may be \n" +
"an expensive operation.")
.dynamic(true)
.buildWithDefault(Boolean.TRUE);
private final ConfigurationOption> ignoreMessageQueues = ConfigurationOption
.builder(new ListValueConverter<>(new WildcardMatcherValueConverter()), List.class)
.key("ignore_message_queues")
.configurationCategory(MESSAGING_CATEGORY)
.description("Used to filter out specific messaging queues/topics from being traced. \n" +
"\n" +
"This property should be set to an array containing one or more strings.\n" +
"When set, sends-to and receives-from the specified queues/topic will be ignored.\n" +
"\n" +
WildcardMatcher.DOCUMENTATION)
.dynamic(true)
.buildWithDefault(Collections.emptyList());
private final ConfigurationOption endMessagingTransactionOnPoll = ConfigurationOption.booleanOption()
.key("end_messaging_transaction_on_poll")
.configurationCategory(MESSAGING_CATEGORY)
.tags("internal")
.description("When tracing messaging systems, we sometimes create transactions based on consumed messages \n" +
"when they are iterated-over after being polled. This means that transaction ending relies on the \n" +
"iterating behavior, which means transactions may be left unclosed. In such cases, we deactivate \n" +
"and close such transactions when the next poll action is invoked on the same thread. \n" +
"However, if the messaging transaction itself tries to poll a queue, it will be ended prematurely. In \n" +
"such cases, set this property to false." +
WildcardMatcher.DOCUMENTATION)
.dynamic(true)
.buildWithDefault(Boolean.TRUE);
private final ConfigurationOption> jmsListenerPackages = ConfigurationOption
.stringsOption()
.key("jms_listener_packages")
.tags("performance", "added[1.36.0]")
.configurationCategory(MESSAGING_CATEGORY)
.description("Defines which packages contain JMS MessageListener implementations for instrumentation." +
"\n" +
"When empty (default), all inner-classes or any classes that have 'Listener' or 'Message' in their names are considered.\n"+
"\n" +
"This configuration option helps to make MessageListener type matching faster and improve application startup performance.\n" +
"\n" +
"Starting from version 1.43.0, the classes that are part of the 'application_packages' option are also included in the list of classes considered."
)
.dynamic(false)
.buildWithDefault(Collections.emptyList());
public JmsStrategy getMessagePollingTransactionStrategy() {
return messagePollingTransactionStrategy.get();
}
public BatchStrategy getMessageBatchStrategy() {
return messageBatchStrategy.get();
}
public List getIgnoreMessageQueues() {
return ignoreMessageQueues.get();
}
public boolean shouldCollectQueueAddress() {
return collectQueueAddress.get();
}
public boolean shouldEndMessagingTransactionOnPoll() {
return endMessagingTransactionOnPoll.get();
}
public Collection getJmsListenerPackages() {
return jmsListenerPackages.get();
}
public enum JmsStrategy {
/**
* Create a transaction capturing JMS {@code receive} invocations
*/
POLLING,
/**
* Use heuristics to create a transaction that captures the JMS message handling execution. This strategy requires heuristics
* when JMS {@code receive} APIs are used (rather than {@code onMessage}), as there is no API representing message handling start
* and end. Even though this is riskier and less deterministic, it is the default JMS tracing strategy otherwise all
* "interesting" subsequent events that follow message receive will be missed because there will be no active transaction.
*/
HANDLING,
/**
* Create a transaction both for the polling ({@code receive}) action AND the subsequent message handling.
*/
BOTH
}
/**
* Only relevant for Spring wrappers around supported messaging clients, such as AMQP.
*/
public enum BatchStrategy {
/**
* Create a transaction for each received message/record, typically by wrapping the message batch data structure
*/
SINGLE_HANDLING,
/**
* Create a single transaction encapsulating the entire message/record batch-processing.
*/
BATCH_HANDLING
}
}