2

Spring's Metrics and Management: MessageChannel Metric Features describes:

If it is a QueueChannel, you also see statistics for the receive operation as well as the count of messages that are currently buffered by this QueueChannel

However:

These legacy metrics will be removed in a future release. See Micrometer Integration.

Where it describes:

The Counter Meters for receive operations on pollable message channels have the following names or tags: name: spring.integration.receive [...]

which sounds like it only counts how many messages have been received. The number of messages in the queue doesn't seem to be available, not even by calculating receive - send (because there is no send).

So, with Spring Integration and Micrometer, is it even possible to read the queue size? How?

Michel Jung
  • 2,966
  • 6
  • 31
  • 51

2 Answers2

2

I think we need to register a Gauge for this queue size value:

/**
 * A gauge tracks a value that may go up or down. The value that is published for gauges is
 * an instantaneous sample of the gauge at publishing time.
 *
 * @author Jon Schneider
 */
public interface Gauge extends Meter {

And here is a respective builder:

/**
 * A convenience method for building a gauge from a supplying function, holding a strong
 * reference to this function.
 *
 * @param name The gauge's name.
 * @param f    A function that yields a double value for the gauge.
 * @return A new gauge builder.
 * @since 1.1.0
 */
@Incubating(since = "1.1.0")
static Builder<Supplier<Number>> builder(String name, Supplier<Number> f) {

Feel free to raise a GH issue to improve things!

At the moment it is probably possible via an external Gauge instance with QueueChannel.getQueueSize() delegation.

Artem Bilan
  • 113,505
  • 11
  • 91
  • 118
2

Until Spring Integration 5.4 is released, this can be used:

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Configuration;
import org.springframework.integration.channel.QueueChannel;
import org.springframework.integration.support.management.metrics.MetricsCaptor;
import org.springframework.integration.support.management.micrometer.MicrometerMetricsCaptor;

import java.util.Collection;

@Configuration
@RequiredArgsConstructor
public class IntegrationMetricConfig {

  private final ApplicationContext applicationContext;
  private final Collection<QueueChannel> queues;

  /**
   * Temporary solution until <a href="https://github.com/spring-projects/spring-integration/pull/3349/files">Add
   * gauges for queue channel size</a> is released. Remove this when updating to Spring Integration
   * 5.4.
   */
  @Autowired
  public void queueSizeGauges() {
    MetricsCaptor metricsCaptor = MicrometerMetricsCaptor.loadCaptor(this.applicationContext);
    queues.forEach(queue -> {
      metricsCaptor.gaugeBuilder("spring.integration.channel.queue.size", queue,
        obj -> queue.getQueueSize())
        .tag("name", queue.getComponentName() == null ? "unknown" : queue.getComponentName())
        .tag("type", "channel")
        .description("The size of the queue channel")
        .build();

      metricsCaptor.gaugeBuilder("spring.integration.channel.queue.remaining.capacity", this,
        obj -> queue.getQueueSize())
        .tag("name", queue.getComponentName() == null ? "unknown" : queue.getComponentName())
        .tag("type", "channel")
        .description("The remaining capacity of the queue channel")
        .build();
    });
  }
}
Michel Jung
  • 2,966
  • 6
  • 31
  • 51