Using OpenTelemetry with Flow

Hi,

I’m trying to use OpenTelemetry in a project which heavily uses flows.

I have flows with incoming messages, each message comes together with a Span
and I would like to propagate Span through the flow
so all loggers and other processing functions can access current span
via thread local Context.current().

For example

source.map { msg ->
  logger.info("...")  // <--- logger here has access to current span which is span from msg
  msg.size
}.map { size ->
  logger.info("...")  // <--- even logger here has access to current span
}

It would be even better if all flow operators could work with spans reasonably well.
Eg. flat map operator could create child spans and end original span.

Is this possible without rewriting every flow operator?

(I believe can replace original flow with flow of pairs where first component is carrying the original message and second component carries span and then redefine all operators to correctly propagate span or create child spans and configure current context in thread local storage. But this doesn’t seem very elegant because I have to replace original operators with custom versions and maintain custom versions. And all my operators must work with span too - which seems distracting from their main purpose)

I don’t know OpenTelemetry, so I apologize if I misunderstood your case. Generally, flows don’t know anything about the logic of your application. They just pass your data from place to place and if you need any custom logic for them, you need to implement it by yourself.

I’m not sure if you only need to pass messages with spans through your flows (“each message comes together with a Span and I would like to propagate Span through the flow”) or you need your flows to actively participate in creating of spans (“flat map operator could create child spans and end original span.”). The first only requires that flows operate on objects that contain both the message and the span. The latter requires to create your own operators, but only for operations that create/modify spans - you don’t need to replace all operators.

Also, it is generally a bad idea to use thread locals when working with coroutines. Coroutines could jump between threads almost freely. If your code is not suspendable then it should be fine, but otherwise, you need to handle thread locals very carefully.