6
6
import com .azure .core .http .HttpPipeline ;
7
7
import com .azure .monitor .opentelemetry .exporter .AzureMonitorExporterBuilder ;
8
8
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 ;
9
12
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 ;
16
13
import org .slf4j .Logger ;
17
14
import org .slf4j .LoggerFactory ;
18
15
import org .springframework .beans .factory .ObjectProvider ;
22
19
import org .springframework .context .annotation .Bean ;
23
20
import org .springframework .context .annotation .Configuration ;
24
21
25
- import java .util .Optional ;
22
+ import java .util .HashMap ;
23
+ import java .util .Map ;
24
+ import java .util .function .Function ;
26
25
27
26
/**
28
27
* Auto config for Azure Spring Monitor
@@ -34,18 +33,33 @@ public class AzureSpringMonitorAutoConfig {
34
33
35
34
private static final Logger LOG = LoggerFactory .getLogger (AzureSpringMonitorAutoConfig .class );
36
35
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 ;
38
52
39
- private final Optional <AzureMonitorExporterBuilder > azureMonitorExporterBuilderOpt ;
40
53
41
54
/**
42
55
* Create an instance of AzureSpringMonitorConfig
43
56
*
44
- * @param connectionStringSysProp connection string system property
57
+ * @param connectionString connection string system property
45
58
* @param httpPipeline an instance of HttpPipeline
46
59
*/
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 ;
49
63
if (!isNativeRuntimeExecution ()) {
50
64
LOG .warn ("You are using Application Insights for Spring in a non-native GraalVM runtime environment. We recommend using the Application Insights Java agent." );
51
65
}
@@ -56,105 +70,55 @@ private static boolean isNativeRuntimeExecution() {
56
70
return imageCode != null ;
57
71
}
58
72
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 ;
70
79
}
71
- return Optional .empty ();
72
80
}
73
81
74
- /**
75
- * Declare a ConfigurableMetricExporterProvider bean
76
- *
77
- * @return ConfigurableMetricExporterProvider
78
- */
79
82
@ Bean
80
- ConfigurableMetricExporterProvider otlpMetricExporterProvider () {
81
- MetricExporter metricExporter = createMetricExporter ();
82
- return new ConfigurableMetricExporterProvider () {
83
+ AutoConfigurationCustomizerProvider autoConfigurationCustomizerProvider () {
84
+ return new AutoConfigurationCustomizerProvider () {
83
85
@ 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
+ }
86
117
}
87
- @ Override
88
- public String getName () {
89
- return AZURE_EXPORTER_NAME ;
90
- }
91
- };
92
-
93
- }
94
118
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
- }
147
119
};
148
120
}
149
121
150
- private LogRecordExporter createLogRecordExporter () {
151
- if (!azureMonitorExporterBuilderOpt .isPresent ()) {
152
- return null ;
153
- }
154
- return azureMonitorExporterBuilderOpt .get ().buildLogRecordExporter ();
155
- }
156
-
157
-
158
122
/**
159
123
* Declare OpenTelemetryVersionCheckRunner bean to check the OpenTelemetry version
160
124
*
0 commit comments