wisp-tracing¶
Convenience functions on top of opentracing Java APIs.
Usage¶
Use this library to easily set up and manipulate traces.
import wisp.tracing.trace
tracer.trace("span-name") {
// This block is instrumented with a scope and span.
doSomething()
// They are automatically closed and finished at the end.
}
Testing¶
This module provides a concurrency-safe io.opentracing.mock.MockTracer
as a testFixture.
Use it with:
testImplementation(testFixtures("app.cash.wisp:wisp-tracing:$version"))
Best practises¶
Use a new scope when you change threads.¶
Scopes are not thread-safe, so you need to set up a new scope before switching threads.
import wisp.tracing.traceWithSpan
import wisp.tracing.withNewScope
tracer.traceWithSpan("multiple-threads") { span ->
thread {
// withNewScope() gives you a new Scope with the same span.
// the scope is closed at the end of the block.
tracer.withNewScope(span) {
doSomething()
}
}
}
Use child spans¶
Easily create child spans. Nested calls to trace/traceWithSpan implicitly create parent-child span relationships.
import wisp.tracing.trace
tracer.trace("parent-span") {
// Create a new child span and finish it as soon as block finishes.
tracer.trace("child-span") {
doSomething()
}
}
Isolate interesting spans¶
New root spans can be created from inside parent spans. These will show up independent of the parent context.
import wisp.tracing.trace
import wisp.tracing.traceWithNewRootSpan
tracer.trace("universe") {
tracer.traceWithNewRootSpan("root") {
// Not a child.
}
}
Use baggage and tags¶
Add all your tags at once, instead of processing and adding them one tag at a time. All primitive type tags are supported.
import wisp.tracing.traceWithSpan
import wisp.tracing.setTags
import wisp.tracing.Tag
// Use typed tags.
tracer.traceWithSpan("tags-example") {
span.setTags(listOf(
Tag("string-tag", "string-value"),
Tag("int-tag", 9999),
Tag("bool-tag", true)
))
}
// Or just use string tags.
tracer.trace("tags-example", tags = mapOf("a" to "b")) {
doSomething()
}
Add all your baggage at once, instead of processing and adding it one piece at a time. This information will be available in downstream traces. Baggage can be anything, but will always be converted to a String.
import wisp.tracing.setBaggageItems
import wisp.tracing.traceWithSpan
tracer.traceWithSpan("baggage-example") { span ->
span.setBaggageItems(
mapOf(
"string-baggage" to "foo",
"int-baggage" to 9999,
"json-baggage" to moshi.adapter(Dinosaur::class.java).toJson(trex)
)
)
doSomething()
}
Sometimes you may want to retain baggage from a parent context on smaller, independent traces.
import wisp.tracing.setBaggageItems
import wisp.tracing.traceWithSpan
import wisp.tracing.traceWithNewRootSpan
tracer.traceWithSpan("has-baggage-context") { span ->
span.setBaggageItems(mapOf("string-baggage" to "foo"))
tracer.traceWithNewRootSpan("new-root-span", retainBaggage = true) { newSpan ->
assert(span.context().baggageItems().first() == newSpan.context().baggageItems().first())
}
}