Skip to content

Commit 15358d6

Browse files
zeitlingertrask
andauthored
fix micrometer bridge auto configuration annotation (#13083)
Co-authored-by: Trask Stalnaker <[email protected]>
1 parent 76d5919 commit 15358d6

File tree

4 files changed

+49
-5
lines changed

4 files changed

+49
-5
lines changed

instrumentation/spring/spring-boot-actuator-autoconfigure-2.0/javaagent/build.gradle.kts

+1
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@ muzzle {
1515
dependencies {
1616
library("org.springframework.boot:spring-boot-actuator-autoconfigure:2.0.0.RELEASE")
1717
library("io.micrometer:micrometer-core:1.5.0")
18+
testLibrary("io.micrometer:micrometer-registry-prometheus:1.0.1")
1819

1920
implementation(project(":instrumentation:micrometer:micrometer-1.5:javaagent"))
2021

instrumentation/spring/spring-boot-actuator-autoconfigure-2.0/javaagent/src/main/java/io/opentelemetry/javaagent/instrumentation/spring/actuator/v2_0/OpenTelemetryMeterRegistryAutoConfiguration.java

+36
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,15 @@
77

88
import io.micrometer.core.instrument.Clock;
99
import io.micrometer.core.instrument.MeterRegistry;
10+
import io.micrometer.core.instrument.composite.CompositeMeterRegistry;
1011
import io.opentelemetry.javaagent.instrumentation.micrometer.v1_5.MicrometerSingletons;
12+
import java.util.ArrayList;
13+
import java.util.Collections;
14+
import java.util.Comparator;
15+
import java.util.LinkedHashSet;
16+
import java.util.List;
17+
import java.util.Set;
18+
import org.springframework.beans.factory.config.BeanPostProcessor;
1119
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
1220
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
1321
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
@@ -32,4 +40,32 @@ public class OpenTelemetryMeterRegistryAutoConfiguration {
3240
public MeterRegistry otelMeterRegistry() {
3341
return MicrometerSingletons.meterRegistry();
3442
}
43+
44+
@Bean
45+
// static to avoid "is not eligible for getting processed by all BeanPostProcessors" warning
46+
static BeanPostProcessor postProcessCompositeMeterRegistry() {
47+
return new BeanPostProcessor() {
48+
@Override
49+
public Object postProcessAfterInitialization(Object bean, String beanName) {
50+
if (bean instanceof CompositeMeterRegistry) {
51+
CompositeMeterRegistry original = (CompositeMeterRegistry) bean;
52+
List<MeterRegistry> list = new ArrayList<>(original.getRegistries());
53+
// sort otel registry last since it doesn't support reading metric values
54+
// and the actuator endpoint reads metrics from the first registry
55+
list.sort(
56+
Comparator.comparingInt(
57+
value -> value == MicrometerSingletons.meterRegistry() ? 1 : 0));
58+
Set<MeterRegistry> registries = new LinkedHashSet<>(list);
59+
return new CompositeMeterRegistry(
60+
original.config().clock(), Collections.singletonList(original)) {
61+
@Override
62+
public Set<MeterRegistry> getRegistries() {
63+
return registries;
64+
}
65+
};
66+
}
67+
return bean;
68+
}
69+
};
70+
}
3571
}

instrumentation/spring/spring-boot-actuator-autoconfigure-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/actuator/v2_0/ActuatorTest.java

+9-4
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,8 @@
1515
import io.opentelemetry.instrumentation.testing.junit.AgentInstrumentationExtension;
1616
import io.opentelemetry.instrumentation.testing.junit.InstrumentationExtension;
1717
import io.opentelemetry.javaagent.instrumentation.spring.actuator.v2_0.SpringApp.TestBean;
18+
import java.util.ArrayList;
19+
import java.util.Set;
1820
import org.junit.jupiter.api.Test;
1921
import org.junit.jupiter.api.extension.RegisterExtension;
2022
import org.springframework.boot.SpringApplication;
@@ -57,9 +59,12 @@ void shouldInjectOtelMeterRegistry() {
5759
"value"))))));
5860

5961
MeterRegistry meterRegistry = context.getBean(MeterRegistry.class);
60-
assertThat(meterRegistry).isNotNull().isInstanceOf(CompositeMeterRegistry.class);
61-
assertThat(((CompositeMeterRegistry) meterRegistry).getRegistries())
62-
.anyMatch(r -> r.getClass().getSimpleName().equals("OpenTelemetryMeterRegistry"))
63-
.anyMatch(r -> r.getClass().getSimpleName().equals("SimpleMeterRegistry"));
62+
assertThat(meterRegistry).isInstanceOf(CompositeMeterRegistry.class);
63+
64+
Set<MeterRegistry> registries = ((CompositeMeterRegistry) meterRegistry).getRegistries();
65+
ArrayList<MeterRegistry> list = new ArrayList<>(registries);
66+
67+
String last = list.get(list.size() - 1).getClass().getSimpleName();
68+
assertThat(last).isEqualTo("OpenTelemetryMeterRegistry");
6469
}
6570
}

instrumentation/spring/spring-boot-actuator-autoconfigure-2.0/javaagent/src/test/java/io/opentelemetry/javaagent/instrumentation/spring/actuator/v2_0/SpringApp.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
import org.springframework.boot.autoconfigure.SpringBootApplication;
1111
import org.springframework.context.annotation.Bean;
1212

13-
@SpringBootApplication
13+
@SpringBootApplication(
14+
excludeName =
15+
"org.springframework.boot.actuate.autoconfigure.metrics.export.prometheus.PrometheusSimpleclientMetricsExportAutoConfiguration")
1416
public class SpringApp {
1517

1618
@Bean

0 commit comments

Comments
 (0)