16
16
17
17
package org .springframework .boot .actuate .autoconfigure .metrics ;
18
18
19
- import java .lang .reflect .Method ;
20
- import java .util .Collection ;
19
+ import java .util .ArrayList ;
21
20
import java .util .List ;
22
21
23
22
import io .micrometer .core .instrument .observation .MeterObservationHandler ;
23
+ import io .micrometer .core .instrument .observation .Observation ;
24
24
import io .micrometer .core .instrument .observation .Observation .Context ;
25
25
import io .micrometer .core .instrument .observation .ObservationHandler ;
26
26
import io .micrometer .core .instrument .observation .ObservationHandler .AllMatchingCompositeObservationHandler ;
27
- import io .micrometer .core .instrument .observation .ObservationHandler .CompositeObservationHandler ;
28
27
import io .micrometer .core .instrument .observation .ObservationHandler .FirstMatchingCompositeObservationHandler ;
29
28
import io .micrometer .core .instrument .observation .ObservationRegistry ;
30
- import io .micrometer .core .instrument .observation .ObservationRegistry .ObservationConfig ;
31
- import io .micrometer .core .instrument .observation .TimerObservationHandler ;
32
29
import io .micrometer .tracing .Tracer ;
33
- import io .micrometer .tracing .handler .DefaultTracingObservationHandler ;
30
+ import io .micrometer .tracing .handler .TracingObservationHandler ;
34
31
import org .junit .jupiter .api .Test ;
32
+ import org .mockito .Answers ;
35
33
import org .mockito .Mockito ;
36
34
37
35
import org .springframework .boot .actuate .autoconfigure .metrics .test .MetricsRun ;
38
36
import org .springframework .boot .autoconfigure .AutoConfigurations ;
39
37
import org .springframework .boot .test .context .runner .ApplicationContextRunner ;
40
38
import org .springframework .context .annotation .Bean ;
41
39
import org .springframework .context .annotation .Configuration ;
40
+ import org .springframework .context .annotation .Import ;
42
41
import org .springframework .core .annotation .Order ;
43
- import org .springframework .util .ReflectionUtils ;
44
42
45
43
import static org .assertj .core .api .Assertions .assertThat ;
46
44
@@ -55,55 +53,51 @@ class TracingAutoConfigurationTests {
55
53
.withConfiguration (AutoConfigurations .of (TracingAutoConfiguration .class ));
56
54
57
55
@ Test
58
- @ SuppressWarnings ("rawtypes" )
59
56
void autoConfiguresObservationHandler () {
60
57
this .contextRunner .withUserConfiguration (ObservationHandlers .class ).run ((context ) -> {
61
58
ObservationRegistry observationRegistry = context .getBean (ObservationRegistry .class );
62
- List <ObservationHandler <?>> handlers = getObservationHandlers (observationRegistry );
63
- assertThat (handlers ).hasSize (6 );
64
- assertThat (handlers .get (0 )).isInstanceOf (TimerObservationHandler .class );
65
- assertThat (handlers .get (1 )).isInstanceOf (CustomObservationHandler .class );
66
- assertThat (handlers .get (2 )).isInstanceOf (FirstMatchingCompositeObservationHandler .class );
67
- assertThat (handlers .get (3 )).isInstanceOf (AllMatchingCompositeObservationHandler .class );
68
- // CustomMeterObservationHandlers get wrapped into a
69
- // FirstMatchingCompositeObservationHandler
70
- assertThat (handlers .get (4 )).isInstanceOf (FirstMatchingCompositeObservationHandler .class );
71
- List <ObservationHandler > containedHandlers = ((CompositeObservationHandler ) handlers .get (4 )).getHandlers ();
72
- assertThat (containedHandlers ).hasSize (2 );
73
- assertThat (containedHandlers .get (0 )).isInstanceOf (CustomMeterObservationHandler .class );
74
- assertThat (containedHandlers .get (1 )).isInstanceOf (CustomMeterObservationHandler .class );
75
- assertThat (handlers .get (4 )).isInstanceOf (FirstMatchingCompositeObservationHandler .class );
76
- // DefaultTracingObservationHandler get wrapped into a
77
- // FirstMatchingCompositeObservationHandler
78
- containedHandlers = ((CompositeObservationHandler ) handlers .get (5 )).getHandlers ();
79
- assertThat (containedHandlers ).hasSize (2 );
80
- assertThat (containedHandlers .get (0 )).isInstanceOf (DefaultTracingObservationHandler .class );
81
- assertThat (containedHandlers .get (1 )).isInstanceOf (DefaultTracingObservationHandler .class );
82
-
59
+ List <ObservationHandler <?>> handlers = context .getBean (CalledHandlers .class ).getCalledHandlers ();
60
+ Observation .start ("test-observation" , observationRegistry );
61
+ assertThat (handlers ).hasSize (3 );
62
+ // Regular handlers are registered first
63
+ assertThat (handlers .get (0 )).isInstanceOf (CustomObservationHandler .class );
64
+ // Multiple MeterObservationHandler are wrapped in
65
+ // FirstMatchingCompositeObservationHandler, which calls only the first one
66
+ assertThat (handlers .get (1 )).isInstanceOf (CustomMeterObservationHandler .class );
67
+ assertThat (((CustomMeterObservationHandler ) handlers .get (1 )).getName ())
68
+ .isEqualTo ("customMeterObservationHandler1" );
69
+ // Multiple TracingObservationHandler are wrapped in
70
+ // FirstMatchingCompositeObservationHandler, which calls only the first one
71
+ assertThat (handlers .get (2 )).isInstanceOf (CustomTracingObservationHandler .class );
72
+ assertThat (((CustomTracingObservationHandler ) handlers .get (2 )).getName ())
73
+ .isEqualTo ("customTracingHandler1" );
83
74
});
84
75
}
85
76
86
- @ SuppressWarnings ("unchecked" )
87
- private List <ObservationHandler <?>> getObservationHandlers (ObservationRegistry registry ) {
88
- Method method = ReflectionUtils .findMethod (ObservationConfig .class , "getObservationHandlers" );
89
- ReflectionUtils .makeAccessible (method );
90
- return List .copyOf (
91
- (Collection <ObservationHandler <?>>) ReflectionUtils .invokeMethod (method , registry .observationConfig ()));
77
+ @ Configuration (proxyBeanMethods = false )
78
+ static class CalledHandlersConfiguration {
79
+
80
+ @ Bean
81
+ CalledHandlers calledHandlers () {
82
+ return new CalledHandlers ();
83
+ }
84
+
92
85
}
93
86
94
87
@ Configuration (proxyBeanMethods = false )
88
+ @ Import (CalledHandlersConfiguration .class )
95
89
static class ObservationHandlers {
96
90
97
91
@ Bean
98
92
@ Order (6 )
99
- DefaultTracingObservationHandler customTracingHandler2 () {
100
- return new DefaultTracingObservationHandler ( Mockito . mock ( Tracer . class ) );
93
+ CustomTracingObservationHandler customTracingHandler2 (CalledHandlers calledHandlers ) {
94
+ return new CustomTracingObservationHandler ( "customTracingHandler2" , calledHandlers );
101
95
}
102
96
103
97
@ Bean
104
98
@ Order (5 )
105
- DefaultTracingObservationHandler customTracingHandler1 () {
106
- return new DefaultTracingObservationHandler ( Mockito . mock ( Tracer . class ) );
99
+ CustomTracingObservationHandler customTracingHandler1 (CalledHandlers calledHandlers ) {
100
+ return new CustomTracingObservationHandler ( "customTracingHandler1" , calledHandlers );
107
101
}
108
102
109
103
@ Bean
@@ -120,25 +114,84 @@ FirstMatchingCompositeObservationHandler customFirstMatchingCompositeObservation
120
114
121
115
@ Bean
122
116
@ Order (2 )
123
- ObservationHandler <Context > customObservationHandler () {
124
- return new CustomObservationHandler ();
117
+ ObservationHandler <Context > customObservationHandler (CalledHandlers calledHandlers ) {
118
+ return new CustomObservationHandler (calledHandlers );
125
119
}
126
120
127
121
@ Bean
128
122
@ Order (1 )
129
- MeterObservationHandler <Context > customMeterObservationHandler2 () {
130
- return new CustomMeterObservationHandler ();
123
+ MeterObservationHandler <Context > customMeterObservationHandler2 (CalledHandlers calledHandlers ) {
124
+ return new CustomMeterObservationHandler ("customMeterObservationHandler2" , calledHandlers );
131
125
}
132
126
133
127
@ Bean
134
128
@ Order (0 )
135
- MeterObservationHandler <Context > customMeterObservationHandler1 () {
136
- return new CustomMeterObservationHandler ();
129
+ MeterObservationHandler <Context > customMeterObservationHandler1 (CalledHandlers calledHandlers ) {
130
+ return new CustomMeterObservationHandler ("customMeterObservationHandler1" , calledHandlers );
131
+ }
132
+
133
+ }
134
+
135
+ private static class CalledHandlers {
136
+
137
+ private final List <ObservationHandler <?>> calledHandlers = new ArrayList <>();
138
+
139
+ void onCalled (ObservationHandler <?> handler ) {
140
+ this .calledHandlers .add (handler );
141
+ }
142
+
143
+ List <ObservationHandler <?>> getCalledHandlers () {
144
+ return this .calledHandlers ;
145
+ }
146
+
147
+ }
148
+
149
+ private static class CustomTracingObservationHandler implements TracingObservationHandler <Context > {
150
+
151
+ private final Tracer tracer = Mockito .mock (Tracer .class , Answers .RETURNS_MOCKS );
152
+
153
+ private final String name ;
154
+
155
+ private final CalledHandlers calledHandlers ;
156
+
157
+ CustomTracingObservationHandler (String name , CalledHandlers calledHandlers ) {
158
+ this .name = name ;
159
+ this .calledHandlers = calledHandlers ;
160
+ }
161
+
162
+ String getName () {
163
+ return this .name ;
164
+ }
165
+
166
+ @ Override
167
+ public Tracer getTracer () {
168
+ return this .tracer ;
169
+ }
170
+
171
+ @ Override
172
+ public void onStart (Context context ) {
173
+ this .calledHandlers .onCalled (this );
174
+ }
175
+
176
+ @ Override
177
+ public boolean supportsContext (Context context ) {
178
+ return true ;
137
179
}
138
180
139
181
}
140
182
141
- static class CustomObservationHandler implements ObservationHandler <Context > {
183
+ private static class CustomObservationHandler implements ObservationHandler <Context > {
184
+
185
+ private final CalledHandlers calledHandlers ;
186
+
187
+ CustomObservationHandler (CalledHandlers calledHandlers ) {
188
+ this .calledHandlers = calledHandlers ;
189
+ }
190
+
191
+ @ Override
192
+ public void onStart (Context context ) {
193
+ this .calledHandlers .onCalled (this );
194
+ }
142
195
143
196
@ Override
144
197
public boolean supportsContext (Context context ) {
@@ -147,7 +200,25 @@ public boolean supportsContext(Context context) {
147
200
148
201
}
149
202
150
- static class CustomMeterObservationHandler implements MeterObservationHandler <Context > {
203
+ private static class CustomMeterObservationHandler implements MeterObservationHandler <Context > {
204
+
205
+ private final CalledHandlers calledHandlers ;
206
+
207
+ private final String name ;
208
+
209
+ CustomMeterObservationHandler (String name , CalledHandlers calledHandlers ) {
210
+ this .name = name ;
211
+ this .calledHandlers = calledHandlers ;
212
+ }
213
+
214
+ String getName () {
215
+ return this .name ;
216
+ }
217
+
218
+ @ Override
219
+ public void onStart (Context context ) {
220
+ this .calledHandlers .onCalled (this );
221
+ }
151
222
152
223
@ Override
153
224
public boolean supportsContext (Context context ) {
0 commit comments