8

Problem:

We upgraded our Spring Boot version from 2.2.2 to 2.3.0, and all of the kafka_consumer_* metrics that were seen in the Prometheus endpoint in 2.2.2 are not visible in 2.3.0.

For example, all of the below are missing:

  • kafka_consumer_records_consumed_total_records_total
  • kafka_consumer_records_lag_records
  • kafka_consumer_fetch_latency_max_seconds
  • kafka_consumer_bytes_consumed_total_bytes_total

Not sure if we're missing some kind of configuration or something buried in the docs...

What has been tried:

  • Combed the Spring Boot 2.3.0 release notes, updated micrometer documentation, and updated spring-kafka documentation for why this might be happening
  • Googled to what feels like the ends of the Earth
  • Tried upgrading to Spring Boot 2.2.7 and the kafka metrics are still there, only upgrading to 2.3.0 seems to cause the issue
  • Removed any non-needed dependency/customization that was in our code for the project, and bare bones just connected to a kafka container on the localhost, and the metrics still don't appear

Relevant code/details:

  • We're using Red Hat AMQ Streams for our kafka broker (kafka version 2.1.1)
  • The only thing we've changed in our environment is the Spring Boot version (and dependencies that are automatically pulled in/updated) to recreate this issue

Below is our build.gradle.kts before the change:

import org.jetbrains.kotlin.gradle.tasks.KotlinCompile

plugins {
    id("org.springframework.boot") version "2.2.2.RELEASE"
    id("io.spring.dependency-management") version "1.0.9.RELEASE"
    kotlin("jvm") version "1.3.72"
    kotlin("plugin.spring") version "1.3.72"
}

group = "ourGroup"
version = "0.0.1"
java.sourceCompatibility = JavaVersion.VERSION_1_8

repositories {
    mavenCentral()
}

extra["springCloudVersion"] = "Hoxton.RELEASE"

dependencyManagement {
    imports {
        mavenBom("org.springframework.cloud:spring-cloud-dependencies:${property("springCloudVersion")}")
    }
}

dependencies {
    implementation("org.springframework.cloud:spring-cloud-starter-stream-kafka")
    implementation("org.springframework.boot:spring-boot-starter-actuator")
    implementation("io.micrometer:micrometer-registry-prometheus")
    implementation("org.springframework.boot:spring-boot-starter-webflux")
    implementation("org.jetbrains.kotlin:kotlin-stdlib-jdk8")
    testImplementation("org.springframework.boot:spring-boot-starter-test") {
        exclude(group = "org.junit.vintage", module = "junit-vintage-engine")
    }
    testImplementation("io.projectreactor:reactor-test")
    testImplementation("org.springframework.security:spring-security-test")
}

tasks.withType<Test> {
    useJUnitPlatform()
}

tasks.withType<KotlinCompile> {
    kotlinOptions {
        freeCompilerArgs = listOf("-Xjsr305=strict")
        jvmTarget = "1.8"
    }
}

Now, if we just update our build.gradle.kts with a new spring boot version like in the below line our kafka metrics disappear:

    id("org.springframework.boot") version "2.3.0.RELEASE"

Below are screenshots of the prometheus metrics we were seeing before and after the change:

Before 2.3.0 upgrade

After 2.3.0 upgrade

