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 ;
53
61
* @author Dmytro Nosan
54
62
* @author Madhura Bhave
55
63
* @author Moritz Halbritter
64
+ * @author Jonatan Ivanov
56
65
*/
57
66
@ ExtendWith (OutputCaptureExtension .class )
58
67
@ SuppressWarnings ("removal" )
@@ -115,6 +124,121 @@ void afterMaxUrisReachedFurtherUrisAreDeniedWhenUsingCustomObservationName(Captu
115
124
});
116
125
}
117
126
127
+ @ Test
128
+ void whenAnActuatorEndpointIsCalledObservationsShouldBeRecorded () {
129
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
130
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
131
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
132
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
133
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
134
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" )
135
+ .run ((context ) -> {
136
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
137
+ "/actuator/info" );
138
+ TestObservationRegistryAssert .assertThat (observationRegistry )
139
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 2 )
140
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" )
141
+ .hasAnObservationWithAKeyValue ("http.url" , "/actuator/info" );
142
+ });
143
+ }
144
+
145
+ @ Test
146
+ void whenActuatorObservationsEnabledObservationsShouldBeRecorded () {
147
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
148
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
149
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
150
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
151
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
152
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
153
+ "management.observations.http.server.actuator.enabled=true" )
154
+ .run ((context ) -> {
155
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
156
+ "/actuator/info" );
157
+ TestObservationRegistryAssert .assertThat (observationRegistry )
158
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 2 )
159
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" )
160
+ .hasAnObservationWithAKeyValue ("http.url" , "/actuator/info" );
161
+ });
162
+ }
163
+
164
+ @ Test
165
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecorded () {
166
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
167
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
168
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
169
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
170
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
171
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
172
+ "management.observations.http.server.actuator.enabled=false" )
173
+ .run ((context ) -> {
174
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
175
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
176
+ "/actuator/info" );
177
+ TestObservationRegistryAssert .assertThat (observationRegistry )
178
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
179
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
180
+ });
181
+ }
182
+
183
+ @ Test
184
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomEndpointBasePath () {
185
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
186
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
187
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
188
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
189
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
190
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
191
+ "management.observations.http.server.actuator.enabled=false" ,
192
+ "management.endpoints.web.base-path=/management" )
193
+ .run ((context ) -> {
194
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
195
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry (context , "/test0" ,
196
+ "/management/info" );
197
+ TestObservationRegistryAssert .assertThat (observationRegistry )
198
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
199
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
200
+ });
201
+ }
202
+
203
+ @ Test
204
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePath () {
205
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
206
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
207
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
208
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
209
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
210
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
211
+ "management.observations.http.server.actuator.enabled=false" , "spring.webflux.base-path=/test-path" )
212
+ .run ((context ) -> {
213
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
214
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry ("/test-path" ,
215
+ context , "/test0" , "/actuator/info" );
216
+ TestObservationRegistryAssert .assertThat (observationRegistry )
217
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
218
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
219
+ });
220
+ }
221
+
222
+ @ Test
223
+ void whenActuatorObservationsDisabledObservationsShouldNotBeRecordedUsingCustomWebfluxBasePathAndCustomEndpointBasePath () {
224
+ this .contextRunner .withUserConfiguration (TestController .class , TestObservationRegistryConfiguration .class )
225
+ .withConfiguration (AutoConfigurations .of (InfoEndpointAutoConfiguration .class ,
226
+ WebFluxAutoConfiguration .class , HttpHandlerAutoConfiguration .class , EndpointAutoConfiguration .class ,
227
+ WebEndpointAutoConfiguration .class , WebFluxEndpointManagementContextConfiguration .class ,
228
+ MetricsAutoConfiguration .class , ObservationAutoConfiguration .class ))
229
+ .withPropertyValues ("management.endpoints.web.exposure.include=info" ,
230
+ "management.observations.http.server.actuator.enabled=false" , "spring.webflux.base-path=/test-path" ,
231
+ "management.endpoints.web.base-path=/management" )
232
+ .run ((context ) -> {
233
+ assertThat (context ).hasBean ("actuatorWebEndpointObservationPredicate" );
234
+ TestObservationRegistry observationRegistry = getInitializedTestObservationRegistry ("/test-path" ,
235
+ context , "/test0" , "/management/info" );
236
+ TestObservationRegistryAssert .assertThat (observationRegistry )
237
+ .hasNumberOfObservationsWithNameEqualTo ("http.server.requests" , 1 )
238
+ .hasAnObservationWithAKeyValue ("http.url" , "/test0" );
239
+ });
240
+ }
241
+
118
242
@ Test
119
243
void shouldNotDenyNorLogIfMaxUrisIsNotReached (CapturedOutput output ) {
120
244
this .contextRunner .withUserConfiguration (TestController .class )
@@ -142,8 +266,7 @@ private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicati
142
266
return getInitializedMeterRegistry (context , "/test0" , "/test1" , "/test2" );
143
267
}
144
268
145
- private MeterRegistry getInitializedMeterRegistry (AssertableReactiveWebApplicationContext context , String ... urls )
146
- throws Exception {
269
+ private MeterRegistry getInitializedMeterRegistry (AssertableReactiveWebApplicationContext context , String ... urls ) {
147
270
assertThat (context ).hasSingleBean (ServerHttpObservationFilter .class );
148
271
WebTestClient client = WebTestClient .bindToApplicationContext (context ).build ();
149
272
for (String url : urls ) {
@@ -152,6 +275,34 @@ private MeterRegistry getInitializedMeterRegistry(AssertableReactiveWebApplicati
152
275
return context .getBean (MeterRegistry .class );
153
276
}
154
277
278
+ private TestObservationRegistry getInitializedTestObservationRegistry (
279
+ AssertableReactiveWebApplicationContext context , String ... urls ) {
280
+ return getInitializedTestObservationRegistry ("" , context , urls );
281
+ }
282
+
283
+ private TestObservationRegistry getInitializedTestObservationRegistry (String baseUrl ,
284
+ AssertableReactiveWebApplicationContext context , String ... urls ) {
285
+ assertThat (context ).hasSingleBean (ServerHttpObservationFilter .class );
286
+ WebTestClient client = WebTestClient .bindToApplicationContext (context )
287
+ .configureClient ()
288
+ .baseUrl (baseUrl )
289
+ .build ();
290
+ for (String url : urls ) {
291
+ client .get ().uri (url ).exchange ().expectStatus ().isOk ();
292
+ }
293
+ return context .getBean (TestObservationRegistry .class );
294
+ }
295
+
296
+ @ Configuration (proxyBeanMethods = false )
297
+ static class TestObservationRegistryConfiguration {
298
+
299
+ @ Bean
300
+ ObservationRegistry observationRegistry () {
301
+ return TestObservationRegistry .create ();
302
+ }
303
+
304
+ }
305
+
155
306
@ Configuration (proxyBeanMethods = false )
156
307
static class CustomConventionConfiguration {
157
308
0 commit comments