19
19
import java .util .List ;
20
20
21
21
import io .micrometer .core .instrument .MeterRegistry ;
22
+ import io .micrometer .observation .ObservationRegistry ;
23
+ import io .micrometer .observation .tck .TestObservationRegistry ;
24
+ import io .micrometer .observation .tck .TestObservationRegistryAssert ;
22
25
import org .junit .jupiter .api .Test ;
23
26
import org .junit .jupiter .api .extension .ExtendWith ;
24
27
import reactor .core .publisher .Mono ;
25
28
29
+ import org .springframework .boot .actuate .autoconfigure .endpoint .EndpointAutoConfiguration ;
30
+ import org .springframework .boot .actuate .autoconfigure .endpoint .web .WebEndpointAutoConfiguration ;
31
+ import org .springframework .boot .actuate .autoconfigure .endpoint .web .reactive .WebFluxEndpointManagementContextConfiguration ;
32
+ import org .springframework .boot .actuate .autoconfigure .info .InfoEndpointAutoConfiguration ;
26
33
import org .springframework .boot .actuate .autoconfigure .metrics .MetricsAutoConfiguration ;
27
34
import org .springframework .boot .actuate .autoconfigure .metrics .test .MetricsRun ;
28
35
import org .springframework .boot .actuate .autoconfigure .metrics .web .TestController ;
29
36
import org .springframework .boot .actuate .autoconfigure .observation .ObservationAutoConfiguration ;
30
37
import org .springframework .boot .autoconfigure .AutoConfigurations ;
38
+ import org .springframework .boot .autoconfigure .web .reactive .HttpHandlerAutoConfiguration ;
31
39
import org .springframework .boot .autoconfigure .web .reactive .WebFluxAutoConfiguration ;
32
40
import org .springframework .boot .test .context .assertj .AssertableReactiveWebApplicationContext ;
33
41
import org .springframework .boot .test .context .runner .ReactiveWebApplicationContextRunner ;
52
60
* @author Brian Clozel
53
61
* @author Dmytro Nosan
54
62
* @author Madhura Bhave
63
+ * @author Jonatan Ivanov
55
64
*/
56
65
@ ExtendWith (OutputCaptureExtension .class )
57
66
@ SuppressWarnings ("removal" )
@@ -114,6 +123,121 @@ void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomObservationName(Captu
114
123
});
115
124
}
116
125
126
+ @ Test
127
+ void whenAnActuatorEndpointIsCalledObservationsShouldBeRecorded () {
128
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
129
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
130
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
131
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
132
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
133
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" )
134
+ .run ((context ) -> {
135
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
136
+ "/actuator/info" );
137
+ TestObservationRegistryAssert .assertThat (observationRegistry )
138
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 2 )
139
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" )
140
+ .hasAnObservationWithAKeyValue ("http.url" , "/actuator/info" );
141
+ });
142
+ }
143
+
144
+ @ Test
145
+ void whenActuatorObservationsEnabledObservationsShouldBeRecorded () {
146
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
147
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
148
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
149
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
150
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
151
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
152
+ "management.observations.http.server.actuator.enabled=true" )
153
+ .run ((context ) -> {
154
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
155
+ "/actuator/info" );
156
+ TestObservationRegistryAssert .assertThat (observationRegistry )
157
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 2 )
158
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" )
159
+ .hasAnObservationWithAKeyValue ("http.url" , "/actuator/info" );
160
+ });
161
+ }
162
+
163
+ @ Test
164
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecorded () {
165
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
166
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
167
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
168
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
169
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
170
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
171
+ "management.observations.http.server.actuator.enabled=false" )
172
+ .run ((context ) -> {
173
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
174
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
175
+ "/actuator/info" );
176
+ TestObservationRegistryAssert .assertThat (observationRegistry )
177
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
178
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
179
+ });
180
+ }
181
+
182
+ @ Test
183
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomEndpointBasePath () {
184
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
185
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
186
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
187
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
188
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
189
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
190
+ "management.observations.http.server.actuator.enabled=false" ,
191
+ "management.endpoints.web.base-path=/management" )
192
+ .run ((context ) -> {
193
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
194
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
195
+ "/management/info" );
196
+ TestObservationRegistryAssert .assertThat (observationRegistry )
197
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
198
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
199
+ });
200
+ }
201
+
202
+ @ Test
203
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePath () {
204
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
205
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
206
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
207
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
208
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
209
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
210
+ "management.observations.http.server.actuator.enabled=false" , "spring.webflux.base-path=/test-path" )
211
+ .run ((context ) -> {
212
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
213
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry ("/test-path" ,
214
+ context , "/test0" , "/actuator/info" );
215
+ TestObservationRegistryAssert .assertThat (observationRegistry )
216
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
217
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
218
+ });
219
+ }
220
+
221
+ @ Test
222
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePathAndCustomEndpointBasePath () {
223
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
224
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
225
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
226
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
227
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
228
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
229
+ "management.observations.http.server.actuator.enabled=false" , "spring.webflux.base-path=/test-path" ,
230
+ "management.endpoints.web.base-path=/management" )
231
+ .run ((context ) -> {
232
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
233
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry ("/test-path" ,
234
+ context , "/test0" , "/management/info" );
235
+ TestObservationRegistryAssert .assertThat (observationRegistry )
236
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
237
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
238
+ });
239
+ }
240
+
117
241
@ Test
118
242
void shouldNotDenyNorLogIfMaxUrisIsNotReached (CapturedOutput output ) {
119
243
this .contextRunner .withUserConfiguration (TestController .class )
@@ -132,8 +256,7 @@ private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicati
132
256
return getInitializedMeterRegistry (context , "/test0" , "/test1" , "/test2" );
133
257
}
134
258
135
- private MeterRegistry getInitializedMeterRegistry (AssertableReactiveWebApplicationContext context , String ... urls )
136
- throws Exception {
259
+ private MeterRegistry getInitializedMeterRegistry (AssertableReactiveWebApplicationContext context , String ... urls ) {
137
260
assertThat (context ).hasSingleBean (ServerHttpObservationFilter .class );
138
261
WebTestClient client = WebTestClient .bindToApplicationContext (context ).build ();
139
262
for (String url : urls ) {
@@ -142,6 +265,34 @@ private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicati
142
265
return context .getBean (MeterRegistry .class );
143
266
}
144
267
268
+ private TestObservationRegistry getInitializedTestObservationRegistry (
269
+ AssertableReactiveWebApplicationContext context , String ... urls ) {
270
+ return getInitializedTestObservationRegistry ("" , context , urls );
271
+ }
272
+
273
+ private TestObservationRegistry getInitializedTestObservationRegistry (String baseUrl ,
274
+ AssertableReactiveWebApplicationContext context , String ... urls ) {
275
+ assertThat (context ).hasSingleBean (ServerHttpObservationFilter .class );
276
+ WebTestClient client = WebTestClient .bindToApplicationContext (context )
277
+ .configureClient ()
278
+ .baseUrl (baseUrl )
279
+ .build ();
280
+ for (String url : urls ) {
281
+ client .get ().uri (url ).exchange ().expectStatus ().isOk ();
282
+ }
283
+ return context .getBean (TestObservationRegistry .class );
284
+ }
285
+
286
+ @ Configuration (proxyBeanMethods = false )
287
+ static class TestObservationRegistryConfiguration {
288
+
289
+ @ Bean
290
+ ObservationRegistry observationRegistry () {
291
+ return TestObservationRegistry .create ();
292
+ }
293
+
294
+ }
295
+
145
296
@ Configuration (proxyBeanMethods = false )
146
297
static class CustomConventionConfiguration {
147
298
0 commit comments