Thanks in advance for the help! Let me know if you need any other details!

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
Alan Yeung
  • 180
  • 3
  • 7
  • I am using `spring-kafka` and just tested @AlanYeung's issue. I can confirm that in Spring Boot `2.3.0.RELEASE`, the `kafka_consumer_*` metrics are gone in `/actuator/prometheus`. I can still see them in `2.2.7.RELEASE`. – jumping_monkey Jun 10 '20 at 01:08
  • 2
    Kafka meters were migrated from scraping JMX MBeans to using native metrics in Boot 2.0. See [this commit](https://github.com/spring-projects/spring-boot/commit/888a81beba23728078337ad91c27ca4abbcb189e#diff-2f3136f1958043f3d7c37de45bf062fa) and [this one](https://github.com/spring-projects/spring-boot/commit/d16074d8fdc457107177bca026635e4575fe0c08#diff-2f3136f1958043f3d7c37de45bf062fa). The last one uses [this](https://github.com/spring-projects/spring-kafka/commit/4c313955a67946bc9bf5c9fec40b26d700f7ffb2). I'll see if I can figure out what's broken tomorrow. – Gary Russell Jun 10 '20 at 01:58
  • Awesome @GaryRussell, thanks a lot for the pointers! I have the `kafka_consumer_*` metrics back in `2.3.0.RELEASE`. Cheers! – jumping_monkey Jun 11 '20 at 00:30
  • 1
    Correction `>in Boot 2.0` should be in Boot 2.3. – Gary Russell Jun 11 '20 at 00:44
  • I'd like to see more new contributors put this much effort into their first question. Nice job, Alan! – Jeremy Caney Jun 17 '20 at 20:16
  • @GaryRussell @jumping_monkey I am having the same problem, and despite reading all this I am really not clear what the solution is. I am not using `spring-kafka` to generate my consumers, although I did try adding that dependency. It did not help. With SpringBoot 2.2.13 worked without spring-kafka. All later version of SpringBoot fail even with spring-kafka dependency. – dlipofsky Dec 14 '21 at 18:29
  • Boot changed from scraping JMX MBeans to using the native `KafkaClientMetrics` provided by Micrometer. If you are creating Consumers yourself you will have to register your own metrics with the meter registry - this is how spring-kafka does it... https://github.com/spring-projects/spring-kafka/blob/4f44ad4e968281606382d2a3c2227a42ed6a327e/spring-kafka/src/main/java/org/springframework/kafka/core/MicrometerConsumerListener.java#L73-L74 – Gary Russell Dec 14 '21 at 18:51
  • Hey, for me Kafka producer metrics is not coming even in SpringBoot 2.2.6. I raise a question plz help: https://stackoverflow.com/questions/72899965/how-to-expose-kafka-producer-metrics-to-prometheus-with-spring-boot-2-2-6 – Trupti Prajapati Jul 08 '22 at 12:56

2 Answers2

4

It works for normal spring-kafka consumers

@SpringBootApplication
public class So62292889Application {

    public static void main(String[] args) {
        SpringApplication.run(So62292889Application.class, args);
    }

    @KafkaListener(id = "so62292889", topics = "so62292889")
    public void listen(String in) {
        System.out.println(in);
    }

    @Bean
    public NewTopic topic() {
        return TopicBuilder.name("so62292889").partitions(1).replicas(1).build();
    }

    @Bean
    public ApplicationRunner runner(MeterRegistry registry) {
        return args -> {
            registry.getMeters().forEach(meter -> System.out.println(meter.getId()));
        };
    }

}
MeterId{name='kafka.consumer.outgoing.byte.total'...

I see you are using spring-cloud-stream. The problem is that this project creates its own producer/consumer factories and doesn't add the Micrometer listeners.

I opened an issue against the binder.

Gary Russell
  • 166,535
  • 14
  • 146
  • 179
3

Similar to @jumping_monkey, I have a spring-kafka app using Spring Boot 2.3.0.RELEASE, and the kafka_consumer_* metrics were not showing up in /actuator/prometheus. They did show up when I downgraded to Spring Boot 2.2.7.RELEASE.

It has been determined that an issue exists for apps using spring-cloud-stream, and there is a plan to fix that. My app does not use spring-cloud-stream, however; it uses spring-kafka.

The solution was to follow the guidance on the spring-kafka reference to add a MicrometerConsumerListener to the consumer factory. After doing this, metrics show up as expected.

Jeremy Caney
  • 7,102
  • 69
  • 48
  • 77
  • 2
    Welcome to Stack Overflow. In the future, please be sure not to post an answer until you've actually found a solution; the answers section shouldn't be used to reiterate that you're facing the same problem. Since you edited your answer to include a solution, I've reworded it to remove your initial follow-up questions, and lead directly into your solution. – Jeremy Caney Jun 17 '20 at 20:19
  • Jeremy - thanks for the feedback. My original preference was to add a comment above, but was blocked from adding a comment because I'm a new user. Hence, I resorted to posting a question within an answer. I thought it best to take this approach rather than create an entirely new question/thread for the same issue - which at first I truly did not have an answer to -- after doing a fair amount of investigation. Thanks again! – Brent Bishop Jun 17 '20 at 20:27
  • @BrentBishop Boot 2.3 will automatically add the listeners as long as the actuator starter is present - see https://github.com/spring-projects/spring-boot/commit/d16074d8fdc457107177bca026635e4575fe0c08 - I just tested it and it worked fine for me. – Gary Russell Jun 17 '20 at 20:37
  • 1
    @GaryRussell: Thank you for testing. Is your code using the auto-configured ConsumerFactory? My app does have actuator starter present. Since I need to dynamically assign bootstrap servers, I have custom code to create the consumerFactory. I debugged through the Spring code in the commit that you shared - and observed that code to add listeners does not run, creating the need to add them in app code. Do I have this correct? – Brent Bishop Jun 18 '20 at 00:17
  • 1
    If so, this is the point that created a little confusion for me. With pre Boot 2.3.0 we just needed to add dependencies and metrics were available. To continue getting metrics with 2.3.0, code is needed to add a listener. In the end, if this is the way it is - it is a minor and reasonable change. I didn't pickup on it when reading through the doc. – Brent Bishop Jun 18 '20 at 00:17
  • Yes; Boot will only run customizers against its auto configured factories. https://github.com/spring-projects/spring-boot/blob/f47e06c4efbdc5a3f31684117309a62b29b2e882/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/kafka/KafkaAutoConfiguration.java#L82-L90 The issue came about because Micrometer deprecated its JMX MBwan scraping mechanism for metrics. So we added the listener mechanism to spring-kafka and the Boot logic to add the listeners to its auto-configured factories, but Boot can't (and shouldn't) interfere with user-defined beans. – Gary Russell Jun 18 '20 at 01:16