Skip to content

Brave 5.7

Compare
Choose a tag to compare
@codefromthecrypt codefromthecrypt released this 07 Oct 19:57
· 447 commits to master since this release

Brave 5.7 introduces configuration customizers and revamps our HTTP abstraction.

XXXCustomizer

Users want to customize only certain parts of the tracing subsystem, letting frameworks configure the rest. For example, a user wants to override the sampler, but not affect the span reporter. This split of concerns works as long as it is possible to run multiple configuration before constructing a component.

Along with a dependency injection tool, customizers help decouple configuration and also ease testing of new features. Users provide XXXCustomizer instances, and frameworks like spring-cloud-sleuth call them at the right time.

In Brave 5.7, we expose several interfaces to customize configuration and use them in our spring-beans integration.

  • CurrentTraceContextCustomizer - called before invoking CurrentTraceContext.Builder.build()
  • ExtraFieldCustomizer - called before invoking ExtraFieldPropagation.FactoryBuilder.build()
  • HttpTracingCustomizer - called before invoking HttpTracing.Builder.build()
  • TracingCustomizer - called before invoking Tracing.Builder.build()

HTTP abstraction overhaul

Before, we used an adapter model to parse a framework type, such as HttpServletRequest. This was a partial function, and aimed to eliminate an extra object allocation otherwise needed during parsing. This worked well until we started to see propagation integration.

For example, Netflix wanted to inspect the http path to make a secondary sampling decision. They could see the request type as a parameter of Extractor.extract(). However, this function had no access to the adapter which would provide means to parse the path. In other words, without a known http request type, secondary sampling could not be accomplished portably.

Through quite a lot of effort, we overhauled every http integration so that they directly use new types: brave.http.HttpClientRequest and brave.http.HttpServerRequest. This opens up new integration possibilities, not just secondary sampling, but also deciding at runtime which headers to use on a per-request basis.

Thanks @basvanbeek for the design help and @anuraaga @devinsba and @jeqo for review

External timestamps in HTTP client and server handling

Armeria supports RequestLog.responseEndTimeNanos() for more precise
timestamps, which line up with metrics. Our HTTP handlers now allow external timestamps, so that advanced frameworks can collaborate in timing decisions. Thanks for the help by @trustin and @kojilin

FinishedSpanHandler.supportsOrphans()

@lambcode noticed that FinishedSpanHandler instances were not called when data is orphaned by buggy instrumentation. While this is technically correct (the "finished" in FinishedSpanHandler is about the correct case), there are use cases to process orphaned data. You can now implement FinishedSpanHandler.supportsOrphans() to indicate handler desires all data, not just complete data. Thanks @lambcode for the code spike and @devinsba @anuraaga for review.