diff --git a/framework-docs/src/docs/asciidoc/attributes.adoc b/framework-docs/src/docs/asciidoc/attributes.adoc index 321eaf5cd34a..1daab4dd8b60 100644 --- a/framework-docs/src/docs/asciidoc/attributes.adoc +++ b/framework-docs/src/docs/asciidoc/attributes.adoc @@ -1,4 +1,5 @@ :chomp: default headers packages +:fold: all :docs-site: https://docs.spring.io // Spring Framework :docs-spring-framework: {docs-site}/spring-framework/docs/{spring-version} diff --git a/framework-docs/src/docs/asciidoc/integration/observability.adoc b/framework-docs/src/docs/asciidoc/integration/observability.adoc index 0fa1af576742..028bc1ee4ef5 100644 --- a/framework-docs/src/docs/asciidoc/integration/observability.adoc +++ b/framework-docs/src/docs/asciidoc/integration/observability.adoc @@ -67,6 +67,12 @@ HTTP server exchanges observations are created with the name `"http.server.reque Applications need to configure the `org.springframework.web.filter.ServerHttpObservationFilter` Servlet filter in their application. It is using the `org.springframework.http.server.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`. +This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the Servlet filter. +Typically, all exceptions handled by Spring MVC's `@ExceptionHandler` and <> will not be recorded with the observation. +You can, at any point during request processing, set the error field on the `ObservationContext` yourself: + +include::code:UserController[] + By default, the following `KeyValues` are created: .Low cardinality Keys @@ -94,6 +100,12 @@ By default, the following `KeyValues` are created: Applications need to configure the `org.springframework.web.filter.reactive.ServerHttpObservationFilter` reactive `WebFilter` in their application. It is using the `org.springframework.http.server.reactive.observation.DefaultServerRequestObservationConvention` by default, backed by the `ServerRequestObservationContext`. +This will only record an observation as an error if the `Exception` has not been handled by the web Framework and has bubbled up to the `WebFilter`. +Typically, all exceptions handled by Spring WebFlux's `@ExceptionHandler` and <> will not be recorded with the observation. +You can, at any point during request processing, set the error field on the `ObservationContext` yourself: + +include::code:UserController[] + By default, the following `KeyValues` are created: .Low cardinality Keys diff --git a/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/reactive/UserController.java b/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/reactive/UserController.java new file mode 100644 index 000000000000..fc6221558c8e --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/reactive/UserController.java @@ -0,0 +1,42 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.docs.integration.observability.httpserver.reactive; + +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.filter.reactive.ServerHttpObservationFilter; +import org.springframework.web.server.ServerWebExchange; + +@Controller +public class UserController { + + @ExceptionHandler(MissingUserException.class) + ResponseEntity handleMissingUser(ServerWebExchange exchange, MissingUserException exception) { + // We want to record this exception with the observation + ServerHttpObservationFilter.findObservationContext(exchange) + .ifPresent(context -> context.setError(exception)); + return ResponseEntity.notFound().build(); + } + + // @fold:on + static class MissingUserException extends RuntimeException { + + } + // @fold:off + +} diff --git a/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/servlet/UserController.java b/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/servlet/UserController.java new file mode 100644 index 000000000000..5f44127961e1 --- /dev/null +++ b/framework-docs/src/main/java/org/springframework/docs/integration/observability/httpserver/servlet/UserController.java @@ -0,0 +1,43 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.docs.integration.observability.httpserver.servlet; + +import jakarta.servlet.http.HttpServletRequest; + +import org.springframework.http.ResponseEntity; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.ExceptionHandler; +import org.springframework.web.filter.ServerHttpObservationFilter; + +@Controller +public class UserController { + + @ExceptionHandler(MissingUserException.class) + ResponseEntity handleMissingUser(HttpServletRequest request, MissingUserException exception) { + // We want to record this exception with the observation + ServerHttpObservationFilter.findObservationContext(request) + .ifPresent(context -> context.setError(exception)); + return ResponseEntity.notFound().build(); + } + + // @fold:on + static class MissingUserException extends RuntimeException { + + } + // @fold:off + +}