From 2c7a883b8c12ff3e5d43e611e93aad296cb22ed3 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Thu, 21 Sep 2023 19:08:25 +0200 Subject: [PATCH] Polish observability doc --- docs/modules/ROOT/pages/observability.adoc | 31 ++++++++++++++++++++-- 1 file changed, 29 insertions(+), 2 deletions(-) diff --git a/docs/modules/ROOT/pages/observability.adoc b/docs/modules/ROOT/pages/observability.adoc index 186d7f50f..1537ffa1b 100644 --- a/docs/modules/ROOT/pages/observability.adoc +++ b/docs/modules/ROOT/pages/observability.adoc @@ -8,19 +8,46 @@ Spring provides support for Observability via https://micrometer.io/[Micrometer] Spring cloud Stream integrates such support at the level of Spring Cloud Function by providing amongst several abstractions an `ObservationFunctionAroundWrapper`, which wraps function to handle observations out of the box. +Required dependencies + +[source,xml] +---- + + org.springframework.boot + spring-boot-starter-actuator + + + io.projectreactor + reactor-core-micrometer + +---- + +and one of the available tracer bridges. For example https://zipkin.io/[Zipkin Brave] + +[source,xml] +---- + + io.micrometer + micrometer-tracing-bridge-brave + +---- + == Imperative Functions Imperative functions are wrapped with the observation wrapper `ObservationFunctionAroundWrapper` which provides necessary infrastructure to handle the interaction with the Observation registry. Such interactions happen per each invocation of the function which effectively means that observation is attached to each invocation of the -function (i.e., single observation per message) +function (i.e., single observation per message). +In other words if the required dependencies mentioned earlier present it will just work == Reactive Functions Reactive functions are not wrapped with ‘ObservationFunctionAroundWrapper’ , because there is a fundamental difference between reactive and imperative functions. Imperative function is a message handler that is invoked by the framework on each message it receives. So for N messages there will be N invocations of such function and because of that we can wrap such function and add additional functionality such as error handling, retries, observability etc. Reactive function is initialization function. It is invoked only once to connect user stream (Flux) to the input and output targets. Once connected we have no visibility nor control of the actual stream. It's in the hands of reactive API. -On top of that, what is the unit of observation? A single item in the flux? A range? What if there are no messages after some time elapsed? etc. . . What we wanted to emphasise is that with reactive functions we can't assume anything, hecne just like with retries and error handling you need to handle observation manually. +On top of that, what is the unit of observation? A single item in the flux? A range? What if there are no messages after some time elapsed? etc. . . What we wanted to emphasise is that with reactive functions we can't assume anything, hence just like with retries and error handling you need to handle observation manually. You can do it by tapping into a segment of your stream using the `tap` operation providing an instance of `ObservationRegistry`. Such a segment defines a unit of observation, which could be a single item in the flux or a range or whatever else you may want to observe within the stream. +See xref:spring-cloud-stream/producing-and-consuming-messages.adoc#reactive-functions-support[Reactive Functions] and a "important" note there that explains the fundamental differences between the _reactive_ and _imperative_ functions. + [source,java] ---- @SpringBootApplication