2

I use Spring Boot 2.1.2.RELEASE, and I try to use Micrometer with CompositeMeterRegistry. My goal is to publish some selected meters to ElasticSearch. The code below shows my sample config. The problem is, that the filter is completely ignored (so all metrics are sent to ElasticSearch), although I can see in the logs that it was processed ("filter reply of meter ..." lines).

Strangely, if I define the MeterFilter as a Spring bean, then it's applied to ALL registries (however, I want it to be applied only on "elasticMeterRegistry").

Here is a sample configuration class:

@Configuration
public class AppConfiguration {

    @Bean
    public ElasticConfig elasticConfig() {
        return new ElasticConfig() {
            @Override
            @Nullable
            public String get(final String k) {
                return null;
            }
        };
    }

    @Bean
    public MeterRegistry meterRegistry(final ElasticConfig elasticConfig) {
        final CompositeMeterRegistry registry = new CompositeMeterRegistry();
        registry.add(new SimpleMeterRegistry());
        registry.add(new JmxMeterRegistry(new JmxConfig() {
            @Override
            public Duration step() {
                return Duration.ofSeconds(10);
            }

            @Override
            @Nullable
            public String get(String k) {
                return null;
            }
        }, Clock.SYSTEM));

        final ElasticMeterRegistry elasticMeterRegistry = new ElasticMeterRegistry(elasticConfig, Clock.SYSTEM);
        elasticMeterRegistry.config().meterFilter(new MeterFilter() {
            @Override
            public MeterFilterReply accept(Meter.Id id) {
                final MeterFilterReply reply =
                        id.getName().startsWith("logback")
                                ? MeterFilterReply.NEUTRAL
                                : MeterFilterReply.DENY;
                log.info("filter reply of meter {}: {}", id.getName(), reply);
                return reply;
            }
        });
        registry.add(elasticMeterRegistry);

        return registry;
    }
}

So, I expect ElasticSearch to receive only "logback" metrics, and JMX to receive all metrics.

UPDATE:

I have played with filters and found a "solution", but I don't really understand why the code above doesn't work.

This works:

elasticMeterRegistry.config().meterFilter(new MeterFilter() {
    @Override
    public MeterFilterReply accept(Meter.Id id) {
        final MeterFilterReply reply =
                id.getName().startsWith("logback")
                        ? MeterFilterReply.ACCEPT
                        : MeterFilterReply.DENY;
        log.info("filter reply of meter {}: {}", id.getName(), reply);
        return reply;
    }
});

The difference is: I return ACCEPT instead of NEUTRAL.

Strangely, the following code does not work (ES gets all metrics):

elasticMeterRegistry.config().meterFilter(
    MeterFilter.accept(id -> id.getName().startsWith("logback")));

But this works:

elasticMeterRegistry.config().meterFilter(
    MeterFilter.accept(id -> id.getName().startsWith("logback")));
elasticMeterRegistry.config().meterFilter(
    MeterFilter.deny());

CONCLUSION:

So, it seems that instead of NEUTRAL, the filter should return ACCEPT. But for meters not starting with "logback", my original filter (with NEUTRAL) returns DENY. Then why are those metrics published to ElasticSearch registry?

Can someone explain this?

1 Answers1

1

This is really a composite of questions. I'll just point out a few points.

For the MeterRegistry bean you defined, Spring Boot will auto-configure an ElasticMeterRegistry bean as there's no ElasticMeterRegistry bean. Instead of creating a CompositeMeterRegistry bean on your own, just define a custom ElasticMeterRegistry bean which is applied the MeterFilter you want and let Spring Boot create one (CompositeMeterRegistry bean) for you.

For MeterFilterReply, ACCEPT will accept the meter immediately, DENY will deny the meter immediately, and NEUTRAL will postpone the decision to next filter(s). Basically meters will be accepted unless there's any DENY.

Johnny Lim
  • 5,623
  • 8
  • 38
  • 53
  • Defining `ElasticMeterRegistry` is a nice suggestion, thank you. However, it doesn't seem to work. First, I tried to define `elasticMeterRegistry` bean, but that failed because a bean with the same name was already registered. It turns out that an `elasticMeterRegistry` bean is defined in `ElasticMetricsExportAutoConfiguration` automatically. Then I tried to inject this bean (instead of defining my own) and add the filter (in a method annotated with `@PostConstruct`, but the filter didn't have any effect. – Alexander Molnár Feb 20 '19 at 10:14
  • For `MeterFilterReply`, you are right. However, if you have only one filter, returning `NEUTRAL` instead of `ACCEPT` should have the same effect, right? – Alexander Molnár Feb 20 '19 at 10:18