Brave 5.12
Brave 5.12 introduces a powerful new way to handle data, completes our RPC abstraction, drops our Zipkin dependency and pours our thinking into RATIONALE docs.
There's a lot in this release for those doing advanced things like managing configuration tools or implementing custom tracing backends. Most users will do nothing except upgrade.
If you are using Brave directly, you should take note of deprecation mentioned. We do a major release every couple years, to remove deprecation and Brave 6 will also do that. By paying attention, not only will your code work faster, but you'll have less surprise later.
Like all releases, volunteers bore a huge responsibility on this release. As so much happened here, it was quite a load. Please reach out and thank those who contributed, star our repo or say hi on gitter. If you have ideas, we'd love to hear about them, too.
On to the main show!
Introducing SpanHandler
Brave 5.12 has a cleaner integration for data than ever before. SpanHandler
replaces FinishedSpanHandler
. SpanHandler
can do everything FinishedSpanHandler
did: redacting, adding tags based on baggage, remapping trace IDs, sending to multiple systems etc.
The more advanced begin
hook adds much more power. You can setup default baggage only on local roots, add correlated mapped data extensions, perform aggregations such as child counts.
This is our most powerful API co-designed by @anuraaga and with lots of good feedback from our usual suspects @jeqo and @jorgheymans. For now, you can just replace FinishedSpanHandler
with SpanHandler
, but if you are curious.. here are few links of interest:
See https://github.com/openzipkin/brave/blob/master/brave/src/main/java/brave/handler/SpanHandler.java
See https://github.com/openzipkin/brave/tree/master/brave/src/test/java/brave/features/handler
See https://github.com/openzipkin/zipkin-reporter-java/tree/master/brave
MutableSpan can do everything now
MutableSpan was initially a response to complaints that immutable conversions added GC pressure and generally weren't a good choice for telemetry.
Before, we paired TraceContext
with MutableSpan
, splitting responsibilities. However, this would make things like natively writing JSON from Zipkin types difficult. Hence, we fully fleshed out MutableSpan
so that it accompanies, but is decoupled from TraceContext
.
Here are some features newly available with much thanks to @anuraaga for a month of help on them!
MutableSpanBytesEncoder
- allows you to writeMutableSpan
directly to JSON without any dependencies or intermediating through another type such aszipkin2.Span
.MutableSpan.xxxId()
- allows you to specify read or remap all IDs including trace IDs, depending on your outputMutableSpan.annotations(), tags()
- read-only immutable collection views for convenience of those not concerned with performance (internally implemented as arrays)MutableSpan.annotationCount(), tagCount() xxxValueAt(index)
- allocation free tools to write data conversions as for loops.
RPC abstraction is now complete!
We started an RPC abstraction about 9 months ago. Last October, we RPC sampling support in Brave 5.8.
With a lot of thanks to our contributors @devinsba @jeqo @jcchavezs and especially weeks of effort by volunteer @anuraaga, we have a complete product. Those using gRPC or Dubbo can now uniformly sample and parse parse based on RPC metadata:
By default, the following are added to both RPC client and server spans:
- Span.name is the RPC service/method. Ex. "zipkin.proto3.SpanService/Report"
- If the service is absent, the method is the name and visa versa.
- Tags:
- "rpc.method", eg "Report"
- "rpc.service", eg "zipkin.proto3.SpanService"
- "rpc.error_code", eg "CANCELLED"
- "error" the RPC error code if there is no exception
- Remote IP and port information
Users familiar with how HTTP works will love the familiarity. The APIs are similar, exactly the same features are supported, whether that's sampling, baggage you name it. Those curious about our decision making process can have a look at the RATIONALE as we tried our best to make sound decisions and be transparent about them. Enjoy!
Zipkin dependency is dropped!
With the SpanHandler
type finalized, we have deprecated support for zipkin2.Reporter<zipkin2.Span>
in Brave and removes dependencies on Zipkin libraries.
This isn't to deprecate Zipkin support, of course, just move the responsibility to the zipkin-reporter-brave project (even [XML beans](https://github.com/openzipkin/zipkin-reporter-java/tree/master/spring-beans for those who need it!)
The end result is cleaner integrations for the various SaaS offerings who use Brave, but don't use Zipkin. Such use cases should be directly implemented as SpanHandler
now, with no need to route through zipkin format.
Zipkin users should simply replace AsyncReporter
with AsyncZipkinSpanHandler
to adjust, similar to what's in our README:
// Configure a reporter, which controls how often spans are sent
// (this dependency is io.zipkin.reporter2:zipkin-sender-okhttp3)
sender = OkHttpSender.create("http://127.0.0.1:9411/api/v2/spans");
// (this dependency is io.zipkin.reporter2:zipkin-reporter-brave)
zipkinSpanHandler = AsyncZipkinSpanHandler.create(sender);
tracing = Tracing.newBuilder()
.addSpanHandler(zipkinSpanHandler)
...
Test infrastructure overhaul
As we no longer have a Zipkin dependency, we decided to make tools to help common unit and integration tests. For example, vendors integrating with Brave should be able to assert on the data produced. Third party libraries should be able to avoid common bugs. Beyond our normal ITHttpServer
and similar tests, we've extracted the following in the brave-tests
package:
- ITRemote - configures the most common test fixtures for multi-threaded integration tests
- TestSpanHandler - allows simple assertions for unit tests
- IntegrationTestSpanHandler - blocking span reporter for remote multi-threaded unit tests.
Rationale
We have updated and added many RATIONALE files including the below to better help people understand our thinking.. and to help us remember our thinking!
Thanks to @jorgheymans @jeqo @jcchavezs @anuraaga and @NersesAM for the help adding content and reviewing
brave
brave-instrumentation
brave-instrumentation-dubbo
brave-instrumentation-http
brave-instrumentation-grpc
brave-instrumentation-kafka-streams
brave-instrumentation-rpc
Other Notable Changes
Updates
- Kafka 2.5 is now supported, thanks to @jeqo
Behavior
- one-way RPC span modeling should no longer use
span.start().flush()
on one host andspan.finish()
(without start) on the other. This was implemented inconsistently and not very compatible with most clones.
Additions
Tracing.Builder.clearSpanHandlers(), spanHandlers()
- allowsTracingCustomizer
instances to re-order or prune span handlers. For example, to ensure Zipkin is last, or theirs is first.Tracing.Builder.alwaysSampleLocal()
- special hook for metrics aggregation and secondary-sampling that says the backend should always see recorded spans even if they weren't sampled in headers
Deprecations:
Tracer.propagationFactory()
is deprecated for the existingTracer.propagation()
as we no longer rely on non-string keys (these were only used by gRPC and we changed to hide this conversion).brave.ErrorParser
is deprecated as it was only used for Zipkin conversion. You can optionally specifyTag<Throwable>
to affect the default "error" tag in zipkin-reporter-brave