ZTracer
ZTracer is the abstraction provided by this library which allows you to seamlessly create traces & spans. For example:
import zio.*
import io.kaizensolutions.trace4cats.zio.extras.ZTracer
val nestedTraceExample: URIO[ZTracer, Unit] =
ZTracer.span("parent") {
ZTracer
.span("child1")(ZTracer.span("grandchild")(ZIO.unit))
.zipParLeft(ZTracer.span("child2")(ZIO.unit))
}
This generates the following structure:
Notice that using the ZTracer abstraction cannot fail; meaning if you mis-configure the tracing configuration, your application will continue to function but traces will not be reported.
ZStream
integration
ZTracer can also be used to trace ZStream
s in tandem with the Spanned
datatype where each element of the ZStream
has an associated span (i.e. Kafka messages). For example:
import zio.*
import zio.stream.*
import io.kaizensolutions.trace4cats.zio.extras.*
import trace4cats.*
// create a stream where each element is associated with a trace header
val stream: ZStream[ZTracer, Nothing, (Int, TraceHeaders)] =
ZStream.range(1, 100)
.mapZIO(i =>
ZTracer.withSpan(s"name-$i")(span =>
ZIO.succeed((i, span.extractHeaders(ToHeaders.standard)))
)
)
// create spans for elements in the stream
val tracedOperationStream: ZStream[ZTracer, Throwable, Spanned[Int]] =
stream.traceEachElement(element => /* we name each span based on the element*/ s"in-begin-$element") {
case (_, headers) => headers // we extract the headers from the element
}
.mapThrough(_._1) // we only care about the element, not the headers - traceEachElement will automatically add the headers back
.mapZIOTraced("Plus 1")(e =>
ZTracer.span(s"plus 1 for $e")(Console.printLine(s"Adding ${e} + 1 = ${e + 1}") *> ZIO.succeed(e + 1))
)
.mapZIOParTraced("Plus 2")(8)(e =>
ZTracer.span(s"plus 2 for $e")(
Console.printLine(s"Adding ${e} + 2 = ${e + 2}").delay(500.millis) *>
ZIO.succeed(e + 2)
)
)
.mapZIOParTraced("Plus 4")(3)(e =>
ZTracer.span(s"plus 4 for $e")(
ZTracer.spanSource()(Console.printLine(s"Adding ${e} + 4 = ${e + 4}").delay(1.second)) *>
ZIO.succeed(e + 2)
)
)
Running the stream above, we'd expect to see something along the lines of:
Have a look at the example if you want to learn more.