23
23
import io .micrometer .tracing .SamplerFunction ;
24
24
import io .micrometer .tracing .otel .bridge .DefaultHttpClientAttributesGetter ;
25
25
import io .micrometer .tracing .otel .bridge .DefaultHttpServerAttributesExtractor ;
26
+ import io .micrometer .tracing .otel .bridge .EventListener ;
27
+ import io .micrometer .tracing .otel .bridge .EventPublishingContextWrapper ;
26
28
import io .micrometer .tracing .otel .bridge .OtelBaggageManager ;
27
29
import io .micrometer .tracing .otel .bridge .OtelCurrentTraceContext ;
28
30
import io .micrometer .tracing .otel .bridge .OtelHttpClientHandler ;
29
31
import io .micrometer .tracing .otel .bridge .OtelHttpServerHandler ;
32
+ import io .micrometer .tracing .otel .bridge .OtelPropagator ;
30
33
import io .micrometer .tracing .otel .bridge .OtelTracer ;
31
34
import io .micrometer .tracing .otel .bridge .OtelTracer .EventPublisher ;
35
+ import io .micrometer .tracing .otel .bridge .Slf4JBaggageEventListener ;
36
+ import io .micrometer .tracing .otel .bridge .Slf4JEventListener ;
37
+ import io .micrometer .tracing .otel .propagation .BaggageTextMapPropagator ;
32
38
import io .opentelemetry .api .OpenTelemetry ;
39
+ import io .opentelemetry .api .baggage .propagation .W3CBaggagePropagator ;
33
40
import io .opentelemetry .api .common .Attributes ;
34
41
import io .opentelemetry .api .trace .Tracer ;
42
+ import io .opentelemetry .api .trace .propagation .W3CTraceContextPropagator ;
43
+ import io .opentelemetry .context .ContextStorage ;
35
44
import io .opentelemetry .context .propagation .ContextPropagators ;
36
45
import io .opentelemetry .context .propagation .TextMapPropagator ;
46
+ import io .opentelemetry .extension .trace .propagation .B3Propagator ;
37
47
import io .opentelemetry .sdk .OpenTelemetrySdk ;
38
48
import io .opentelemetry .sdk .resources .Resource ;
39
49
import io .opentelemetry .sdk .trace .SdkTracerProvider ;
44
54
import io .opentelemetry .sdk .trace .samplers .Sampler ;
45
55
import io .opentelemetry .semconv .resource .attributes .ResourceAttributes ;
46
56
57
+ import org .springframework .beans .factory .ObjectProvider ;
47
58
import org .springframework .boot .SpringBootVersion ;
48
59
import org .springframework .boot .autoconfigure .AutoConfiguration ;
49
60
import org .springframework .boot .autoconfigure .EnableAutoConfiguration ;
50
61
import org .springframework .boot .autoconfigure .condition .ConditionalOnClass ;
51
62
import org .springframework .boot .autoconfigure .condition .ConditionalOnMissingBean ;
63
+ import org .springframework .boot .autoconfigure .condition .ConditionalOnProperty ;
52
64
import org .springframework .boot .context .properties .EnableConfigurationProperties ;
53
65
import org .springframework .context .annotation .Bean ;
66
+ import org .springframework .context .annotation .Configuration ;
54
67
import org .springframework .core .env .Environment ;
55
68
56
69
/**
@@ -70,6 +83,12 @@ public class OpenTelemetryAutoConfiguration {
70
83
*/
71
84
private static final String DEFAULT_APPLICATION_NAME = "application" ;
72
85
86
+ private final TracingProperties tracingProperties ;
87
+
88
+ OpenTelemetryAutoConfiguration (TracingProperties tracingProperties ) {
89
+ this .tracingProperties = tracingProperties ;
90
+ }
91
+
73
92
@ Bean
74
93
@ ConditionalOnMissingBean
75
94
OpenTelemetry openTelemetry (SdkTracerProvider sdkTracerProvider , ContextPropagators contextPropagators ) {
@@ -79,33 +98,31 @@ OpenTelemetry openTelemetry(SdkTracerProvider sdkTracerProvider, ContextPropagat
79
98
80
99
@ Bean
81
100
@ ConditionalOnMissingBean
82
- SdkTracerProvider otelSdkTracerProvider (Environment environment , List <SpanProcessor > spanProcessors ,
101
+ SdkTracerProvider otelSdkTracerProvider (Environment environment , ObjectProvider <SpanProcessor > spanProcessors ,
83
102
Sampler sampler ) {
84
103
String applicationName = environment .getProperty ("spring.application.name" , DEFAULT_APPLICATION_NAME );
85
104
SdkTracerProviderBuilder builder = SdkTracerProvider .builder ().setSampler (sampler )
86
105
.setResource (Resource .create (Attributes .of (ResourceAttributes .SERVICE_NAME , applicationName )));
87
- for (SpanProcessor spanProcessor : spanProcessors ) {
88
- builder .addSpanProcessor (spanProcessor );
89
- }
106
+ spanProcessors .orderedStream ().forEach (builder ::addSpanProcessor );
90
107
return builder .build ();
91
108
}
92
109
93
110
@ Bean
94
111
@ ConditionalOnMissingBean
95
- ContextPropagators otelContextPropagators (List <TextMapPropagator > textMapPropagators ) {
96
- return ContextPropagators .create (TextMapPropagator .composite (textMapPropagators ));
112
+ ContextPropagators otelContextPropagators (ObjectProvider <TextMapPropagator > textMapPropagators ) {
113
+ return ContextPropagators
114
+ .create (TextMapPropagator .composite (textMapPropagators .orderedStream ().collect (Collectors .toList ())));
97
115
}
98
116
99
117
@ Bean
100
118
@ ConditionalOnMissingBean
101
- Sampler otelSampler (TracingProperties properties ) {
102
- return Sampler .traceIdRatioBased (properties .getSampling ().getProbability ());
119
+ Sampler otelSampler () {
120
+ return Sampler .traceIdRatioBased (this . tracingProperties .getSampling ().getProbability ());
103
121
}
104
122
105
123
@ Bean
106
- @ ConditionalOnMissingBean
107
- SpanProcessor otelSpanProcessor (List <SpanExporter > spanExporter ) {
108
- return SpanProcessor .composite (spanExporter .stream ()
124
+ SpanProcessor otelSpanProcessor (ObjectProvider <SpanExporter > spanExporters ) {
125
+ return SpanProcessor .composite (spanExporters .orderedStream ()
109
126
.map ((exporter ) -> BatchSpanProcessor .builder (exporter ).build ()).collect (Collectors .toList ()));
110
127
}
111
128
@@ -119,20 +136,26 @@ Tracer otelTracer(OpenTelemetry openTelemetry) {
119
136
@ ConditionalOnMissingBean
120
137
OtelTracer micrometerOtelTracer (Tracer tracer , EventPublisher eventPublisher ,
121
138
OtelCurrentTraceContext otelCurrentTraceContext ) {
122
- return new OtelTracer (tracer , otelCurrentTraceContext , eventPublisher ,
123
- new OtelBaggageManager ( otelCurrentTraceContext , List . of (), List .of ()));
139
+ return new OtelTracer (tracer , otelCurrentTraceContext , eventPublisher , new OtelBaggageManager (
140
+ otelCurrentTraceContext , this . tracingProperties . getBaggage (). getRemoteFields (), List .of ()));
124
141
}
125
142
126
143
@ Bean
127
144
@ ConditionalOnMissingBean
128
- EventPublisher otelTracerEventPublisher () {
129
- return (event ) -> {
130
- };
145
+ OtelPropagator otelPropagator (ContextPropagators contextPropagators , Tracer tracer ) {
146
+ return new OtelPropagator (contextPropagators , tracer );
131
147
}
132
148
133
149
@ Bean
134
150
@ ConditionalOnMissingBean
135
- OtelCurrentTraceContext otelCurrentTraceContext () {
151
+ EventPublisher otelTracerEventPublisher (List <EventListener > eventListeners ) {
152
+ return new OTelEventPublisher (eventListeners );
153
+ }
154
+
155
+ @ Bean
156
+ @ ConditionalOnMissingBean
157
+ OtelCurrentTraceContext otelCurrentTraceContext (EventPublisher publisher ) {
158
+ ContextStorage .addWrapper (new EventPublishingContextWrapper (publisher ));
136
159
return new OtelCurrentTraceContext ();
137
160
}
138
161
@@ -150,4 +173,84 @@ OtelHttpServerHandler otelHttpServerHandler(OpenTelemetry openTelemetry) {
150
173
new DefaultHttpServerAttributesExtractor ());
151
174
}
152
175
176
+ @ Bean
177
+ @ ConditionalOnMissingBean
178
+ Slf4JEventListener otelSlf4JEventListener () {
179
+ return new Slf4JEventListener ();
180
+ }
181
+
182
+ @ Configuration (proxyBeanMethods = false )
183
+ @ ConditionalOnProperty (prefix = "management.tracing.baggage" , name = "enabled" , matchIfMissing = true )
184
+ static class BaggageConfiguration {
185
+
186
+ private final TracingProperties tracingProperties ;
187
+
188
+ BaggageConfiguration (TracingProperties tracingProperties ) {
189
+ this .tracingProperties = tracingProperties ;
190
+ }
191
+
192
+ @ Bean
193
+ @ ConditionalOnProperty (prefix = "management.tracing.propagation" , name = "type" , havingValue = "W3C" ,
194
+ matchIfMissing = true )
195
+ TextMapPropagator w3cTextMapPropagatorWithBaggage () {
196
+ return TextMapPropagator .composite (W3CTraceContextPropagator .getInstance (),
197
+ W3CBaggagePropagator .getInstance ());
198
+ }
199
+
200
+ @ Bean
201
+ @ ConditionalOnProperty (prefix = "management.tracing.propagation" , name = "type" , havingValue = "B3" )
202
+ TextMapPropagator b3BaggageTextMapPropagator (OtelCurrentTraceContext otelCurrentTraceContext ) {
203
+ List <String > remoteFields = this .tracingProperties .getBaggage ().getRemoteFields ();
204
+ return TextMapPropagator .composite (B3Propagator .injectingSingleHeader (), new BaggageTextMapPropagator (
205
+ remoteFields , new OtelBaggageManager (otelCurrentTraceContext , remoteFields , List .of ())));
206
+ }
207
+
208
+ @ Bean
209
+ @ ConditionalOnMissingBean
210
+ @ ConditionalOnProperty (prefix = "management.tracing.baggage.correlation" , name = "enabled" ,
211
+ matchIfMissing = true )
212
+ Slf4JBaggageEventListener otelSlf4JBaggageEventListener () {
213
+ return new Slf4JBaggageEventListener (this .tracingProperties .getBaggage ().getCorrelation ().getFields ());
214
+ }
215
+
216
+ }
217
+
218
+ @ Configuration (proxyBeanMethods = false )
219
+ @ ConditionalOnProperty (prefix = "management.tracing.baggage" , name = "enabled" , havingValue = "false" )
220
+ static class NoBaggageConfiguration {
221
+
222
+ @ Bean
223
+ @ ConditionalOnMissingBean
224
+ @ ConditionalOnProperty (prefix = "management.tracing.propagation" , name = "type" , havingValue = "B3" )
225
+ B3Propagator b3TextMapPropagator () {
226
+ return B3Propagator .injectingSingleHeader ();
227
+ }
228
+
229
+ @ Bean
230
+ @ ConditionalOnMissingBean
231
+ @ ConditionalOnProperty (prefix = "management.tracing.propagation" , name = "type" , havingValue = "W3C" ,
232
+ matchIfMissing = true )
233
+ W3CTraceContextPropagator w3cTextMapPropagatorWithoutBaggage () {
234
+ return W3CTraceContextPropagator .getInstance ();
235
+ }
236
+
237
+ }
238
+
239
+ static class OTelEventPublisher implements EventPublisher {
240
+
241
+ private final List <EventListener > listeners ;
242
+
243
+ OTelEventPublisher (List <EventListener > listeners ) {
244
+ this .listeners = listeners ;
245
+ }
246
+
247
+ @ Override
248
+ public void publishEvent (Object event ) {
249
+ for (EventListener listener : this .listeners ) {
250
+ listener .onEvent (event );
251
+ }
252
+ }
253
+
254
+ }
255
+
153
256
}
0 commit comments