Skip to content

Prometheus ClassCastException while scraping (Micrometer 1.13 / SB 3.3) #5150

@knoobie

Description

@knoobie

Describe the bug
Multiple Methods annotated with @Timed (or creating a Timer by hand) with the same value to group them together throws a ClassCastException once histogram is enabled on some - but not on all.

java.lang.ClassCastException: class io.prometheus.metrics.model.snapshots.SummarySnapshot$SummaryDataPointSnapshot cannot be cast to class io.prometheus.metrics.model.snapshots.HistogramSnapshot$HistogramDataPointSnapshot (io.prometheus.metrics.model.snapshots.SummarySnapshot$SummaryDataPointSnapshot and io.prometheus.metrics.model.snapshots.HistogramSnapshot$HistogramDataPointSnapshot are in unnamed module of loader 'app')

	at io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter.writeClassicHistogramBuckets(OpenMetricsTextFormatWriter.java:125)
	at io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter.writeHistogram(OpenMetricsTextFormatWriter.java:120)
	at io.prometheus.metrics.expositionformats.OpenMetricsTextFormatWriter.write(OpenMetricsTextFormatWriter.java:72)
	at io.micrometer.prometheusmetrics.PrometheusMeterRegistry.scrape(PrometheusMeterRegistry.java:167)
	at io.micrometer.prometheusmetrics.PrometheusMeterRegistry.scrape(PrometheusMeterRegistry.java:163)
	at io.micrometer.prometheusmetrics.PrometheusMeterRegistry.scrape(PrometheusMeterRegistry.java:136)

Environment

  • Micrometer version: 1.13 (bundled in Spring Boot 3.3)
  • Micrometer registry: Prometheus

To Reproduce

Smallest example by Andy Wilkinson (wilkinsona) (don't wanna spam tag him)

package com.example;

import io.micrometer.core.instrument.Timer;
import io.micrometer.core.instrument.Timer.Sample;
import io.micrometer.prometheusmetrics.PrometheusConfig;
import io.micrometer.prometheusmetrics.PrometheusMeterRegistry;

public class Reproducer {

	public static void main(String[] args) throws InterruptedException {
		PrometheusMeterRegistry registry = new PrometheusMeterRegistry(new PrometheusConfig() {
			
			@Override
			public String get(String key) {
				return null;
			}
			
		});
		
		timed(registry, false, "one");
		timed(registry, true, "two");
		
		System.out.println(registry.scrape("application/openmetrics-text; version=1.0.0; charset=utf-8"));
	}
	
	static void timed(PrometheusMeterRegistry registry, boolean histogram, String methodName) throws InterruptedException {
		Sample sample = Timer.start(registry);
		Thread.sleep(500);
		sample.stop(Timer.builder("example").publishPercentileHistogram(histogram).tag("method-name",  methodName).register(registry));
	}

}

Example with Spring involved: spring-projects/spring-boot#40907 (comment)

Expected behavior
No exception; using Timer with and without histogram should work.

Additional context
Originally reported here: spring-projects/spring-boot#40907

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionA user question, probably better suited for StackOverflowregistry: prometheusA Prometheus Registry related issue

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions