Library / SDK
openzipkin/brave avatar
openzipkin/brave

Brave 6.3.1: one version for every module, a JRE 1.6 floor, and no install section

Java distributed tracing implementation compatible with Zipkin backend services.

2,404 stars712 forksJavaApache-2.0

At a glance

What is it?
Brave is OpenZipkin's Java tracing library, published as io.zipkin.brave under Apache-2.0. Its README carries no installation command, pins every module to one shared release version, and sets a Java floor that rules out tracing Servlet 2.5 applications.
Who is it for?
Brave is a reasonable choice for a service that has to hand timing data to a Zipkin backend without taking on someone else's dependency decisions, and the zero third-party dependency claim is the reason it keeps working inside applications that pin their own SLF4J, Gson and Guava versions. Two constraints decide whether it fits.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 2 days ago.
What is it written in?
Mainly Java, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on November 14, 2026, and from our analysis. They are not legal advice.

From daily snapshots

Star history

  • openzipkin/brave2,404 ★ · -2
Star history
Repository2026-09-302026-11-14
openzipkin/brave2.4k2.4k

-2 Stars in the last 45 days, measured from the daily GitHub snapshot. Compare with other projects

Editorial analysis

There is no install command, only coordinates and two repositories

The usage documentation has no installation section and no shell command. It gives you a group ID instead: all artifacts publish to the group ID "io.zipkin.brave", and every component uses a common release version. Libraries go to Maven Central, searchable by namespace, and snapshots are uploaded to Sonatype after commits to master. That split has a practical consequence. A snapshot artifact on Sonatype is built from an arbitrary commit, so it is a moving target with no version number of its own, while a Central release is immutable. Anything reproducible belongs on the Central coordinate.

Aligning versions is done through a bill of materials rather than by repeating a number in each dependency block. The import lives in the dependencyManagement section with type pom and scope import:

xml
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>io.zipkin.brave</groupId>
        <artifactId>brave-bom</artifactId>
        <version>${brave.version}</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

With that in place, an instrumentation dependency carries no version at all:

xml
<dependency>
  <groupId>io.zipkin.brave</groupId>
  <artifactId>brave-instrumentation-okhttp3</artifactId>
</dependency>

The `${brave.version}` property then overrides every aligned dependency in one place, which is what the text describes as the common use, testing a new feature or a fix.

One shared version number means one instrumentation patch moves all of them

Because all components publish under a common release version, there is no way to take a fix in a single instrumentation module without taking it in every other module carrying the same number. That is the deliberate trade behind the sentence about aligning versions in one place: fewer version conflicts in exchange for coarser upgrades.

The release trail in the repository metadata shows the pace that produces. Version 6.2.0 is dated 2025-04-28, 6.3.0 is dated 2025-06-01, and 6.3.1 is dated 2026-03-24. The gap between the minor release and the patch is close to ten months, which means a consumer picking up 6.3.1 is picking up whatever else landed in the tree during that window, whether or not it touches the module it uses. The last recorded push to the master branch is dated 2026-03-25, the day after that tag, so the branch tip and the release are close together at that point.

The tree also shows what a shared version implies in practice: `brave/`, `brave-bom/`, `brave-tests/`, `context/`, `instrumentation/` and `spring-beans/` are separate Maven modules sitting next to a root `pom.xml`, plus `build-bin/`, `mvnw`, `mvnw.cmd`, a `.mvn/` directory and a checked-in `.settings.xml`. A shared version across modules built by one reactor is ordinary Maven practice, and it is also why a release is a single coordinated operation rather than a per-module publish.

The JRE 1.6 floor is what keeps Servlet 2.5 out of reach

The tracer library targets JRE6+, and the compatibility policy gives the reasoning: Brave matches the minimum Java version of whatever is being traced or integrated with, and adds no third party dependencies, so it neither makes dependency decisions for you nor changes them. The floor is stated as a benefit with a cost attached. Java 1.6 allows older JREs and older Android runtimes, and the text says this may limit some applications.

The named casualty is precise. Servlet 2.5 works with Java 1.5, but because Brave requires 1.6, a Servlet 2.5 application cannot be traced until it runs on at least JRE 1.6. So the floor is not an abstract compatibility note; it decides whether one specific generation of servlet container is observable at all. On an Android runtime the same floor cuts the other way and is the reason the library can be used there at all.

The integration list in the tree gives a sense of how wide that surface is. Under `instrumentation/` sit per-library modules, and the documentation names gRPC and Kafka clients as the two that are tested against multiple library versions, on the grounds that libraries which update often lead to api drift and a fixed compile target would break on the next release of the traced library. Tracing a library that moves faster than your Java version means matching the library's own pace, not Brave's.

Provided scope is how Brave avoids an argument with your dependency choices

The compatibility policy states that Brave adds no third party dependencies, and the mechanism named for the integrations is scope: every integration sets its associated library to provided scope, which ensures Brave does not interfere with the versions you choose. Provided scope puts the traced library on your compile and runtime classpath from your own build, so Brave compiles against it and never drags a second copy into the tree.

The worked example uses zipkin-sender-urlconnection, described as a basic reporting library. Including it, Brave transitively includes no json, logging, protobuf or thrift dependency, which the policy says means zero concern if your application has chosen a specific version of SLF4J, Gson or Guava. The size claim attached to it is that the entire dependency tree, including basic reporting in json, thrift or protobuf, is less than 512KiB of jars.

That is the whole design argument in one paragraph, and it has a limit worth stating plainly. The guarantee covers Brave's own tree. A tracer that reports to a Zipkin server still has to speak to something, and the repository points out that trace data is normally sent to a Zipkin server while third-party plugins handle alternates such as Amazon X-Ray, which lives in a separate repository under `zipkin-aws` with an X-Ray UDP storage module. Those plugin repositories are outside the boundary the zero-dependency claim draws.

X-B3-TraceId parsing and log correlation live in the library

Brave intercepts production requests to gather timing data, correlate and propagate trace contexts, and that propagation is handled in the tracer itself: the library includes code that parses `X-B3-TraceId` headers. Header parsing being part of the core rather than of each integration means a service that passes a header through a filter, a queue or an HTTP client inherits the same context handling, provided the traced component uses an instrumentation module that calls into the tracer.

Most of the surface area is instrumentation rather than the tracer. The repository includes trace filters for Servlet and log correlation for Apache Log4J, and the documentation is explicit that most users never write tracing code, instead reusing instrumentation others have written. It points at two places to look before rolling your own: its own `instrumentation/` directory and Zipkin's list of tracers and instrumentation, on the grounds that common tracing libraries such as Servlet and Spring already exist and that instrumentation written there is tested and benchmarked.

Trace context also has to survive leaving the request thread. The `context/` directory holds the libraries for putting trace IDs into log files and for changing thread local behavior, with SLF4J named as an integration target. That is the part teams tend to discover late: propagation only carries a context if the thread hop keeps it, and thread local storage is the mechanism that can lose it.

Spring XML configuration is the path for tracing without custom code

For applications that cannot take a code change, the repository carries a `spring-beans/` module described as Spring XML Configuration, which allows tracing to be set up without any custom code. That is aimed at legacy applications, and it is the reason the module sits beside the Java instrumentation rather than inside the documentation site: a Spring application can declare its tracing beans in the same XML it already declares its data sources in.

The module sits inside the Java 1.6 floor described above, so the two constraints combine. XML configuration removes the need for custom code, but the traced application still has to run on a JRE that Brave accepts. The other constraint is api drift against the frameworks being traced, which is why the policy points at version range testing for gRPC and Kafka clients and why some libraries update often enough to cause it.

The remaining root entries describe how the project is worked on rather than how it is used: `HACKING.md`, `RELEASE.md` and `SECURITY.md` at the top level, `.github/`, `.editorconfig`, `LICENSE` and `NOTICE` for the Apache-2.0 terms, and `src/` beside the modules. Nothing in the text available here describes what the root `src/` directory holds, and nothing describes what the checked-in `.settings.xml` points at, so both remain questions for the repository rather than statements this article can make.

Editorial conclusion

Brave is a reasonable choice for a service that has to hand timing data to a Zipkin backend without taking on someone else's dependency decisions, and the zero third-party dependency claim is the reason it keeps working inside applications that pin their own SLF4J, Gson and Guava versions. Two constraints decide whether it fits. The first is the Java floor: tracing a Servlet 2.5 application needs JRE 1.6 or later, so the library cannot go as far back as some of the servers it is meant to observe. The second is versioning: every artifact shares one version number, so a single instrumentation patch moves all of them, and the override warning in the alignment section applies to you, not just to the maintainers. Before pinning 6.3.1, read that alignment section, confirm your own JRE clears the floor, and check the snapshot repository only if you intend to run master code.

Frequently asked questions

What is Brave used for in Java?

Brave is a distributed tracing instrumentation library that intercepts production requests to gather timing data, correlate and propagate trace contexts. Trace data normally goes to a Zipkin server, with third-party plugins available for alternates such as Amazon X-Ray.

Which Java version does Brave require?

The tracer library targets JRE6+ with a floor of Java 1.6, which allows older JREs and older Android runtimes. The consequence named in the compatibility policy is that a Servlet 2.5 application cannot be traced until it runs on at least JRE 1.6.

Does Brave pull in other libraries?

It adds no third party dependencies, and integrations set their associated library to provided scope so Brave does not interfere with the versions you choose. The worked example, zipkin-sender-urlconnection, transitively adds no json, logging, protobuf or thrift dependency.

Where are Brave artifacts published?

Library releases go to Maven Central under the group ID io.zipkin.brave, and snapshots are uploaded to Sonatype after commits to master. All components share one common release version, so there is no per-module number.

How do several Brave modules end up on the same version?

Import the brave-bom artifact in your dependencyManagement section with type pom and scope import, set the ${brave.version} property, and leave the version off each instrumentation dependency. The override is described as useful for testing a new feature or fix.

Which libraries does Brave provide instrumentation for?

The repository names trace filters for Servlet, log correlation for Apache Log4J, a context library for trace IDs in log files and thread local behavior, and instrumentation directories for gRPC and Kafka clients tested against multiple library versions.

Official sources

  1. Issues
  2. License: Apache-2.0
  3. openzipkin/brave on GitHub
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/openzipkin-brave.svg)](https://hysenlabs.com/projects/openzipkin-brave)

Star history chart for your README

markdown
[![Star history](https://hysenlabs.com/chart/openzipkin-brave.svg)](https://hysenlabs.com/projects/openzipkin-brave)

Was this useful?