fix micrometer bridge auto configuration annotation (#13083)

Co-authored-by: Trask Stalnaker <trask.stalnaker@gmail.com>
This commit is contained in:
Gregor Zeitlinger 2025-02-12 15:37:09 +01:00 committed by GitHub
parent 76d59198d0
commit 15358d6a3d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 49 additions and 5 deletions

View File

@ -15,6 +15,7 @@ muzzle {
dependencies {
library("org.springframework.boot:spring-boot-actuator-autoconfigure:2.0.0.RELEASE")
library("io.micrometer:micrometer-core:1.5.0")
testLibrary("io.micrometer:micrometer-registry-prometheus:1.0.1")
implementation(project(":instrumentation:micrometer:micrometer-1.5:javaagent"))

View File

@ -7,7 +7,15 @@ package io.opentelemetry.javaagent.instrumentation.spring.actuator.v2_0;
import io.micrometer.core.instrument.Clock;
import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
import io.opentelemetry.javaagent.instrumentation.micrometer.v1_5.MicrometerSingletons;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@ -32,4 +40,32 @@ public class OpenTelemetryMeterRegistryAutoConfiguration {
public MeterRegistry otelMeterRegistry() {
return MicrometerSingletons.meterRegistry();
}
@Bean
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
static BeanPostProcessor postProcessCompositeMeterRegistry() {
return new BeanPostProcessor() {
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) {
if (bean instanceof CompositeMeterRegistry) {
CompositeMeterRegistry original = (CompositeMeterRegistry) bean;
List<MeterRegistry> list = new ArrayList<>(original.getRegistries());
// sort otel registry last since it doesn't support reading metric values
// and the actuator endpoint reads metrics from the first registry
list.sort(
Comparator.comparingInt(
value -> value == MicrometerSingletons.meterRegistry() ? 1 : 0));
Set<MeterRegistry> registries = new LinkedHashSet<>(list);
return new CompositeMeterRegistry(
original.config().clock(), Collections.singletonList(original)) {
@Override
public Set<MeterRegistry> getRegistries() {
return registries;
}
};
}
return bean;
}
};
}
}

View File

@ -15,6 +15,8 @@ import io.opentelemetry.instrumentation.testing.internal.AutoCleanupExtension;
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
import io.opentelemetry.javaagent.instrumentation.spring.actuator.v2_0.SpringApp.TestBean;
import java.util.ArrayList;
import java.util.Set;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;
import org.springframework.boot.SpringApplication;
@ -57,9 +59,12 @@ class ActuatorTest {
"value"))))));
MeterRegistry meterRegistry = context.getBean(MeterRegistry.class);
assertThat(meterRegistry).isNotNull().isInstanceOf(CompositeMeterRegistry.class);
assertThat(((CompositeMeterRegistry) meterRegistry).getRegistries())
.anyMatch(r -> r.getClass().getSimpleName().equals("OpenTelemetryMeterRegistry"))
.anyMatch(r -> r.getClass().getSimpleName().equals("SimpleMeterRegistry"));
assertThat(meterRegistry).isInstanceOf(CompositeMeterRegistry.class);
Set<MeterRegistry> registries = ((CompositeMeterRegistry) meterRegistry).getRegistries();
ArrayList<MeterRegistry> list = new ArrayList<>(registries);
String last = list.get(list.size() - 1).getClass().getSimpleName();
assertThat(last).isEqualTo("OpenTelemetryMeterRegistry");
}
}

View File

@ -10,7 +10,9 @@ import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
@SpringBootApplication
@SpringBootApplication(
excludeName =
"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusSimpleclientMetricsExportAutoConfiguration")
public class SpringApp {
@Bean