Skip to content

Commit dc7a73a

Browse files
authored
Use exporter autoconfiguration in Spring Monitor (#41761)
1 parent ac9ee63 commit dc7a73a

File tree

4 files changed

+65
-235
lines changed

4 files changed

+65
-235
lines changed

sdk/spring/spring-cloud-azure-starter-monitor/src/main/java/com/azure/monitor/applicationinsights/spring/AzureSpringMonitorAutoConfig.java

Lines changed: 65 additions & 101 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,10 @@
66
import com.azure.core.http.HttpPipeline;
77
import com.azure.monitor.opentelemetry.exporter.AzureMonitorExporterBuilder;
88
import io.opentelemetry.instrumentation.spring.autoconfigure.OpenTelemetryAutoConfiguration;
9+
import io.opentelemetry.sdk.autoconfigure.AutoConfiguredOpenTelemetrySdkBuilder;
10+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizer;
11+
import io.opentelemetry.sdk.autoconfigure.spi.AutoConfigurationCustomizerProvider;
912
import io.opentelemetry.sdk.autoconfigure.spi.ConfigProperties;
10-
import io.opentelemetry.sdk.autoconfigure.spi.logs.ConfigurableLogRecordExporterProvider;
11-
import io.opentelemetry.sdk.autoconfigure.spi.metrics.ConfigurableMetricExporterProvider;
12-
import io.opentelemetry.sdk.autoconfigure.spi.traces.ConfigurableSpanExporterProvider;
13-
import io.opentelemetry.sdk.logs.export.LogRecordExporter;
14-
import io.opentelemetry.sdk.metrics.export.MetricExporter;
15-
import io.opentelemetry.sdk.trace.export.SpanExporter;
1613
import org.slf4j.Logger;
1714
import org.slf4j.LoggerFactory;
1815
import org.springframework.beans.factory.ObjectProvider;
@@ -22,7 +19,9 @@
2219
import org.springframework.context.annotation.Bean;
2320
import org.springframework.context.annotation.Configuration;
2421

25-
import java.util.Optional;
22+
import java.util.HashMap;
23+
import java.util.Map;
24+
import java.util.function.Function;
2625

2726
/**
2827
* Auto config for Azure Spring Monitor
@@ -34,18 +33,33 @@ public class AzureSpringMonitorAutoConfig {
3433

3534
private static final Logger LOG = LoggerFactory.getLogger(AzureSpringMonitorAutoConfig.class);
3635

37-
static final String AZURE_EXPORTER_NAME = "azure-exporter";
36+
private static final Function<ConfigProperties, Map<String, String>> OTEL_DISABLE_CONFIG = configProperties -> {
37+
Map<String, String> properties = new HashMap<>();
38+
properties.put("otel.sdk.disabled", "true");
39+
return properties;
40+
};
41+
42+
private static final Function<ConfigProperties, Map<String, String>> NO_EXPORT_CONFIG = configProperties -> {
43+
Map<String, String> properties = new HashMap<>(3);
44+
properties.put("otel.traces.exporter", "none");
45+
properties.put("otel.metrics.exporter", "none");
46+
properties.put("otel.logs.exporter", "none");
47+
return properties;
48+
};
49+
50+
private final String connectionString;
51+
private final ObjectProvider<HttpPipeline> httpPipeline;
3852

39-
private final Optional<AzureMonitorExporterBuilder> azureMonitorExporterBuilderOpt;
4053

4154
/**
4255
* Create an instance of AzureSpringMonitorConfig
4356
*
44-
* @param connectionStringSysProp connection string system property
57+
* @param connectionString connection string system property
4558
* @param httpPipeline an instance of HttpPipeline
4659
*/
47-
public AzureSpringMonitorAutoConfig(@Value("${applicationinsights.connection.string:}") String connectionStringSysProp, ObjectProvider<HttpPipeline> httpPipeline) {
48-
this.azureMonitorExporterBuilderOpt = createAzureMonitorExporterBuilder(connectionStringSysProp, httpPipeline);
60+
public AzureSpringMonitorAutoConfig(@Value("${applicationinsights.connection.string:}") String connectionString, ObjectProvider<HttpPipeline> httpPipeline) {
61+
this.connectionString = connectionString;
62+
this.httpPipeline = httpPipeline;
4963
if (!isNativeRuntimeExecution()) {
5064
LOG.warn("You are using Application Insights for Spring in a non-native GraalVM runtime environment. We recommend using the Application Insights Java agent.");
5165
}
@@ -56,105 +70,55 @@ private static boolean isNativeRuntimeExecution() {
5670
return imageCode != null;
5771
}
5872

59-
private Optional<AzureMonitorExporterBuilder> createAzureMonitorExporterBuilder(String connectionStringSysProp, ObjectProvider<HttpPipeline> httpPipeline) {
60-
Optional<String> connectionString = ConnectionStringRetriever.retrieveConnectionString(connectionStringSysProp);
61-
if (connectionString.isPresent()) {
62-
AzureMonitorExporterBuilder azureMonitorExporterBuilder = new AzureMonitorExporterBuilder().connectionString(connectionString.get());
63-
HttpPipeline providedHttpPipeline = httpPipeline.getIfAvailable();
64-
if (providedHttpPipeline != null) {
65-
azureMonitorExporterBuilder = azureMonitorExporterBuilder.httpPipeline(providedHttpPipeline);
66-
}
67-
return Optional.of(azureMonitorExporterBuilder);
68-
} else {
69-
LOG.warn("Unable to find the Application Insights connection string. The telemetry data won't be sent to Azure.");
73+
private static boolean applicationInsightsAgentIsAttached() {
74+
try {
75+
Class.forName("com.microsoft.applicationinsights.agent.Agent", false, null);
76+
return true;
77+
} catch (ClassNotFoundException e) {
78+
return false;
7079
}
71-
return Optional.empty();
7280
}
7381

74-
/**
75-
* Declare a ConfigurableMetricExporterProvider bean
76-
*
77-
* @return ConfigurableMetricExporterProvider
78-
*/
7982
@Bean
80-
ConfigurableMetricExporterProvider otlpMetricExporterProvider() {
81-
MetricExporter metricExporter = createMetricExporter();
82-
return new ConfigurableMetricExporterProvider() {
83+
AutoConfigurationCustomizerProvider autoConfigurationCustomizerProvider() {
84+
return new AutoConfigurationCustomizerProvider() {
8385
@Override
84-
public MetricExporter createExporter(ConfigProperties configProperties) {
85-
return metricExporter;
86+
public void customize(AutoConfigurationCustomizer autoConfigurationCustomizer) {
87+
88+
if (!isNativeRuntimeExecution() && applicationInsightsAgentIsAttached()) {
89+
LOG.warn("The spring-cloud-azure-starter-monitor Spring starter is disabled because the Application Insights Java agent is enabled."
90+
+ " You can remove this message by adding the otel.sdk.disabled=true property.");
91+
autoConfigurationCustomizer.addPropertiesCustomizer(OTEL_DISABLE_CONFIG);
92+
return;
93+
}
94+
95+
if (connectionString == null || connectionString.isEmpty()) {
96+
LOG.warn("Unable to find the Application Insights connection string. The telemetry data won't be sent to Azure.");
97+
// If the user does not provide a connection, we disable the export and leave the instrumentation enabled to spot potential failures from
98+
// the instrumentation, in the customer automatic tests for example.
99+
autoConfigurationCustomizer.addPropertiesCustomizer(NO_EXPORT_CONFIG);
100+
return;
101+
}
102+
103+
if (!connectionString.contains("InstrumentationKey=")) {
104+
throw new WrongConnectionStringException();
105+
}
106+
107+
if (autoConfigurationCustomizer instanceof AutoConfiguredOpenTelemetrySdkBuilder) {
108+
AutoConfiguredOpenTelemetrySdkBuilder sdkBuilder = (AutoConfiguredOpenTelemetrySdkBuilder) autoConfigurationCustomizer;
109+
110+
AzureMonitorExporterBuilder azureMonitorExporterBuilder = new AzureMonitorExporterBuilder().connectionString(connectionString);
111+
HttpPipeline providedHttpPipeline = httpPipeline.getIfAvailable();
112+
if (providedHttpPipeline != null) {
113+
azureMonitorExporterBuilder = azureMonitorExporterBuilder.httpPipeline(providedHttpPipeline);
114+
}
115+
azureMonitorExporterBuilder.install(sdkBuilder);
116+
}
86117
}
87-
@Override
88-
public String getName() {
89-
return AZURE_EXPORTER_NAME;
90-
}
91-
};
92-
93-
}
94118

95-
private MetricExporter createMetricExporter() {
96-
if (!azureMonitorExporterBuilderOpt.isPresent()) {
97-
return null;
98-
}
99-
return azureMonitorExporterBuilderOpt.get().buildMetricExporter();
100-
}
101-
102-
/**
103-
* Declare a ConfigurableSpanExporterProvider bean
104-
*
105-
* @return ConfigurableSpanExporterProvider
106-
*/
107-
@Bean
108-
ConfigurableSpanExporterProvider otlpSpanExporterProvider() {
109-
SpanExporter spanExporter = createSpanExporter();
110-
return new ConfigurableSpanExporterProvider() {
111-
@Override
112-
public SpanExporter createExporter(ConfigProperties configProperties) {
113-
return spanExporter;
114-
}
115-
@Override
116-
public String getName() {
117-
return AZURE_EXPORTER_NAME;
118-
}
119-
};
120-
}
121-
122-
private SpanExporter createSpanExporter() {
123-
if (!azureMonitorExporterBuilderOpt.isPresent()) {
124-
return null;
125-
}
126-
return azureMonitorExporterBuilderOpt.get().buildTraceExporter();
127-
}
128-
129-
130-
/**
131-
* Declare a ConfigurableLogRecordExporterProvider bean
132-
*
133-
* @return ConfigurableLogRecordExporterProvider
134-
*/
135-
@Bean
136-
ConfigurableLogRecordExporterProvider otlpLogRecordExporterProvider() {
137-
LogRecordExporter logRecordExporter = createLogRecordExporter();
138-
return new ConfigurableLogRecordExporterProvider() {
139-
@Override
140-
public LogRecordExporter createExporter(ConfigProperties configProperties) {
141-
return logRecordExporter;
142-
}
143-
@Override
144-
public String getName() {
145-
return AZURE_EXPORTER_NAME;
146-
}
147119
};
148120
}
149121

150-
private LogRecordExporter createLogRecordExporter() {
151-
if (!azureMonitorExporterBuilderOpt.isPresent()) {
152-
return null;
153-
}
154-
return azureMonitorExporterBuilderOpt.get().buildLogRecordExporter();
155-
}
156-
157-
158122
/**
159123
* Declare OpenTelemetryVersionCheckRunner bean to check the OpenTelemetry version
160124
*

sdk/spring/spring-cloud-azure-starter-monitor/src/main/java/com/azure/monitor/applicationinsights/spring/ConnectionStringRetriever.java

Lines changed: 0 additions & 38 deletions
This file was deleted.

sdk/spring/spring-cloud-azure-starter-monitor/src/main/java/com/azure/monitor/applicationinsights/spring/PropertiesPostProcessor.java

Lines changed: 0 additions & 94 deletions
This file was deleted.

sdk/spring/spring-cloud-azure-starter-monitor/src/main/resources/META-INF/spring.factories

Lines changed: 0 additions & 2 deletions
This file was deleted.

0 commit comments

Comments
 (0)