Archived Natchez now supports tracing
An experimental extension of Natchez's
Trace that supports tracing of
Bayou adds an additional method to the
def spanR(name: String): Resource[F, Unit]
This creates a new span, and returns a
Resource such that all effects run within the scope of the
Resource are run within that span.
For example, vanilla
span for a traced effect
F may be implemented in terms of
def span[A](name: String)(k: F[A]): F[A] = spanR(name).use(_ => k)
But now it is also possible to span an entire
def span[A](name: String)(k: Stream[F, A]): Stream[F, A] = Stream.resource(spanR(name)).flatMap(_ => k)
Trace fully interoperates with Natchez:
natchez.Trace and is implemented with
What's the catch?
Trace cannot be implemented with
Kleisli; instead it is implemented for
In practice, I believe this is not a problem, assuming that you initialize tracing early in your
IOApp. Although this setup must be in concrete
IO up until you have an instance of
Trace[IO], your application logic from that point on may be written in terms of
Furthermore, there are advantages to using
IO as your traced effect.
- No need to
mapKbetween your untraced and traced effects, as they are both
IOLocalhas better performance than
Kleisliand furthermore has no performance impact on untraced code.
One shortcoming of
IOLocal-based tracing is that the root span must be installed upon creation. To mitigate this, Bayou offers an
IOTrace class with additional methods that allow a different root span to be injected after-the-fact.
def span[A](span: Span[IO])(k: IO[A]): IO[A] def spanR(span: Span[IO]): Resource[IO, Unit]