@withSpan("custom name")
val findUser: IO[User] = ???
// expands into
val findUser: IO[User] =
Tracer[IO].span("custom_name").surround(???)
Summary
Pros
1) Separate tracing from the business layer
2) Relatively easy to add tracing to the existing methods
3) Generates boilerplate for you: the name of the span and attributes can be derived automatically
4) Since the result type remains the same, IDEs should be fine
Cons
1) It's macros
2) @spanAttribute contributes to the visual noise
3) Spring-like
Questions
1) Why @withSpan and @spanAttribute instead of @span and @attribute?
If I recall correctly, problems can arise in case-insensitive systems because we already have Span and Attribute.
However, if that is not the case, I would prefer @span and @attribute.
2) Should the macro capture source information?
We can easily add source attributes to the span, such as Attribute("source.file", "some/path/Service.scala") and Attribute("source.line", 123L).
An experimental implementation of the https://github.com/typelevel/otel4s/discussions/550. OpenTelemetry Java offers similar functionality using reflections and AOP https://opentelemetry.io/docs/languages/java/automatic/annotations/.
Before we start
The functionality exists in a separate
otel4s-core-trace-experimental
module.How it works
The body of a method annotated with
@withSpan
will be wrapped into a span:The macro works with variables too:
Summary
Pros
1) Separate tracing from the business layer 2) Relatively easy to add tracing to the existing methods 3) Generates boilerplate for you: the name of the span and attributes can be derived automatically 4) Since the result type remains the same, IDEs should be fine
Cons
1) It's macros 2)
@spanAttribute
contributes to the visual noise 3) Spring-likeQuestions
1) Why
@withSpan
and@spanAttribute
instead of@span
and@attribute
?If I recall correctly, problems can arise in case-insensitive systems because we already have
Span
andAttribute
.However, if that is not the case, I would prefer
@span
and@attribute
.2) Should the macro capture source information?
We can easily add source attributes to the span, such as
Attribute("source.file", "some/path/Service.scala")
andAttribute("source.line", 123L)
.