4

I use spring boot 2.2.5 + micrometer 1.3.5 + starter-data-mongodb

Under "io.micrometer.core.instrument.binder.mongodb" I can see 2 classes CommandListener and ConnectionPoolListener. I would like to know what purpose these serve?

In actuator metrics endpoint, mongo metrics are not available.

How do I enable metrics for mongodb in actuator? For example, actuator automatically shows several metrics of RabbitMQ. I was expecting something similar in case of MongoDB as well. Should I create my own metrics?

Winster
  • 943
  • 10
  • 28
  • Is it a good practice to start/stop timer in AbstractMongoEventListener - onBeforeConvert & onAfterConvert – Winster May 18 '20 at 15:37

3 Answers3

9

In order to enable Spring Boot applying its AutoConfiguration I suggest to use the customizer pattern:

Kotlin:

@Configuration
class MongoConfiguration {

    @Bean
    fun mongoClientSettingsBuilderCustomizer(meterRegistry: MeterRegistry) =
        MongoClientSettingsBuilderCustomizer {
           it.addCommandListener(MongoMetricsCommandListener(meterRegistry))}
}

Java:

@Configuration
public class MongoConfiguration {

   @Bean
   public MongoClientSettingsBuilderCustomizer mongoClientSettingsBuilderCustomizer(MeterRegistry meterRegistry) {
        return builder -> builder.addCommandListener(new MongoMetricsCommandListener(meterRegistry));
   }

}

Please note you currenly will neither see a relation to the spring data repository nor to the mongo collection in the metrics. see open issue


EDIT (07/30/2021):

The issues has been fixed, so you likely get collection metrics in a current release.

rgrebski
  • 2,354
  • 20
  • 29
chrgue
  • 579
  • 1
  • 6
  • 18
4

Adding those listeners is not as straighforward as i thought and it's quite dependend on which properties you use for configuring Spring Data MongoDB.

The key for the integration is to customize the com.mongodb.MongoClientSettings instance which is used for creating the MongoClient. There are multiple possiblities to do so as documented in Connecting to MongoDB with Spring

The following is a working example (simplified from an application of ours) based on Spring Boot 2.3 which assumes you are using spring.data.mongodb.uri to specify the connection string in your application.properties.

package com.example.demo;

import com.mongodb.ConnectionString;
import com.mongodb.MongoClientSettings;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.binder.mongodb.MongoMetricsCommandListener;
import io.micrometer.core.instrument.binder.mongodb.MongoMetricsConnectionPoolListener;
import org.springframework.boot.autoconfigure.mongo.MongoProperties;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.mongodb.core.MongoClientFactoryBean;

@Configuration
public class MongoConfiguration {

    @Bean
    public MongoClientFactoryBean mongoClientFactoryBean(MongoProperties properties, MeterRegistry meterRegistry) {
        MongoClientFactoryBean mongoClientFactoryBean = new MongoClientFactoryBean();

        mongoClientFactoryBean.setConnectionString(new ConnectionString(properties.getUri()));

        MongoClientSettings settings = MongoClientSettings.builder()
                .addCommandListener(new MongoMetricsCommandListener(meterRegistry))
                .applyToConnectionPoolSettings(builder ->
                        builder.addConnectionPoolListener(new MongoMetricsConnectionPoolListener(meterRegistry)))
                .build();
        mongoClientFactoryBean.setMongoClientSettings(settings);

        return mongoClientFactoryBean;
    }

}

Unfortunately a lot has in configuring MongoDB from Spring Boot 2.2 to 2.3. If you cannot use Spring Boot 2.3 and you are stuck in backporting this to 2.2 please let me know.

0

Short answer

Create a MongoClientOptions bean with addCommandListener and you are good to go.

@Configuration
public class MongoConfiguration {
    @Autowired
    private MeterRegistry meterRegistry;

    @Bean
    public MongoClientOptions myMongoClientOptions() {
        return MongoClientOptions.builder()
.addCommandListener(new MongoMetricsCommandListener(meterRegistry)).build();
    }

}

@chargue's answer won't work for certain version of spring-data-mongodb. Because org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration initializes MongoClient with MongoClientOptions, not MongoClientSettings. It might work in newer version of spring-data-mongodb cuz MongoClientSettings is the recommended way according to mongodb's documents.

    @Bean
    @ConditionalOnMissingBean(type = { "com.mongodb.MongoClient", "com.mongodb.client.MongoClient" })
    public MongoClient mongo(MongoProperties properties, ObjectProvider<MongoClientOptions> options,
            Environment environment) {
        return new MongoClientFactory(properties, environment).createMongoClient(options.getIfAvailable());
    }

Make sure prometheus and micrometer is correctlly setup. You should see mongo metrics in prometheus endpoint like below:

# HELP process_cpu_usage The "recent cpu usage" for the Java Virtual Machine process
# TYPE process_cpu_usage gauge
process_cpu_usage{application="",} 0.004362672325272289
# HELP mongodb_driver_commands_seconds_max Timer of mongodb commands
# TYPE mongodb_driver_commands_seconds_max gauge
mongodb_driver_commands_seconds_max{application="",cluster_id="60b0d12d73b6df671cb4d882",command="find",server_address="",status="SUCCESS",} 34.684200332
mongodb_driver_commands_seconds_max{application="",cluster_id="60b0d12d73b6df671cb4d882",command="buildInfo",server_address="",status="SUCCESS",} 0.263514375
# HELP mongodb_driver_commands_seconds Timer of mongodb commands
# TYPE mongodb_driver_commands_seconds summary
mongodb_driver_commands_seconds_count{application="",cluster_id="60b0d12d73b6df671cb4d882",command="find",server_address="",status="SUCCESS",} 1.0
mongodb_driver_commands_seconds_sum{application="",cluster_id="60b0d12d73b6df671cb4d882",command="find",server_address="",status="SUCCESS",} 34.684200332
mongodb_driver_commands_seconds_count{application="",cluster_id="60b0d12d73b6df671cb4d882",command="buildInfo",server_address="",status="SUCCESS",} 1.0
mongodb_driver_commands_seconds_sum{application="",cluster_id="60b0d12d73b6df671cb4d882",command="buildInfo",server_address="",status="SUCCESS",} 0.263514375
yadance nick
  • 101
  • 1
  • 5
  • How make it work for spring 2.6? seems like interface MongoClientFactory drastically changed – M_F Mar 22 '22 at 15:38