typelevel / otel4s

An OpenTelemetry library for Scala based on Cats-Effect
https://typelevel.org/otel4s
Apache License 2.0
171 stars 35 forks source link

Setting the `SpanKind` is tedious #725

Closed NthPortal closed 1 month ago

NthPortal commented 1 month ago

because the Tracer macros do not support setting the SpanKind, if you want to set the SpanKind and also avoid creating Attributes when the Tracer is disabled, you need to faff about with conditionals and Tracer#meta a bunch. for example:

val t: Tracer[F] = ???
val spanOps =
  if (t.meta.isEnabled) {
    t.spanBuilder("server foo bar")
      .withSpanKind(SpanKind.Server)
      .addAttributes(Attribute("foo", "bar"))
      .build
  } else t.meta.noopSpanBuilder.build

it's annoying and makes the code substantially less readable. it might seem a little bloaty, but I think we can add support for SpanKind to the Tracer macros without too much extra effort or code to maintain. I intend to work on this shortly (though it's stealable if someone wants)

iRevive commented 1 month ago

If the Tracer is noop, the noop SpanBuilder will be used under the hood. However, more is needed to solve the allocation problem.

What if we make addAttribute(s) arguments call-by-name? No attributes will be allocated if the Tracer is noop:

val spanOps =
  t.spanBuilder("server foo bar")
    .withSpanKind(SpanKind.Server)
    .addAttributes(Attribute("foo", "bar"))
    .build

We can also use a macro, but it would be slightly more complicated.

iRevive commented 1 month ago

Ah, we cannot use call-by-name with the varargs. So macro is the only choice.

iRevive commented 1 month ago

While we can add a spanKind to the tracer, it would be beneficial to have a truly zero-allocation noop SpanBuilder, I believe.

I can take care of the macro part.