Archived Natchez now supports tracing Resources and Streams out-of-the-box.
An experimental extension of Natchez's Trace that supports tracing of Resource and Stream.
Bayou adds an additional method to the Trace API.
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 spanR.
def span[A](name: String)(k: F[A]): F[A] =
spanR(name).use(_ => k)But now it is also possible to span an entire Stream.
def span[A](name: String)(k: Stream[F, A]): Stream[F, A] =
Stream.resource(spanR(name)).flatMap(_ => k)Bayou's Trace fully interoperates with Natchez: bayou.Trace extends natchez.Trace and is implemented with natchez.Span.
Bayou's Trace cannot be implemented with Kleisli; instead it is implemented for IO via IOLocal.
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 F[_]: Trace.
Furthermore, there are advantages to using IO as your traced effect.
- No need to
mapKbetween your untraced and traced effects, as they are bothIO. IOLocalhas better performance thanKleisliand 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]