Metrics and Management

This section describes how to capture metrics for Spring Integration. In recent versions, we have relied more on Micrometer (see micrometer.io), and we plan to use Micrometer even more in future releases.

Disabling Logging in High Volume Environments

You can control debug logging in the main message flow. In very high volume applications, calls to isDebugEnabled() can be quite expensive with some logging subsystems. You can disable all such logging to avoid this overhead. Exception logging (debug or otherwise) is not affected by this setting.

The following listing shows the available options for controlling logging:

  • Java

  • XML

@Configuration
@EnableIntegration
@EnableIntegrationManagement(
    defaultLoggingEnabled = "true" <1>)

public static class ContextConfiguration {
...
}
<int:management default-logging-enabled="true"/> (1)
1 Set to false to disable all logging in the main message flow, regardless of the log system category settings. Set to 'true' to enable debug logging (if also enabled by the logging subsystem). Only applied if you have not explicitly configured the setting in a bean definition. The default is true.
defaultLoggingEnabled is applied only if you have not explicitly configured the corresponding setting in a bean definition.

Micrometer Integration

Overview

Starting with version 5.0.3, the presence of a Micrometer MeterRegistry in the application context triggers support for Micrometer metrics.

To use Micrometer, add one of the MeterRegistry beans to the application context.

For each MessageHandler and MessageChannel, timers are registered. For each MessageSource, a counter is registered.

This only applies to objects that extend AbstractMessageHandler, AbstractMessageChannel, and AbstractMessageSource (which is the case for most framework components).

The Timer Meters for send operations on message channels have the following names or tags:

  • name: spring.integration.send

  • tag: type:channel

  • tag: name:<componentName>

  • tag: result:(success|failure)

  • tag: exception:(none|exception simple class name)

  • description: Send processing time

(A failure result with a none exception means the channel’s send() operation returned false.)

The Counter Meters for receive operations on pollable message channels have the following names or tags:

  • name: spring.integration.receive

  • tag: type:channel

  • tag: name:<componentName>

  • tag: result:(success|failure)

  • tag: exception:(none|exception simple class name)

  • description: Messages received

The Timer Meters for operations on message handlers have the following names or tags:

  • name: spring.integration.send

  • tag: type:handler

  • tag: name:<componentName>

  • tag: result:(success|failure)

  • tag: exception:(none|exception simple class name)

  • description: Send processing time

The Counter meters for message sources have the following names/tags:

  • name: spring.integration.receive

  • tag: type:source

  • tag: name:<componentName>

  • tag: result:success

  • tag: exception:none

  • description: Messages received

In addition, there are three Gauge Meters:

  • spring.integration.channels: The number of MessageChannels in the application.

  • spring.integration.handlers: The number of MessageHandlers in the application.

  • spring.integration.sources: The number of MessageSources in the application.

It is possible to customize the names and tags of Meters created by integration components by providing a subclass of MicrometerMetricsCaptor. The MicrometerCustomMetricsTests test case shows a simple example of how to do that. You can also further customize the meters by overloading the build() methods on builder subclasses.

Starting with version 5.1.13, the QueueChannel exposes Micrometer gauges for queue size and remaining capacity:

  • name: spring.integration.channel.queue.size

  • tag: type:channel

  • tag: name:<componentName>

  • description: The size of the queue channel

and

  • name: spring.integration.channel.queue.remaining.capacity

  • tag: type:channel

  • tag: name:<componentName>

  • description: The remaining capacity of the queue channel

Disabling Meters

By default, all meters are registered when first used. Now, with Micrometer, you can add MeterFilter s to the MeterRegistry to prevent some or all from being registered. You can filter out (deny) meters by any of the properties provided, name, tag, etc. See Meter Filters in the Micrometer documentation for more information.

For example, given:

@Bean
public QueueChannel noMeters() {
    return new QueueChannel(10);
}

You can suppress registration of meters for just this channel with:

registry.config().meterFilter(MeterFilter.deny(id ->
        "channel".equals(id.getTag("type")) &&
        "noMeters".equals(id.getTag("name"))));

Micrometer Observation

Starting with version 6.0, Spring Integration utilizes a Micrometer Observation abstraction which can handle metrics as well as tracing via appropriate ObservationHandler configuration.

The observation handling is enabled on the IntegrationManagement components whenever an ObservationRegistry bean is present in the application context and an @EnableIntegrationManagement is configured. To customize what set of components should be instrumented, an observationPatterns() attribute is exposed on the @EnableIntegrationManagement annotation. See its javadocs for a pattern matching algorithm.

By default, none of the IntegrationManagement components are instrumented with an ObservationRegistry bean. Can be configured as * to match all components.

The meters are not gathered in this case independently, but delegated to an appropriate ObservationHandler configured on the provided ObservationRegistry.

