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
@@ -59,51 +57,48 @@ class TracingAutoConfigurationTests {
59
57
void autoConfiguresObservationHandler () {
60
58
this .contextRunner .withUserConfiguration (ObservationHandlers .class ).run ((context ) -> {
61
59
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
-
60
+ List <ObservationHandler <?>> handlers = context .getBean (CalledHandlers .class ).getCalledHandlers ();
61
+ Observation .start ("test-observation" , observationRegistry );
62
+ assertThat (handlers ).hasSize (3 );
63
+ // Regular handlers are registered first
64
+ assertThat (handlers .get (0 )).isInstanceOf (CustomObservationHandler .class );
65
+ // Multiple MeterObservationHandler are wrapped in
66
+ // FirstMatchingCompositeObservationHandler, which calls only the first one
67
+ assertThat (handlers .get (1 )).isInstanceOf (CustomMeterObservationHandler .class );
68
+ assertThat (((CustomMeterObservationHandler ) handlers .get (1 )).getName ())
69
+ .isEqualTo ("customMeterObservationHandler1" );
70
+ // Multiple TracingObservationHandler are wrapped in
71
+ // FirstMatchingCompositeObservationHandler, which calls only the first one
72
+ assertThat (handlers .get (2 )).isInstanceOf (CustomTracingObservationHandler .class );
73
+ assertThat (((CustomTracingObservationHandler ) handlers .get (2 )).getName ())
74
+ .isEqualTo ("customTracingHandler1" );
83
75
});
84
76
}
85
77
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 ()));
78
+ @ Configuration (proxyBeanMethods = false )
79
+ static class CalledHandlersConfiguration {
80
+
81
+ @ Bean
82
+ CalledHandlers calledHandlers () {
83
+ return new CalledHandlers ();
84
+ }
85
+
92
86
}
93
87
94
88
@ Configuration (proxyBeanMethods = false )
89
+ @ Import (CalledHandlersConfiguration .class )
95
90
static class ObservationHandlers {
96
91
97
92
@ Bean
98
93
@ Order (6 )
99
- DefaultTracingObservationHandler customTracingHandler2 () {
100
- return new DefaultTracingObservationHandler ( Mockito . mock ( Tracer . class ) );
94
+ CustomTracingObservationHandler customTracingHandler2 (CalledHandlers calledHandlers ) {
95
+ return new CustomTracingObservationHandler ( "customTracingHandler2" , calledHandlers );
101
96
}
102
97
103
98
@ Bean
104
99
@ Order (5 )
105
- DefaultTracingObservationHandler customTracingHandler1 () {
106
- return new DefaultTracingObservationHandler ( Mockito . mock ( Tracer . class ) );
100
+ CustomTracingObservationHandler customTracingHandler1 (CalledHandlers calledHandlers ) {
101
+ return new CustomTracingObservationHandler ( "customTracingHandler1" , calledHandlers );
107
102
}
108
103
109
104
@ Bean
@@ -120,25 +115,84 @@ FirstMatchingCompositeObservationHandler customFirstMatchingCompositeObservation
120
115
121
116
@ Bean
122
117
@ Order (2 )
123
- ObservationHandler <Context > customObservationHandler () {
124
- return new CustomObservationHandler ();
118
+ ObservationHandler <Context > customObservationHandler (CalledHandlers calledHandlers ) {
119
+ return new CustomObservationHandler (calledHandlers );
125
120
}
126
121
127
122
@ Bean
128
123
@ Order (1 )
129
- MeterObservationHandler <Context > customMeterObservationHandler2 () {
130
- return new CustomMeterObservationHandler ();
124
+ MeterObservationHandler <Context > customMeterObservationHandler2 (CalledHandlers calledHandlers ) {
125
+ return new CustomMeterObservationHandler ("customMeterObservationHandler2" , calledHandlers );
131
126
}
132
127
133
128
@ Bean
134
129
@ Order (0 )
135
- MeterObservationHandler <Context > customMeterObservationHandler1 () {
136
- return new CustomMeterObservationHandler ();
130
+ MeterObservationHandler <Context > customMeterObservationHandler1 (CalledHandlers calledHandlers ) {
131
+ return new CustomMeterObservationHandler ("customMeterObservationHandler1" , calledHandlers );
132
+ }
133
+
134
+ }
135
+
136
+ private static class CalledHandlers {
137
+
138
+ private final List <ObservationHandler <?>> calledHandlers = new ArrayList <>();
139
+
140
+ void onCalled (ObservationHandler <?> handler ) {
141
+ this .calledHandlers .add (handler );
142
+ }
143
+
144
+ List <ObservationHandler <?>> getCalledHandlers () {
145
+ return this .calledHandlers ;
146
+ }
147
+
148
+ }
149
+
150
+ private static class CustomTracingObservationHandler implements TracingObservationHandler <Context > {
151
+
152
+ private final Tracer tracer = Mockito .mock (Tracer .class , Answers .RETURNS_MOCKS );
153
+
154
+ private final String name ;
155
+
156
+ private final CalledHandlers calledHandlers ;
157
+
158
+ CustomTracingObservationHandler (String name , CalledHandlers calledHandlers ) {
159
+ this .name = name ;
160
+ this .calledHandlers = calledHandlers ;
161
+ }
162
+
163
+ String getName () {
164
+ return this .name ;
165
+ }
166
+
167
+ @ Override
168
+ public Tracer getTracer () {
169
+ return this .tracer ;
170
+ }
171
+
172
+ @ Override
173
+ public void onStart (Context context ) {
174
+ this .calledHandlers .onCalled (this );
175
+ }
176
+
177
+ @ Override
178
+ public boolean supportsContext (Context context ) {
179
+ return true ;
137
180
}
138
181
139
182
}
140
183
141
- static class CustomObservationHandler implements ObservationHandler <Context > {
184
+ private static class CustomObservationHandler implements ObservationHandler <Context > {
185
+
186
+ private final CalledHandlers calledHandlers ;
187
+
188
+ CustomObservationHandler (CalledHandlers calledHandlers ) {
189
+ this .calledHandlers = calledHandlers ;
190
+ }
191
+
192
+ @ Override
193
+ public void onStart (Context context ) {
194
+ this .calledHandlers .onCalled (this );
195
+ }
142
196
143
197
@ Override
144
198
public boolean supportsContext (Context context ) {
@@ -147,7 +201,25 @@ public boolean supportsContext(Context context) {
147
201
148
202
}
149
203
150
- static class CustomMeterObservationHandler implements MeterObservationHandler <Context > {
204
+ private static class CustomMeterObservationHandler implements MeterObservationHandler <Context > {
205
+
206
+ private final CalledHandlers calledHandlers ;
207
+
208
+ private final String name ;
209
+
210
+ CustomMeterObservationHandler (String name , CalledHandlers calledHandlers ) {
211
+ this .name = name ;
212
+ this .calledHandlers = calledHandlers ;
213
+ }
214
+
215
+ String getName () {
216
+ return this .name ;
217
+ }
218
+
219
+ @ Override
220
+ public void onStart (Context context ) {
221
+ this .calledHandlers .onCalled (this );
222
+ }
151
223
152
224
@ Override
153
225
public boolean supportsContext (Context context ) {
0 commit comments