Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@

public final class ActuatorInstrumentation implements TypeInstrumentation {

private static final String SPRING_BOOT_3_METRICS_AUTO_CONFIGURATION =
"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration";
private static final String SPRING_BOOT_4_METRICS_AUTO_CONFIGURATION =
"org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration";

@Override
public ElementMatcher<TypeDescription> typeMatcher() {
return named("org.springframework.boot.autoconfigure.AutoConfigurationImportSelector");
Expand All @@ -36,8 +41,9 @@ public static class GetCandidateConfigurationsAdvice {

@Advice.OnMethodExit(suppress = Throwable.class)
public static void onExit(@Advice.Return(readOnly = false) List<String> configurations) {
if (configurations.contains(
"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration")) {
if ((configurations.contains(SPRING_BOOT_3_METRICS_AUTO_CONFIGURATION)
|| configurations.contains(SPRING_BOOT_4_METRICS_AUTO_CONFIGURATION))
&& !configurations.contains(AzureMonitorAutoConfiguration.class.getName())) {
List<String> configs = new ArrayList<>(configurations.size() + 1);
configs.addAll(configurations);
// using class reference here so that muzzle will consider it a dependency of this advice
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,6 @@
package io.opentelemetry.javaagent.instrumentation.micrometer.ai;

import io.micrometer.core.instrument.Clock;
import org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration;
import org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration;
import org.springframework.boot.autoconfigure.AutoConfigureAfter;
import org.springframework.boot.autoconfigure.AutoConfigureBefore;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
Expand All @@ -15,12 +12,22 @@
import org.springframework.context.annotation.Configuration;

@Configuration(proxyBeanMethods = false)
@AutoConfigureBefore(CompositeMeterRegistryAutoConfiguration.class)
@AutoConfigureBefore(
name = {
"org.springframework.boot.actuate.autoconfigure.metrics.CompositeMeterRegistryAutoConfiguration",
"org.springframework.boot.micrometer.metrics.autoconfigure.CompositeMeterRegistryAutoConfiguration"
})
// configure after SimpleMeterRegistry is registered, otherwise SimpleMeterRegistry will be
// suppressed by the existence of the MeterRegistry created here, which can alter the spring boot
// actuator scraping endpoint behavior (since AzureMonitorMeterRegistry is a delta
// StepMeterRegistry, while SimpleMeterRegistry is cumulative)
@AutoConfigureAfter({MetricsAutoConfiguration.class, SimpleMetricsExportAutoConfiguration.class})
@AutoConfigureAfter(
name = {
"org.springframework.boot.actuate.autoconfigure.metrics.MetricsAutoConfiguration",
"org.springframework.boot.actuate.autoconfigure.metrics.export.simple.SimpleMetricsExportAutoConfiguration",
"org.springframework.boot.micrometer.metrics.autoconfigure.MetricsAutoConfiguration",
"org.springframework.boot.micrometer.metrics.autoconfigure.export.simple.SimpleMetricsExportAutoConfiguration"
})
@ConditionalOnBean(Clock.class)
@ConditionalOnClass(AzureMonitorMeterRegistry.class)
public class AzureMonitorAutoConfiguration {
Expand Down
1 change: 1 addition & 0 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ include(":smoke-tests:framework")

// TODO (trask) consider un-hiding these and running smoke tests against the latest versions
hideFromDependabot(":smoke-tests:apps:ActuatorMetrics")
hideFromDependabot(":smoke-tests:apps:ActuatorMetricsSpringBoot4")
hideFromDependabot(":smoke-tests:apps:AutoPerfCounters")
hideFromDependabot(":smoke-tests:apps:AzureSdk")
hideFromDependabot(":smoke-tests:apps:AzureFunctions")
Expand Down
24 changes: 24 additions & 0 deletions smoke-tests/apps/ActuatorMetricsSpringBoot4/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import com.github.jengelman.gradle.plugins.shadow.tasks.ShadowJar

plugins {
id("ai.smoke-test-jar")
}

configurations.configureEach {
resolutionStrategy.force(
"ch.qos.logback:logback-classic:1.5.21",
"ch.qos.logback:logback-core:1.5.21",
"org.slf4j:slf4j-api:2.0.17"
)
}

dependencies {
implementation("org.springframework.boot:spring-boot-starter-web:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-actuator:4.0.0")
implementation("org.springframework.boot:spring-boot-starter-micrometer-metrics:4.0.0")
}

tasks.named<ShadowJar>("shadowJar") {
append("META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports")
append("META-INF/spring/org.springframework.boot.actuate.autoconfigure.web.ManagementContextConfiguration.imports")
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.smoketestapp;

import io.micrometer.core.instrument.MeterRegistry;
import io.micrometer.core.instrument.Metrics;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.tomcat.servlet.TomcatServletWebServerFactory;
import org.springframework.boot.web.server.servlet.ServletWebServerFactory;
import org.springframework.context.annotation.Bean;

@SpringBootApplication
public class SpringBootApp {

@Bean
public ServletWebServerFactory servletWebServerFactory() {
return new TomcatServletWebServerFactory();
}

@Bean
public MeterRegistry meterRegistry() {
return Metrics.globalRegistry;
}

public static void main(String[] args) {
SpringApplication.run(SpringBootApp.class, args);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.smoketestapp;

import io.micrometer.core.instrument.Counter;
import io.micrometer.core.instrument.MeterRegistry;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class TestController {

private final Counter counter;

public TestController(MeterRegistry meterRegistry) {
this.counter =
Counter.builder("demo.requests.total").tag("endpoint", "test").register(meterRegistry);
}

@GetMapping("/")
public String root() {
return "OK";
}

@GetMapping("/test")
public String test() {
counter.increment();
return "OK!";
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT License.

package com.microsoft.applicationinsights.smoketest;

import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_21;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_21_OPENJ9;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_25;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_25_OPENJ9;
import static org.assertj.core.api.Assertions.assertThat;

import com.microsoft.applicationinsights.smoketest.schemav2.Data;
import com.microsoft.applicationinsights.smoketest.schemav2.DataPoint;
import com.microsoft.applicationinsights.smoketest.schemav2.Envelope;
import com.microsoft.applicationinsights.smoketest.schemav2.MetricData;
import java.util.List;
import java.util.concurrent.TimeUnit;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.RegisterExtension;

@UseAgent
abstract class ActuatorMetricsSpringBoot4Test {

@RegisterExtension static final SmokeTestExtension testing = SmokeTestExtension.create();

@Test
@TargetUri("/test")
void shouldCaptureCustomMetricRegisteredOnSpringMeterRegistry() throws Exception {
testing.getTelemetry(0);

List<Envelope> metricItems =
testing.mockedIngestion.waitForItems(
ActuatorMetricsSpringBoot4Test::isTargetMetric, 1, 20, TimeUnit.SECONDS);

MetricData data = (MetricData) ((Data<?>) metricItems.get(0).getData()).getBaseData();
List<DataPoint> points = data.getMetrics();

assertThat(points)
.anySatisfy(point -> assertThat(point.getName()).isEqualTo("demo_requests_total"));
assertThat(data.getProperties()).containsEntry("endpoint", "test");
}

static boolean isTargetMetric(Envelope input) {
if (!input.getData().getBaseType().equals("MetricData")) {
return false;
}
MetricData data = (MetricData) ((Data<?>) input.getData()).getBaseData();
if (!"test".equals(data.getProperties().get("endpoint"))) {
return false;
}
for (DataPoint point : data.getMetrics()) {
if ("demo_requests_total".equals(point.getName()) && point.getValue() >= 1) {
return true;
}
}
return false;
}

@Environment(JAVA_21)
static class Java21Test extends ActuatorMetricsSpringBoot4Test {}

@Environment(JAVA_21_OPENJ9)
static class Java21OpenJ9Test extends ActuatorMetricsSpringBoot4Test {}

@Environment(JAVA_25)
static class Java25Test extends ActuatorMetricsSpringBoot4Test {}

@Environment(JAVA_25_OPENJ9)
static class Java25OpenJ9Test extends ActuatorMetricsSpringBoot4Test {}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"role": {
"name": "testrolename",
"instance": "testroleinstance"
},
"sampling": {
"percentage": 100
},
"metricIntervalSeconds": 5
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
<appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<root level="warn">
<appender-ref ref="CONSOLE"/>
</root>
</configuration>
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_17_OPENJ9;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_21;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_21_OPENJ9;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_25;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_25_OPENJ9;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_8;
import static com.microsoft.applicationinsights.smoketest.EnvironmentValue.JAVA_8_OPENJ9;
import static org.assertj.core.api.Assertions.assertThat;
Expand Down Expand Up @@ -99,4 +101,10 @@ static class Java21Test extends MicrometerTest {}

@Environment(JAVA_21_OPENJ9)
static class Java21OpenJ9Test extends MicrometerTest {}

@Environment(JAVA_25)
static class Java25Test extends MicrometerTest {}

@Environment(JAVA_25_OPENJ9)
static class Java25OpenJ9Test extends MicrometerTest {}
}