The following Spring Integration components are instrumented with observation logic each with a respective convention:

  • MessageProducerSupport, being the inbound endpoint of the flow, is considered as a CONSUMER span type and uses the IntegrationObservation.HANDLER API;

  • MessagingGatewaySupport` is an inbound request-reply endpoint, and is considered as a SERVER span type. It uses the IntegrationObservation.GATEWAY API;

  • An AbstractMessageChannel.send() operation is the only Spring Integration API where it produces messages. So, it is treated as a PRODUCER span type and uses the IntegrationObservation.PRODCUER API. This makes more sense when a channel is a distributed implementation (e.g. PublishSubscribeKafkaChannel or ZeroMqChannel) and trace information has to be added to the message. So, the IntegrationObservation.PRODUCER observation is based on a MessageSenderContext where Spring Integration supplies a MutableMessage to allow a subsequent tracing Propagator to add headers, so they are available to the consumer;

  • An AbstractMessageHandler is a CONSUMER span type and uses the IntegrationObservation.HANDLER API.

An observation production on the IntegrationManagement components can be customized via ObservationConvention configuration. For example an AbstractMessageHandler expects a MessageReceiverObservationConvention via its setObservationConvention() API.

The following are supported metrics, spans and conventions for Observation API:

Observability - Metrics

Below you can find a list of all metrics declared by this project.

Gateway

Observation for inbound message gateways.

Metric name spring.integration.gateway (defined by convention class o.s.i.support.management.observation.DefaultMessageRequestReplyReceiverObservationConvention). Type timer.

Metric name spring.integration.gateway.active (defined by convention class o.s.i.support.management.observation.DefaultMessageRequestReplyReceiverObservationConvention). Type long task timer.

KeyValues that are added after starting the Observation might be missing from the *.active metrics.
Micrometer internally uses nanoseconds for the baseunit. However, each backend determines the actual baseunit. (i.e. Prometheus uses seconds)

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 1. Low cardinality Keys

Name

Description

spring.integration.name (required)

Name of the message gateway component.

spring.integration.outcome (required)

Outcome of the request/reply execution.

spring.integration.type (required)

Type of the component - 'gateway'.

Handler

Observation for message handlers.

Metric name spring.integration.handler (defined by convention class o.s.i.support.management.observation.DefaultMessageReceiverObservationConvention). Type timer.

Metric name spring.integration.handler.active (defined by convention class o.s.i.support.management.observation.DefaultMessageReceiverObservationConvention). Type long task timer.

KeyValues that are added after starting the Observation might be missing from the *.active metrics.
Micrometer internally uses nanoseconds for the baseunit. However, each backend determines the actual baseunit. (i.e. Prometheus uses seconds)

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 2. Low cardinality Keys

Name

Description

spring.integration.name (required)

Name of the message handler component.

spring.integration.type (required)

Type of the component - 'handler'.

Producer

Observation for message producers, e.g. channels.

Metric name spring.integration.producer (defined by convention class o.s.i.support.management.observation.DefaultMessageSenderObservationConvention). Type timer.

Metric name spring.integration.producer.active (defined by convention class o.s.i.support.management.observation.DefaultMessageSenderObservationConvention). Type long task timer.

KeyValues that are added after starting the Observation might be missing from the *.active metrics.
Micrometer internally uses nanoseconds for the baseunit. However, each backend determines the actual baseunit. (i.e. Prometheus uses seconds)

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 3. Low cardinality Keys

Name

Description

spring.integration.name (required)

Name of the message handler component.

spring.integration.type (required)

Type of the component - 'producer'.

Observability - Spans

Below you can find a list of all spans declared by this project.

Gateway Span

Observation for inbound message gateways.

Span name spring.integration.gateway (defined by convention class o.s.i.support.management.observation.DefaultMessageRequestReplyReceiverObservationConvention).

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 4. Tag Keys

Name

Description

spring.integration.name (required)

Name of the message gateway component.

spring.integration.outcome (required)

Outcome of the request/reply execution.

spring.integration.type (required)

Type of the component - 'gateway'.

Handler Span

Observation for message handlers.

Span name spring.integration.handler (defined by convention class o.s.i.support.management.observation.DefaultMessageReceiverObservationConvention).

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 5. Tag Keys

Name

Description

spring.integration.name (required)

Name of the message handler component.

spring.integration.type (required)

Type of the component - 'handler'.

Producer Span

Observation for message producers, e.g. channels.

Span name spring.integration.producer (defined by convention class o.s.i.support.management.observation.DefaultMessageSenderObservationConvention).

Fully qualified name of the enclosing class o.s.i.support.management.observation.IntegrationObservation.

All tags must be prefixed with spring.integration. prefix!
Table 6. Tag Keys

Name

Description

spring.integration.name (required)

Name of the message handler component.

spring.integration.type (required)

Type of the component - 'producer'.

Observability - Conventions

Below you can find a list of all GlobalObservationConvention and ObservationConvention declared by this project.

Table 7. ObservationConvention implementations

ObservationConvention Class Name

Applicable ObservationContext Class Name

o.s.i.support.management.observation.DefaultMessageReceiverObservationConvention

MessageReceiverContext

o.s.i.support.management.observation.MessageReceiverObservationConvention

MessageReceiverContext

o.s.i.support.management.observation.DefaultMessageRequestReplyReceiverObservationConvention

MessageRequestReplyReceiverContext

o.s.i.support.management.observation.MessageRequestReplyReceiverObservationConvention

MessageRequestReplyReceiverContext

o.s.i.support.management.observation.DefaultMessageSenderObservationConvention

MessageSenderContext

o.s.i.support.management.observation.MessageSenderObservationConvention

MessageSenderContext

Observation Propagation

To supply a connected chain of spans in one trace, independently of the nature of the messaging flow, even if a MessageChannel is persistent and distributed, the observation must be enabled on this channel and on consumers (subscribers) for this channel. This way, the tracing information is stored in the message headers before it is propagated to a consumer thread or persisted into the database. This is done via mentioned above MessageSenderContext. The consumer (a MessageHandler) side restores tracing information from those headers using a MessageReceiverContext and starts a new child Observation.

Spring Integration JMX Support

Also see JMX Support.