├── .editorconfig ├── .github ├── CONTRIBUTING.md ├── ISSUE_TEMPLATE │ ├── bug.md │ ├── config.yml │ └── feature.md └── workflows │ ├── create_release.yml │ ├── deploy.yml │ ├── security.yml │ └── test.yml ├── .gitignore ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ └── maven-wrapper.properties ├── .settings.xml ├── HACKING.md ├── LICENSE ├── NOTICE ├── README.md ├── RELEASE.md ├── SECURITY.md ├── brave-bom └── pom.xml ├── brave-tests ├── README.md ├── pom.xml └── src │ ├── main │ ├── java │ │ └── brave │ │ │ └── test │ │ │ ├── ITRemote.java │ │ │ ├── IntegrationTestSpanHandler.java │ │ │ ├── TestSpanHandler.java │ │ │ ├── propagation │ │ │ ├── B3SingleFormatClassLoaderTest.java │ │ │ ├── CurrentTraceContextTest.java │ │ │ ├── PropagationSetterTest.java │ │ │ └── PropagationTest.java │ │ │ └── util │ │ │ ├── AssertableCallback.java │ │ │ ├── ClassLoaders.java │ │ │ └── GarbageCollectors.java │ └── resources │ │ └── log4j2.properties │ └── test │ └── java │ └── brave │ ├── TracingClassLoaderTest.java │ ├── internal │ ├── PlatformClassLoaderTest.java │ ├── handler │ │ └── NoopAwareSpanHandlerClassLoaderTest.java │ └── recorder │ │ └── PendingSpansClassLoaderTest.java │ ├── propagation │ ├── B3PropagationTest.java │ ├── InheritableDefaultCurrentTraceContextTest.java │ ├── StrictCurrentTraceContextTest.java │ ├── ThreadLocalCurrentTraceContextClassLoaderTest.java │ ├── ThreadLocalCurrentTraceContextTest.java │ ├── ThreadLocalSpanClassLoaderTest.java │ ├── TraceContextClassLoaderTest.java │ └── URLConnectionSetterTest.java │ └── test │ ├── ITRemoteTest.java │ ├── IntegrationTestSpanHandlerTest.java │ └── util │ └── ClassLoadersTest.java ├── brave ├── RATIONALE.md ├── README.md ├── bnd.bnd ├── pom.xml └── src │ ├── it │ └── no_deps │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ └── test │ │ └── java │ │ └── brave │ │ └── no_deps │ │ └── TracingTest.java │ ├── main │ └── java │ │ └── brave │ │ ├── Clock.java │ │ ├── CurrentSpanCustomizer.java │ │ ├── LazySpan.java │ │ ├── NoopScopedSpan.java │ │ ├── NoopSpan.java │ │ ├── NoopSpanCustomizer.java │ │ ├── RealScopedSpan.java │ │ ├── RealSpan.java │ │ ├── Request.java │ │ ├── Response.java │ │ ├── ScopedSpan.java │ │ ├── Span.java │ │ ├── SpanCustomizer.java │ │ ├── SpanCustomizerShield.java │ │ ├── Tag.java │ │ ├── Tags.java │ │ ├── Tracer.java │ │ ├── Tracing.java │ │ ├── TracingCustomizer.java │ │ ├── baggage │ │ ├── BaggageField.java │ │ ├── BaggageFields.java │ │ ├── BaggagePropagation.java │ │ ├── BaggagePropagationConfig.java │ │ ├── BaggagePropagationCustomizer.java │ │ ├── CorrelationFlushScope.java │ │ ├── CorrelationScopeConfig.java │ │ ├── CorrelationScopeCustomizer.java │ │ ├── CorrelationScopeDecorator.java │ │ └── CorrelationUpdateScope.java │ │ ├── handler │ │ ├── MutableSpan.java │ │ ├── MutableSpanBytesEncoder.java │ │ └── SpanHandler.java │ │ ├── internal │ │ ├── CorrelationContext.java │ │ ├── InternalPropagation.java │ │ ├── Nullable.java │ │ ├── Platform.java │ │ ├── RecyclableBuffers.java │ │ ├── Throwables.java │ │ ├── WrappingExecutorService.java │ │ ├── baggage │ │ │ ├── BaggageCodec.java │ │ │ ├── BaggageContext.java │ │ │ ├── BaggageFields.java │ │ │ ├── ExtraBaggageContext.java │ │ │ └── SingleFieldBaggageCodec.java │ │ ├── codec │ │ │ ├── CharSequences.java │ │ │ ├── EntrySplitter.java │ │ │ ├── HexCodec.java │ │ │ ├── IpLiteral.java │ │ │ ├── JsonEscaper.java │ │ │ ├── JsonWriter.java │ │ │ ├── WriteBuffer.java │ │ │ └── ZipkinV2JsonWriter.java │ │ ├── collect │ │ │ ├── Lists.java │ │ │ ├── LongBitSet.java │ │ │ ├── UnsafeArrayMap.java │ │ │ └── WeakConcurrentMap.java │ │ ├── extra │ │ │ ├── Extra.java │ │ │ ├── ExtraFactory.java │ │ │ ├── MapExtra.java │ │ │ └── MapExtraFactory.java │ │ ├── handler │ │ │ ├── NoopAwareSpanHandler.java │ │ │ └── OrphanTracker.java │ │ ├── propagation │ │ │ └── InjectorFactory.java │ │ └── recorder │ │ │ ├── PendingSpan.java │ │ │ ├── PendingSpans.java │ │ │ └── TickClock.java │ │ ├── propagation │ │ ├── B3Propagation.java │ │ ├── B3SingleFormat.java │ │ ├── B3SinglePropagation.java │ │ ├── CurrentTraceContext.java │ │ ├── CurrentTraceContextCustomizer.java │ │ ├── Propagation.java │ │ ├── SamplingFlags.java │ │ ├── StrictCurrentTraceContext.java │ │ ├── StrictScopeDecorator.java │ │ ├── ThreadLocalCurrentTraceContext.java │ │ ├── ThreadLocalSpan.java │ │ ├── TraceContext.java │ │ ├── TraceContextOrSamplingFlags.java │ │ └── TraceIdContext.java │ │ └── sampler │ │ ├── BoundarySampler.java │ │ ├── CountingSampler.java │ │ ├── DeclarativeSampler.java │ │ ├── Matcher.java │ │ ├── Matchers.java │ │ ├── ParameterizedSampler.java │ │ ├── RateLimitingSampler.java │ │ ├── Sampler.java │ │ ├── SamplerFunction.java │ │ └── SamplerFunctions.java │ └── test │ ├── java │ └── brave │ │ ├── CurrentSpanCustomizerTest.java │ │ ├── CurrentTraceContextExecutorServiceTest.java │ │ ├── CurrentTraceContextExecutorTest.java │ │ ├── CurrentTracingTest.java │ │ ├── GarbageCollectors.java │ │ ├── LazySpanTest.java │ │ ├── NoopSpanTest.java │ │ ├── RealSpanCustomizerTest.java │ │ ├── RealSpanTest.java │ │ ├── RequestTest.java │ │ ├── ResponseTest.java │ │ ├── SpanCustomizerShieldTest.java │ │ ├── TagTest.java │ │ ├── TagsTest.java │ │ ├── TracerTest.java │ │ ├── TracingTest.java │ │ ├── baggage │ │ ├── Access.java │ │ ├── BaggageFieldTest.java │ │ ├── BaggageFieldsTest.java │ │ ├── BaggagePropagationTest.java │ │ └── CorrelationScopeDecoratorTest.java │ │ ├── features │ │ ├── advanced │ │ │ └── CustomScopedClockTracingTest.java │ │ ├── baggage │ │ │ ├── BaggageInSingleHeaderTest.java │ │ │ └── SingleHeaderCodec.java │ │ ├── finagle_context │ │ │ ├── FinagleContextInteropTest.java │ │ │ └── package-info.java │ │ ├── handler │ │ │ ├── CountingChildrenTest.java │ │ │ ├── DefaultTagsTest.java │ │ │ ├── MutableSpanAsyncReporterTest.java │ │ │ ├── RedactingSpanHandlerTest.java │ │ │ ├── SkeletalSpansTest.java │ │ │ ├── SpanMetricsCustomizer.java │ │ │ ├── SpanMetricsCustomizerTest.java │ │ │ └── package-info.java │ │ ├── opentracing │ │ │ ├── BraveSpan.java │ │ │ ├── BraveSpanBuilder.java │ │ │ ├── BraveSpanContext.java │ │ │ ├── BraveTracer.java │ │ │ ├── OpenTracingAdapterTest.java │ │ │ ├── TextMapPropagation.java │ │ │ └── package-info.java │ │ ├── package-info.java │ │ ├── propagation │ │ │ ├── CustomTraceIdPropagation.java │ │ │ ├── HackedTraceIdTest.java │ │ │ ├── SetOnceBaggageTest.java │ │ │ └── package-info.java │ │ └── sampler │ │ │ └── AspectJSamplerTest.java │ │ ├── handler │ │ ├── MutableSpanBytesEncoderTest.java │ │ └── MutableSpanTest.java │ │ ├── internal │ │ ├── InternalPropagationTest.java │ │ ├── PlatformTest.java │ │ ├── codec │ │ │ ├── CharSequencesTest.java │ │ │ ├── EntrySplitterTest.java │ │ │ ├── HexCodecTest.java │ │ │ ├── IpLiteralTest.java │ │ │ ├── JsonEscaperTest.java │ │ │ ├── JsonWriterTest.java │ │ │ ├── WriteBufferTest.java │ │ │ └── ZipkinV2JsonWriterTest.java │ │ ├── collect │ │ │ ├── ListsTest.java │ │ │ ├── UnsafeArrayMapTest.java │ │ │ └── WeakConcurrentMapTest.java │ │ ├── extra │ │ │ ├── BasicMapExtra.java │ │ │ ├── ExtraFactoryTest.java │ │ │ └── MapExtraTest.java │ │ ├── handler │ │ │ ├── NoopAwareSpanHandlerTest.java │ │ │ └── OrphanTrackerTest.java │ │ ├── propagation │ │ │ └── InjectorFactoryTest.java │ │ └── recorder │ │ │ ├── PendingSpansTest.java │ │ │ └── TickClockTest.java │ │ ├── propagation │ │ ├── B3PropagationTest.java │ │ ├── B3SingleFormatTest.java │ │ ├── PropagationConstantsTest.java │ │ ├── PropagationFactoryTest.java │ │ ├── SamplingFlagsTest.java │ │ ├── StrictScopeDecoratorTest.java │ │ ├── ThreadLocalSpanTest.java │ │ ├── TraceContextOrSamplingFlagsTest.java │ │ ├── TraceContextTest.java │ │ └── TraceIdContextTest.java │ │ ├── sampler │ │ ├── BoundarySamplerTest.java │ │ ├── CountingSamplerTest.java │ │ ├── DeclarativeSamplerTest.java │ │ ├── MatchersTest.java │ │ ├── ParameterizedSamplerTest.java │ │ ├── RateLimitingSamplerSoakTest.java │ │ ├── RateLimitingSamplerTest.java │ │ ├── SamplerFunctionsTest.java │ │ └── SamplerTest.java │ │ └── test │ │ └── TestSpanHandler.java │ └── resources │ └── log4j2.properties ├── build-bin ├── README.md ├── configure_deploy ├── configure_test ├── deploy ├── deploy_bom ├── docker │ └── configure_docker ├── git │ ├── login_git │ └── version_from_trigger_tag ├── gpg │ └── configure_gpg ├── javadoc_to_gh_pages ├── maven │ ├── maven_deploy │ ├── maven_go_offline │ ├── maven_opts │ └── maven_release └── test ├── context ├── jfr │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── context │ │ │ └── jfr │ │ │ └── JfrScopeDecorator.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── context │ │ │ └── jfr │ │ │ └── JfrScopeDecoratorTest.java │ │ └── resources │ │ └── log4j2.properties ├── log4j12 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── log4j12 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── resources │ │ │ └── log4j.properties │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── context │ │ │ └── log4j12 │ │ │ └── MDCScopeDecorator.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── context │ │ │ └── log4j12 │ │ │ └── MDCScopeDecoratorTest.java │ │ └── resources │ │ └── log4j2.properties ├── log4j2 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── context │ │ │ └── log4j2 │ │ │ └── ThreadContextScopeDecorator.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── context │ │ │ └── log4j2 │ │ │ └── ThreadContextScopeDecoratorTest.java │ │ └── resources │ │ └── log4j2.properties ├── pom.xml └── slf4j │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ ├── main │ └── java │ │ └── brave │ │ └── context │ │ └── slf4j │ │ └── MDCScopeDecorator.java │ └── test │ ├── java │ └── brave │ │ └── context │ │ └── slf4j │ │ └── MDCScopeDecoratorTest.java │ └── resources │ └── log4j2.properties ├── instrumentation ├── RATIONALE.md ├── README.md ├── benchmarks │ ├── README.md │ ├── pom.xml │ └── src │ │ └── test │ │ ├── assembly │ │ └── test-jar.xml │ │ ├── java │ │ └── brave │ │ │ ├── EndToEndBenchmarks.java │ │ │ ├── TracerBenchmarks.java │ │ │ ├── baggage │ │ │ └── BaggagePropagationBenchmarks.java │ │ │ ├── handler │ │ │ └── MutableSpanBenchmarks.java │ │ │ ├── http │ │ │ ├── HttpClientBenchmarks.java │ │ │ └── HttpServerBenchmarks.java │ │ │ ├── httpasyncclient │ │ │ └── ApacheHttpAsyncClientBenchmarks.java │ │ │ ├── httpclient │ │ │ └── ApacheHttpClientBenchmarks.java │ │ │ ├── internal │ │ │ ├── PlatformBenchmarks.java │ │ │ ├── codec │ │ │ │ ├── CharSequencesBenchmarks.java │ │ │ │ ├── EntrySplitterBenchmarks.java │ │ │ │ └── ZipkinV2JsonWriterBenchmarks.java │ │ │ └── handler │ │ │ │ └── NoopAwareSpanHandlerBenchmarks.java │ │ │ ├── jaxrs2 │ │ │ ├── JaxRs2ClientBenchmarks.java │ │ │ └── JaxRs2ServerBenchmarks.java │ │ │ ├── jersey │ │ │ └── server │ │ │ │ ├── FakeExtendedUriInfo.java │ │ │ │ ├── JerseyServerBenchmarks.java │ │ │ │ └── TracingApplicationEventListenerAdapterBenchmarks.java │ │ │ ├── jms │ │ │ └── JmsMessageProducerBenchmarks.java │ │ │ ├── kafka │ │ │ └── clients │ │ │ │ └── TracingProducerBenchmarks.java │ │ │ ├── netty │ │ │ └── http │ │ │ │ ├── HelloWorldHandler.java │ │ │ │ └── NettyHttpServerBenchmarks.java │ │ │ ├── okhttp3 │ │ │ └── OkHttpClientBenchmarks.java │ │ │ ├── propagation │ │ │ ├── B3PropagationBenchmarks.java │ │ │ ├── B3SinglePropagationBenchmarks.java │ │ │ └── CurrentTraceContextBenchmarks.java │ │ │ ├── rocketmq │ │ │ └── client │ │ │ │ └── RocketMQProducerBenchmarks.java │ │ │ ├── sampler │ │ │ └── SamplerBenchmarks.java │ │ │ ├── servlet │ │ │ ├── ServletBenchmarks.java │ │ │ └── internal │ │ │ │ └── ServletRuntimeBenchmarks.java │ │ │ └── spring │ │ │ ├── rabbit │ │ │ └── TracingMessagePostProcessorBenchmarks.java │ │ │ ├── web │ │ │ ├── AsyncRestTemplateBenchmarks.java │ │ │ └── RestTemplateBenchmarks.java │ │ │ └── webmvc │ │ │ └── WebMvcBenchmarks.java │ │ └── resources │ │ └── log4j2.properties ├── dubbo │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── brave │ │ │ │ └── dubbo │ │ │ │ ├── DubboClientRequest.java │ │ │ │ ├── DubboClientResponse.java │ │ │ │ ├── DubboParser.java │ │ │ │ ├── DubboRequest.java │ │ │ │ ├── DubboResponse.java │ │ │ │ ├── DubboServerRequest.java │ │ │ │ ├── DubboServerResponse.java │ │ │ │ ├── FinishSpan.java │ │ │ │ └── TracingFilter.java │ │ └── resources │ │ │ └── META-INF │ │ │ └── dubbo │ │ │ └── org.apache.dubbo.rpc.Filter │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── dubbo │ │ │ ├── DubboClientRequestTest.java │ │ │ ├── DubboClientResponseTest.java │ │ │ ├── DubboParserTest.java │ │ │ ├── DubboServerRequestTest.java │ │ │ ├── DubboServerResponseTest.java │ │ │ ├── FinishSpanTest.java │ │ │ ├── GraterService.java │ │ │ ├── GreeterService.java │ │ │ ├── ITTracingFilter.java │ │ │ ├── ITTracingFilter_Consumer.java │ │ │ ├── ITTracingFilter_Provider.java │ │ │ ├── PickUnusedPort.java │ │ │ └── TestServer.java │ │ └── resources │ │ └── log4j2.properties ├── grpc │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── grpc_floor │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ ├── main │ │ │ └── java │ │ │ │ └── io │ │ │ │ └── grpc │ │ │ │ └── examples │ │ │ │ └── helloworld │ │ │ │ ├── GraterGrpc.java │ │ │ │ ├── GreeterGrpc.java │ │ │ │ ├── HelloReply.java │ │ │ │ ├── HelloReplyOrBuilder.java │ │ │ │ ├── HelloRequest.java │ │ │ │ ├── HelloRequestOrBuilder.java │ │ │ │ └── HelloWorldProto.java │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── grpc12 │ │ │ ├── ITTracingClientInterceptor.java │ │ │ └── ITTracingServerInterceptor.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── grpc │ │ │ ├── GrpcClientRequest.java │ │ │ ├── GrpcClientResponse.java │ │ │ ├── GrpcParser.java │ │ │ ├── GrpcPropagation.java │ │ │ ├── GrpcRequest.java │ │ │ ├── GrpcResponse.java │ │ │ ├── GrpcServerRequest.java │ │ │ ├── GrpcServerResponse.java │ │ │ ├── GrpcTracing.java │ │ │ ├── TracingClientInterceptor.java │ │ │ └── TracingServerInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── grpc │ │ │ ├── BaseITTracingClientInterceptor.java │ │ │ ├── BaseITTracingServerInterceptor.java │ │ │ ├── GreeterImpl.java │ │ │ ├── GrpcClientRequestTest.java │ │ │ ├── GrpcClientResponseTest.java │ │ │ ├── GrpcParserTest.java │ │ │ ├── GrpcServerRequestTest.java │ │ │ ├── GrpcServerResponseTest.java │ │ │ ├── ITTracingClientInterceptor.java │ │ │ ├── ITTracingServerInterceptor.java │ │ │ ├── PickUnusedPort.java │ │ │ ├── TestObjects.java │ │ │ └── TestServer.java │ │ ├── proto │ │ └── helloworld.proto │ │ └── resources │ │ └── log4j2.properties ├── http-tests-jakarta │ ├── README.md │ ├── pom.xml │ └── src │ │ └── main │ │ ├── java │ │ └── brave │ │ │ └── test │ │ │ └── jakarta │ │ │ └── http │ │ │ ├── ITServlet5Container.java │ │ │ └── Jetty11ServerController.java │ │ └── resources │ │ └── jetty-logging.properties ├── http-tests │ ├── README.md │ ├── pom.xml │ └── src │ │ ├── main │ │ ├── java │ │ │ └── brave │ │ │ │ └── test │ │ │ │ └── http │ │ │ │ ├── ITHttpAsyncClient.java │ │ │ │ ├── ITHttpClient.java │ │ │ │ ├── ITHttpServer.java │ │ │ │ ├── ITServlet25Container.java │ │ │ │ ├── ITServlet3Container.java │ │ │ │ ├── ITServletContainer.java │ │ │ │ ├── Jetty9ServerController.java │ │ │ │ ├── Log4J2Log.java │ │ │ │ └── ServletContainer.java │ │ └── resources │ │ │ └── log4j2.properties │ │ └── test │ │ └── java │ │ └── brave │ │ └── http │ │ └── features │ │ ├── RequestSamplingTest.java │ │ ├── TracingDispatcher.java │ │ └── TracingInterceptor.java ├── http │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── http │ │ │ ├── HttpClientHandler.java │ │ │ ├── HttpClientRequest.java │ │ │ ├── HttpClientResponse.java │ │ │ ├── HttpHandler.java │ │ │ ├── HttpRequest.java │ │ │ ├── HttpRequestMatchers.java │ │ │ ├── HttpRequestParser.java │ │ │ ├── HttpResponse.java │ │ │ ├── HttpResponseParser.java │ │ │ ├── HttpRuleSampler.java │ │ │ ├── HttpServerHandler.java │ │ │ ├── HttpServerRequest.java │ │ │ ├── HttpServerResponse.java │ │ │ ├── HttpTags.java │ │ │ ├── HttpTracing.java │ │ │ └── HttpTracingCustomizer.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── http │ │ ├── CurrentHttpTracingTest.java │ │ ├── HttpClientHandlerTest.java │ │ ├── HttpClientRequestSetterTest.java │ │ ├── HttpHandlerTest.java │ │ ├── HttpRequestMatchersTest.java │ │ ├── HttpResponseParserTest.java │ │ ├── HttpRuleSamplerTest.java │ │ ├── HttpServerHandlerTest.java │ │ ├── HttpServerRequestTest.java │ │ ├── HttpTagsTest.java │ │ ├── HttpTracingTest.java │ │ └── ITHttpTracingClassLoader.java ├── httpasyncclient │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── httpasyncclient │ │ │ └── TracingHttpAsyncClientBuilder.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── httpasyncclient │ │ ├── HttpResponseWrapperTest.java │ │ ├── ITTracingHttpAsyncClientBuilder.java │ │ └── TracingHttpAsyncClientBuilderTest.java ├── httpclient │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── httpclient_floor │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── httpclient_v43 │ │ │ ├── ITTracingCachingHttpClientBuilder.java │ │ │ └── ITTracingHttpClientBuilder.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── httpclient │ │ │ ├── TracingCachingHttpClientBuilder.java │ │ │ ├── TracingHttpClientBuilder.java │ │ │ ├── TracingMainExec.java │ │ │ └── TracingProtocolExec.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── httpclient │ │ ├── HttpResponseWrapperTest.java │ │ ├── ITTracingCachingHttpClientBuilder.java │ │ └── ITTracingHttpClientBuilder.java ├── httpclient5 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── httpclient5 │ │ │ ├── AsyncExecCallbackWrapper.java │ │ │ ├── AsyncHandleSendHandler.java │ │ │ ├── HandleReceiveHandler.java │ │ │ ├── HandleSendHandler.java │ │ │ ├── HttpClient5Tracing.java │ │ │ ├── HttpClientUtils.java │ │ │ ├── HttpRequestWrapper.java │ │ │ ├── HttpResponseWrapper.java │ │ │ ├── TraceContextCloseScopeInterceptor.java │ │ │ ├── TraceContextFutureCallback.java │ │ │ ├── TraceContextOpenScopeInterceptor.java │ │ │ └── TracingHttpAsyncClient.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── httpclient5 │ │ ├── HttpResponseWrapperTest.java │ │ ├── ITTracingCachingH2ClientBuilder.java │ │ ├── ITTracingCachingHttpAsyncClientBuilder.java │ │ ├── ITTracingCachingHttpClientBuilder.java │ │ ├── ITTracingH2AsyncClientBuilder.java │ │ ├── ITTracingHttpAsyncClientBuilder.java │ │ └── ITTracingHttpClientBuilder.java ├── jakarta-jms │ └── pom.xml ├── jaxrs2 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jaxrs2 │ │ │ ├── ContainerParser.java │ │ │ ├── SpanCustomizingContainerFilter.java │ │ │ └── TracingClientFilter.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jaxrs2 │ │ │ ├── ClientRequestContextWrapperTest.java │ │ │ ├── ClientResponseContextWrapperTest.java │ │ │ ├── ITSpanCustomizingContainerFilter.java │ │ │ ├── ITTracingJaxRSClientBuilder.java │ │ │ ├── InjectionTest.java │ │ │ └── TestResource.java │ │ └── resources │ │ └── log4j2.properties ├── jdbi3 │ ├── RATIONALE.md │ ├── README.md │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jdbi3 │ │ │ ├── JdbiTracing.java │ │ │ └── TracingSqlLogger.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jdbi3 │ │ │ ├── ITJdbiTracing.java │ │ │ ├── MySQLContainer.java │ │ │ └── TracingSqlLoggerTest.java │ │ └── resources │ │ └── log4j2.properties ├── jersey-server-jakarta │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jakarta │ │ │ └── jersey │ │ │ └── server │ │ │ ├── EventParser.java │ │ │ ├── SpanCustomizingApplicationEventListener.java │ │ │ └── TracingApplicationEventListener.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jakarta │ │ │ └── jersey │ │ │ └── server │ │ │ ├── ContainerRequestWrapperTest.java │ │ │ ├── EventParserTest.java │ │ │ ├── ITSpanCustomizingApplicationEventListener.java │ │ │ ├── ITTracingApplicationEventListener.java │ │ │ ├── InjectionTest.java │ │ │ ├── RequestEventWrapperTest.java │ │ │ ├── SpanCustomizingApplicationEventListenerTest.java │ │ │ ├── TestResource.java │ │ │ └── TracingApplicationEventListenerInjectionTest.java │ │ └── resources │ │ └── log4j2.properties ├── jersey-server │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jersey │ │ │ └── server │ │ │ ├── EventParser.java │ │ │ ├── SpanCustomizingApplicationEventListener.java │ │ │ └── TracingApplicationEventListener.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jersey │ │ │ └── server │ │ │ ├── ContainerRequestWrapperTest.java │ │ │ ├── EventParserTest.java │ │ │ ├── ITSpanCustomizingApplicationEventListener.java │ │ │ ├── ITTracingApplicationEventListener.java │ │ │ ├── InjectionTest.java │ │ │ ├── RequestEventWrapperTest.java │ │ │ ├── SpanCustomizingApplicationEventListenerTest.java │ │ │ ├── TestResource.java │ │ │ └── TracingApplicationEventListenerInjectionTest.java │ │ └── resources │ │ └── log4j2.properties ├── jms-jakarta │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── jms30 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── jms │ │ │ ├── ITJmsTracingMessageConsumer.java │ │ │ └── ITJmsTracingMessageProducer.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jakarta │ │ │ └── jms │ │ │ ├── JMSProducerRequest.java │ │ │ ├── JmsTracing.java │ │ │ ├── MessageConsumerRequest.java │ │ │ ├── MessageParser.java │ │ │ ├── MessageProducerRequest.java │ │ │ ├── MessageProperties.java │ │ │ ├── PropertyFilter.java │ │ │ ├── TracingCompletionListener.java │ │ │ ├── TracingConnection.java │ │ │ ├── TracingConnectionConsumer.java │ │ │ ├── TracingConnectionFactory.java │ │ │ ├── TracingConsumer.java │ │ │ ├── TracingExceptionListener.java │ │ │ ├── TracingJMSConsumer.java │ │ │ ├── TracingJMSContext.java │ │ │ ├── TracingJMSProducer.java │ │ │ ├── TracingMessageConsumer.java │ │ │ ├── TracingMessageListener.java │ │ │ ├── TracingMessageProducer.java │ │ │ ├── TracingProducer.java │ │ │ ├── TracingServerSession.java │ │ │ ├── TracingServerSessionPool.java │ │ │ ├── TracingSession.java │ │ │ ├── TracingXAConnection.java │ │ │ ├── TracingXAConnectionFactory.java │ │ │ ├── TracingXAJMSContext.java │ │ │ └── TracingXASession.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jakarta │ │ │ └── jms │ │ │ ├── ITJms.java │ │ │ ├── ITTracingJMSConsumer.java │ │ │ ├── ITTracingJMSProducer.java │ │ │ ├── ITTracingMessageConsumer.java │ │ │ ├── ITTracingMessageProducer.java │ │ │ ├── JmsExtension.java │ │ │ ├── JmsTracingTest.java │ │ │ ├── MessageParserTest.java │ │ │ ├── MessagePropertiesTest.java │ │ │ ├── PropertyFilterTest.java │ │ │ ├── TracingCompletionListenerTest.java │ │ │ ├── TracingJMSConsumerTest.java │ │ │ └── TracingMessageListenerTest.java │ │ └── resources │ │ └── log4j2.properties ├── jms │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── jms11 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── jms │ │ │ ├── ITJmsTracingMessageConsumer.java │ │ │ └── ITJmsTracingMessageProducer.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jms │ │ │ ├── JMS2_0.java │ │ │ ├── JMSProducerRequest.java │ │ │ ├── JmsTracing.java │ │ │ ├── MessageConsumerRequest.java │ │ │ ├── MessageParser.java │ │ │ ├── MessageProducerRequest.java │ │ │ ├── MessageProperties.java │ │ │ ├── PropertyFilter.java │ │ │ ├── TracingCompletionListener.java │ │ │ ├── TracingConnection.java │ │ │ ├── TracingConnectionConsumer.java │ │ │ ├── TracingConnectionFactory.java │ │ │ ├── TracingConsumer.java │ │ │ ├── TracingExceptionListener.java │ │ │ ├── TracingJMSConsumer.java │ │ │ ├── TracingJMSContext.java │ │ │ ├── TracingJMSProducer.java │ │ │ ├── TracingMessageConsumer.java │ │ │ ├── TracingMessageListener.java │ │ │ ├── TracingMessageProducer.java │ │ │ ├── TracingProducer.java │ │ │ ├── TracingServerSession.java │ │ │ ├── TracingServerSessionPool.java │ │ │ ├── TracingSession.java │ │ │ ├── TracingXAConnection.java │ │ │ ├── TracingXAConnectionFactory.java │ │ │ ├── TracingXAJMSContext.java │ │ │ └── TracingXASession.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── jms │ │ │ ├── ArtemisJmsExtension.java │ │ │ ├── ITJms.java │ │ │ ├── ITJms_1_1_TracingMessageConsumer.java │ │ │ ├── ITJms_1_1_TracingMessageProducer.java │ │ │ ├── ITJms_2_0_TracingMessageConsumer.java │ │ │ ├── ITJms_2_0_TracingMessageProducer.java │ │ │ ├── ITTracingJMSConsumer.java │ │ │ ├── ITTracingJMSProducer.java │ │ │ ├── JmsExtension.java │ │ │ ├── JmsTracingTest.java │ │ │ ├── MessageParserTest.java │ │ │ ├── MessagePropertiesTest.java │ │ │ ├── PropertyFilterTest.java │ │ │ ├── TracingCompletionListenerTest.java │ │ │ ├── TracingJMSConsumerTest.java │ │ │ └── TracingMessageListenerTest.java │ │ └── resources │ │ └── log4j2.properties ├── kafka-clients │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── kafka_floor │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── kafka1 │ │ │ └── clients │ │ │ └── ITKafkaTracing.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── kafka │ │ │ └── clients │ │ │ ├── KafkaConsumerRequest.java │ │ │ ├── KafkaHeaders.java │ │ │ ├── KafkaProducerRequest.java │ │ │ ├── KafkaTags.java │ │ │ ├── KafkaTracing.java │ │ │ ├── TracingCallback.java │ │ │ ├── TracingConsumer.java │ │ │ └── TracingProducer.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── kafka │ │ │ └── clients │ │ │ ├── ITKafka.java │ │ │ ├── ITKafkaTracing.java │ │ │ ├── KafkaConsumerRequestSetterTest.java │ │ │ ├── KafkaConsumerRequestTest.java │ │ │ ├── KafkaContainer.java │ │ │ ├── KafkaHeadersTest.java │ │ │ ├── KafkaProducerRequestTest.java │ │ │ ├── KafkaTest.java │ │ │ ├── KafkaTracingTest.java │ │ │ ├── TracingCallbackTest.java │ │ │ ├── TracingConsumerTest.java │ │ │ └── TracingProducerTest.java │ │ └── resources │ │ └── log4j2.properties ├── kafka-streams │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── kafka │ │ │ └── streams │ │ │ ├── BaseTracingProcessor.java │ │ │ ├── KafkaHeaders.java │ │ │ ├── KafkaStreamsPropagation.java │ │ │ ├── KafkaStreamsTags.java │ │ │ ├── KafkaStreamsTracing.java │ │ │ ├── TracingFixedKeyProcessor.java │ │ │ ├── TracingFixedKeyProcessorContext.java │ │ │ ├── TracingFixedKeyProcessorSupplier.java │ │ │ ├── TracingKafkaClientSupplier.java │ │ │ ├── TracingProcessingContext.java │ │ │ ├── TracingProcessor.java │ │ │ ├── TracingProcessorContext.java │ │ │ └── TracingProcessorSupplier.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── kafka │ │ │ └── streams │ │ │ ├── ITKafkaStreams.java │ │ │ ├── ITKafkaStreamsTracing.java │ │ │ ├── KafkaContainer.java │ │ │ ├── KafkaHeadersTest.java │ │ │ ├── KafkaStreamsTest.java │ │ │ ├── KafkaStreamsTracingTest.java │ │ │ └── TracingKafkaClientSupplierTests.java │ │ └── resources │ │ └── log4j2.properties ├── messaging │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── messaging │ │ │ ├── ConsumerRequest.java │ │ │ ├── ConsumerResponse.java │ │ │ ├── MessagingRequest.java │ │ │ ├── MessagingRequestMatchers.java │ │ │ ├── MessagingResponse.java │ │ │ ├── MessagingRuleSampler.java │ │ │ ├── MessagingTracing.java │ │ │ ├── MessagingTracingCustomizer.java │ │ │ ├── ProducerRequest.java │ │ │ └── ProducerResponse.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── messaging │ │ ├── CurrentMessagingTracingTest.java │ │ ├── MessagingRequestMatchersTest.java │ │ ├── MessagingRuleSamplerTest.java │ │ ├── MessagingTracingClassLoaderTest.java │ │ ├── MessagingTracingTest.java │ │ └── features │ │ └── ExampleTest.java ├── mongodb │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── mongodb_floor │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── mongodb_v3 │ │ │ └── ITMongoDBTracing.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── mongodb │ │ │ ├── MongoDBDriver.java │ │ │ ├── MongoDBTracing.java │ │ │ └── TraceMongoCommandListener.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── mongodb │ │ │ ├── ITMongoDBTracing.java │ │ │ ├── MongoDBContainer.java │ │ │ ├── MongoDBDriverTest.java │ │ │ ├── MongoDBTracingTest.java │ │ │ └── TraceMongoCommandListenerTest.java │ │ └── resources │ │ └── log4j2.properties ├── mysql │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── mysql │ │ │ └── TracingStatementInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── mysql │ │ │ ├── ITTracingStatementInterceptor.java │ │ │ └── TracingStatementInterceptorTest.java │ │ └── resources │ │ └── log4j2.properties ├── mysql6 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── mysql6 │ │ │ └── TracingStatementInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── mysql6 │ │ │ ├── ITTracingStatementInterceptor.java │ │ │ └── TracingStatementInterceptorTest.java │ │ └── resources │ │ └── log4j2.properties ├── mysql8 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── mysql8 │ │ │ ├── TracingExceptionInterceptor.java │ │ │ └── TracingQueryInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── mysql8 │ │ │ ├── ITTracingQueryInterceptor.java │ │ │ └── TracingQueryInterceptorTest.java │ │ └── resources │ │ └── log4j2.properties ├── netty-codec-http │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── netty │ │ │ └── http │ │ │ ├── NettyHttpTracing.java │ │ │ └── TracingHttpServerHandler.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── netty │ │ │ └── http │ │ │ ├── HttpResponseWrapperTest.java │ │ │ ├── ITNettyHttpTracing.java │ │ │ └── TestHandler.java │ │ └── resources │ │ └── log4j2.properties ├── okhttp3 │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── okhttp3_floor │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── okhttp3_v3 │ │ │ ├── ITTracingCallFactory.java │ │ │ └── ITTracingInterceptor.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── okhttp3 │ │ │ ├── TraceContextCall.java │ │ │ ├── TracingCallFactory.java │ │ │ └── TracingInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── okhttp3 │ │ │ ├── ITTracingCallFactory.java │ │ │ ├── ITTracingInterceptor.java │ │ │ ├── ResponseWrapperTest.java │ │ │ ├── TracingInterceptorTest.java │ │ │ └── features │ │ │ └── ITRetrofit.java │ │ └── resources │ │ └── log4j2.properties ├── pom.xml ├── rocketmq-client │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── rocketmq │ │ │ └── client │ │ │ ├── AbstractMessageListener.java │ │ │ ├── MessageConsumerRequest.java │ │ │ ├── MessageProducerRequest.java │ │ │ ├── RocketMQTracing.java │ │ │ ├── TracingMessageListenerConcurrently.java │ │ │ ├── TracingMessageListenerOrderly.java │ │ │ └── TracingSendMessageHook.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── rocketmq │ │ │ └── client │ │ │ ├── ITRocketMQTracing.java │ │ │ ├── MessagePropertiesTest.java │ │ │ └── RocketMQContainer.java │ │ └── resources │ │ └── log4j2.properties ├── rpc │ ├── RATIONALE.md │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── rpc │ │ │ ├── RpcClientHandler.java │ │ │ ├── RpcClientRequest.java │ │ │ ├── RpcClientResponse.java │ │ │ ├── RpcHandler.java │ │ │ ├── RpcRequest.java │ │ │ ├── RpcRequestMatchers.java │ │ │ ├── RpcRequestParser.java │ │ │ ├── RpcResponse.java │ │ │ ├── RpcResponseParser.java │ │ │ ├── RpcRuleSampler.java │ │ │ ├── RpcServerHandler.java │ │ │ ├── RpcServerRequest.java │ │ │ ├── RpcServerResponse.java │ │ │ ├── RpcTags.java │ │ │ ├── RpcTracing.java │ │ │ └── RpcTracingCustomizer.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── rpc │ │ ├── CurrentRpcTracingTest.java │ │ ├── ITRpcTracingClassLoader.java │ │ ├── RpcClientHandlerTest.java │ │ ├── RpcClientRequestSetterTest.java │ │ ├── RpcHandlerTest.java │ │ ├── RpcParserTest.java │ │ ├── RpcRequestMatchersTest.java │ │ ├── RpcRequestParserTest.java │ │ ├── RpcResponseParserTest.java │ │ ├── RpcRuleSamplerTest.java │ │ ├── RpcServerHandlerTest.java │ │ ├── RpcTagsTest.java │ │ ├── RpcTracingTest.java │ │ └── features │ │ └── ExampleTest.java ├── servlet-jakarta │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── jakarta │ │ │ └── servlet │ │ │ ├── HttpServletRequestWrapper.java │ │ │ ├── HttpServletResponseWrapper.java │ │ │ ├── TracingFilter.java │ │ │ └── internal │ │ │ └── ServletRuntime.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── jakarta │ │ └── servlet │ │ ├── HttpServletRequestWrapperTest.java │ │ ├── HttpServletResponseWrapperTest.java │ │ └── ITTracingFilter.java ├── servlet │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── servlet25 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ ├── servlet.internal │ │ │ └── ServletRuntime25Test.java │ │ │ └── servlet25 │ │ │ └── ITTracingFilter.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── servlet │ │ │ ├── HttpServletRequestWrapper.java │ │ │ ├── HttpServletResponseWrapper.java │ │ │ ├── TracingFilter.java │ │ │ └── internal │ │ │ └── ServletRuntime.java │ │ └── test │ │ └── java │ │ └── brave │ │ └── servlet │ │ ├── HttpServletRequestWrapperTest.java │ │ ├── HttpServletResponseWrapperTest.java │ │ ├── ITTracingFilter.java │ │ └── internal │ │ └── ServletRuntimeTest.java ├── spring-rabbit │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── spring │ │ │ └── rabbit │ │ │ ├── MessageConsumerRequest.java │ │ │ ├── MessageHeaders.java │ │ │ ├── MessageProducerRequest.java │ │ │ ├── SpringRabbitTracing.java │ │ │ ├── TracingMessagePostProcessor.java │ │ │ └── TracingRabbitListenerAdvice.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── spring │ │ │ └── rabbit │ │ │ ├── ITSpringRabbit.java │ │ │ ├── ITSpringRabbitTracing.java │ │ │ ├── MessageHeadersTest.java │ │ │ ├── SpringRabbitTracingTest.java │ │ │ ├── TracingMessagePostProcessorTest.java │ │ │ └── TracingRabbitListenerAdviceTest.java │ │ └── resources │ │ └── log4j2.properties ├── spring-web │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ └── spring3 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ └── java │ │ │ └── brave │ │ │ └── spring │ │ │ └── web3 │ │ │ └── ITTracingClientHttpRequestInterceptor.java │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── spring │ │ │ └── web │ │ │ ├── TraceContextListenableFuture.java │ │ │ ├── TracingAsyncClientHttpRequestInterceptor.java │ │ │ └── TracingClientHttpRequestInterceptor.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── spring │ │ │ └── web │ │ │ ├── ClientHttpResponseWrapperTest.java │ │ │ ├── HttpRequestWrapperTest.java │ │ │ ├── ITTracingAsyncClientHttpRequestInterceptor.java │ │ │ ├── ITTracingClientHttpRequestInterceptor.java │ │ │ ├── TracingAsyncClientHttpRequestInterceptorAutowireTest.java │ │ │ └── TracingClientHttpRequestInterceptorAutowireTest.java │ │ └── resources │ │ └── log4j2.properties ├── spring-webmvc │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ │ ├── it │ │ ├── servlet25 │ │ │ ├── README.md │ │ │ ├── pom.xml │ │ │ └── src │ │ │ │ └── test │ │ │ │ ├── java │ │ │ │ └── brave │ │ │ │ │ └── spring │ │ │ │ │ └── webmvc │ │ │ │ │ └── ITSpanCustomizingHandlerInterceptor.java │ │ │ │ └── resources │ │ │ │ └── log4j2.properties │ │ └── spring2 │ │ │ ├── pom.xml │ │ │ └── src │ │ │ └── test │ │ │ ├── java │ │ │ └── brave │ │ │ │ └── spring │ │ │ │ └── webmvc │ │ │ │ └── ITSpanCustomizingHandlerInterceptor.java │ │ │ └── resources │ │ │ └── log4j2.properties │ │ ├── main │ │ └── java │ │ │ └── brave │ │ │ └── spring │ │ │ └── webmvc │ │ │ ├── DelegatingTracingFilter.java │ │ │ ├── HandlerParser.java │ │ │ ├── SpanCustomizingAsyncHandlerInterceptor.java │ │ │ ├── SpanCustomizingHandlerInterceptor.java │ │ │ └── WebMvcRuntime.java │ │ └── test │ │ ├── java │ │ └── brave │ │ │ └── spring │ │ │ └── webmvc │ │ │ ├── BaseITSpanCustomizingHandlerInterceptor.java │ │ │ ├── HandlerParserTest.java │ │ │ ├── ITSpanCustomizingAsyncHandlerInterceptor.java │ │ │ ├── ITSpanCustomizingHandlerInterceptor.java │ │ │ ├── Servlet25TestController.java │ │ │ ├── Servlet3TestController.java │ │ │ ├── SpanCustomizingAsyncHandlerInterceptorTest.java │ │ │ ├── SpanCustomizingHandlerInterceptorTest.java │ │ │ └── WebMvcRuntimeTest.java │ │ └── resources │ │ └── log4j2.properties └── vertx-web │ ├── README.md │ ├── bnd.bnd │ ├── pom.xml │ └── src │ ├── main │ └── java │ │ └── brave │ │ └── vertx │ │ └── web │ │ ├── TracingRoutingContextHandler.java │ │ └── VertxWebTracing.java │ └── test │ └── java │ └── brave │ └── vertx │ └── web │ ├── HttpServerResponseWrapperTest.java │ └── ITVertxWebTracing.java ├── mvnw ├── mvnw.cmd ├── pom.xml ├── spring-beans ├── README.md ├── bnd.bnd ├── pom.xml └── src │ ├── it │ └── spring2 │ │ ├── README.md │ │ ├── pom.xml │ │ └── src │ │ └── test │ │ └── resources │ │ └── log4j.properties │ ├── main │ └── java │ │ └── brave │ │ └── spring │ │ └── beans │ │ ├── BaggagePropagationFactoryBean.java │ │ ├── CorrelationScopeDecoratorFactoryBean.java │ │ ├── CurrentTraceContextFactoryBean.java │ │ ├── HttpTracingFactoryBean.java │ │ ├── MessagingTracingFactoryBean.java │ │ ├── RpcTracingFactoryBean.java │ │ ├── SingleBaggageFieldFactoryBean.java │ │ ├── SingleCorrelationFieldFactoryBean.java │ │ └── TracingFactoryBean.java │ └── test │ ├── java │ └── brave │ │ └── spring │ │ └── beans │ │ ├── BaggagePropagationFactoryBeanTest.java │ │ ├── CorrelationScopeDecoratorFactoryBeanTest.java │ │ ├── CurrentTraceContextFactoryBeanTest.java │ │ ├── HttpTracingFactoryBeanTest.java │ │ ├── MessagingTracingFactoryBeanTest.java │ │ ├── RpcTracingFactoryBeanTest.java │ │ ├── SingleBaggageFieldFactoryBeanTest.java │ │ ├── SingleCorrelationFieldFactoryBeanTest.java │ │ ├── TracingFactoryBeanTest.java │ │ └── XmlBeans.java │ └── resources │ └── log4j2.properties └── src ├── etc └── header.txt └── it └── settings.xml /.editorconfig: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright The OpenZipkin Authors 3 | # SPDX-License-Identifier: Apache-2.0 4 | # 5 | 6 | root = true 7 | 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_style = space 12 | indent_size = 2 13 | insert_final_newline = true 14 | trim_trailing_whitespace = true -------------------------------------------------------------------------------- /.github/CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to Zipkin 2 | 3 | If you would like to contribute code, fork this GitHub repository and 4 | send a pull request (on a branch other than `master` or `gh-pages`). 5 | 6 | When submitting code, please apply [Square Code Style](https://github.com/square/java-code-styles). 7 | * If the settings import correctly, CodeStyle/Java will be named Square and use 2 space tab and indent, with 4 space continuation indent. 8 | 9 | You may also want to configure your IDE to perform `null` analysis using Brave's 10 | source retention annotation `brave.internal.Nullable`. For example, in IntelliJ, 11 | search for "Nullable" under "Inspections". Click "Configure Annotations", then 12 | add `brave.internal.Nullable` as a "Nullable Annotation". 13 | 14 | ## License 15 | 16 | By contributing your code, you agree to license your contribution under 17 | the terms of the [APLv2](../LICENSE). 18 | 19 | All files are released with the Apache 2.0 license. 20 | 21 | If you are adding a new file it should have a header like below. This 22 | can be automatically added by running `./mvnw com.mycila:license-maven-plugin:format`. 23 | 24 | ``` 25 | /* 26 | * Copyright The OpenZipkin Authors 27 | * SPDX-License-Identifier: Apache-2.0 28 | */ 29 | ``` 30 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/bug.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Bug 3 | about: If you’ve found a bug, spend the time to write a failing test. Bugs with tests get fixed and stay fixed. If you have a solution in mind, skip raising an issue and open a pull request instead. 4 | labels: bug 5 | --- 6 | ## Describe the Bug 7 | A clear and concise description of what the bug is. If you have a solution in mind, skip raising an issue and open a pull request instead. 8 | 9 | Regardless, the best is to spend some time to write a failing test. Bugs with tests get fixed and stay fixed. 10 | 11 | ## Steps to Reproduce 12 | Steps to reproduce the behavior: 13 | 14 | ## Expected Behaviour 15 | Suggest what you think correct behaviour should be. Note, it may be solved differently depending on the problem. 16 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/config.yml: -------------------------------------------------------------------------------- 1 | blank_issues_enabled: false 2 | contact_links: 3 | - name: Question 4 | url: https://gitter.im/openzipkin/zipkin 5 | about: Please ask questions about how to do something or to understand why something isn't working on our Gitter chat - we'll be happy to respond there in detail. This issue tracker is not for questions. 6 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE/feature.md: -------------------------------------------------------------------------------- 1 | --- 2 | name: Feature Request 3 | about: Please first, look at existing issues to see if the feature has been requested before. 4 | labels: enhancement 5 | --- 6 | Please first, look at [existing issues](https://github.com/openzipkin/brave/issues) to see if the feature has been requested before. If you don't find anything tell us what problem you’re trying to solve. Often a solution already exists! Don’t send pull requests to implement new features without first getting our support. Sometimes we leave features out on purpose to keep the project small. 7 | 8 | ## Feature 9 | Description of the feature 10 | 11 | ## Rationale 12 | Why would this feature help others besides me? 13 | 14 | ## Example Scenario 15 | What kind of use cases would benefit from this feature? 16 | 17 | ## Prior Art 18 | * Links to prior art 19 | * More links 20 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.class 2 | 3 | # Mobile Tools for Java (J2ME) 4 | .mtj.tmp/ 5 | 6 | # Package Files # 7 | *.war 8 | *.ear 9 | 10 | # virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml 11 | hs_err_pid* 12 | 13 | # Maven 14 | target/ 15 | 16 | # IntelliJ 17 | .idea/ 18 | *.iml 19 | 20 | # macOS 21 | .DS_Store 22 | 23 | # Eclipse 24 | .classpath 25 | .project 26 | .settings/ 27 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/openzipkin/brave/6eb165143230762898905f90512e81d9740b842e/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | # Licensed to the Apache Software Foundation (ASF) under one 2 | # or more contributor license agreements. See the NOTICE file 3 | # distributed with this work for additional information 4 | # regarding copyright ownership. The ASF licenses this file 5 | # to you under the Apache License, Version 2.0 (the 6 | # "License"); you may not use this file except in compliance 7 | # with the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, 12 | # software distributed under the License is distributed on an 13 | # "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 14 | # KIND, either express or implied. See the License for the 15 | # specific language governing permissions and limitations 16 | # under the License. 17 | wrapperVersion=3.3.2 18 | distributionType=bin 19 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip 20 | wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.3.2/maven-wrapper-3.3.2.jar 21 | -------------------------------------------------------------------------------- /.settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 12 | 13 | 14 | gpg.passphrase 15 | ${env.GPG_PASSPHRASE} 16 | 17 | 18 | ossrh 19 | ${env.SONATYPE_USER} 20 | ${env.SONATYPE_PASSWORD} 21 | 22 | 23 | github.com 24 | zipkinci 25 | ${env.GH_TOKEN} 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Brave 2 | 3 | Copyright The OpenZipkin Authors 4 | SPDX-License-Identifier: Apache-2.0 5 | 6 | ------------------------------------------------------------------------------- 7 | 8 | This product contains a modified portion of 'InetAddresses', distributed 9 | by Google in the Guava Library: 10 | 11 | * Copyright (C) 2008 The Guava Authors 12 | * License: Apache License v2.0 13 | * Homepage: https://github.com/google/guava 14 | 15 | This product contains a modified portion of 'JsonUtf8Writer', distributed 16 | by Square, Inc in the Moshi Library: 17 | 18 | * Copyright (C) 2010 Google Inc. 19 | * License: Apache License v2.0 20 | * Homepage: https://github.com/square/moshi 21 | 22 | This product contains a modified portion of 'WeakConcurrentMap', distributed 23 | by Rafael Winterhalter in the weak-lock-free Library: 24 | 25 | * License: Apache License v2.0 26 | * Homepage: https://github.com/raphw/weak-lock-free 27 | -------------------------------------------------------------------------------- /SECURITY.md: -------------------------------------------------------------------------------- 1 | # OpenZipkin Security Process 2 | 3 | This document outlines the process for handling security concerns in OpenZipkin projects. 4 | 5 | Any vulnerability or misconfiguration detected in our [security workflow](.github/workflows/security.yml) 6 | should be addressed as a normal pull request. 7 | 8 | OpenZipkin is a volunteer community and does not have a dedicated security team. There may be 9 | periods where no volunteer is able to address a security concern. There is no SLA or warranty 10 | offered by volunteers. If you are a security researcher, please consider this before escalating. 11 | 12 | For security concerns that are sensitive or otherwise outside the scope of public issues, please 13 | contact zipkin-admin@googlegroups.com. 14 | -------------------------------------------------------------------------------- /brave-tests/README.md: -------------------------------------------------------------------------------- 1 | # brave-tests 2 | 3 | This module contains test base classes used to ensure extensions work 4 | portably. 5 | -------------------------------------------------------------------------------- /brave-tests/src/main/java/brave/test/propagation/B3SingleFormatClassLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test.propagation; 6 | 7 | import brave.propagation.B3SingleFormat; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static brave.test.util.ClassLoaders.assertRunIsUnloadable; 11 | 12 | class B3SingleFormatClassLoaderTest { 13 | @Test void unloadable_afterBasicUsage() { 14 | assertRunIsUnloadable(BasicUsage.class, getClass().getClassLoader()); 15 | } 16 | 17 | static class BasicUsage implements Runnable { 18 | @Override public void run() { 19 | String expected = "1234567812345678-1234567812345678-1"; 20 | String written = 21 | B3SingleFormat.writeB3SingleFormat(B3SingleFormat.parseB3SingleFormat(expected).context()); 22 | if (!written.equals(expected)) throw new AssertionError(); 23 | } 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /brave-tests/src/main/java/brave/test/util/GarbageCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test.util; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | /** 10 | * Utilities for working with the garbage collector in tests. 11 | */ 12 | public final class GarbageCollectors { 13 | 14 | /** 15 | * Runs the garbage collector and waits until all of the provided {@link WeakReference} are 16 | * cleared, indicating the referenced objects have been collected. 17 | */ 18 | public static void blockOnGC() { 19 | System.gc(); 20 | try { 21 | Thread.sleep(200); 22 | } catch (InterruptedException e) { 23 | Thread.currentThread().interrupt(); 24 | throw new AssertionError(e); 25 | } 26 | } 27 | 28 | private GarbageCollectors() {} 29 | } 30 | -------------------------------------------------------------------------------- /brave-tests/src/main/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /brave-tests/src/test/java/brave/propagation/InheritableDefaultCurrentTraceContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.test.propagation.CurrentTraceContextTest; 8 | import java.util.function.Supplier; 9 | import org.junit.jupiter.api.BeforeEach; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import static brave.propagation.CurrentTraceContext.Default.INHERITABLE; 13 | import static org.junit.jupiter.api.Assertions.assertThrows; 14 | 15 | class InheritableDefaultCurrentTraceContextTest extends CurrentTraceContextTest { 16 | @Override protected Class> builderSupplier() { 17 | return BuilderSupplier.class; 18 | } 19 | 20 | static class BuilderSupplier implements Supplier { 21 | @Override public CurrentTraceContext.Builder get() { 22 | return new ThreadLocalCurrentTraceContext.Builder(INHERITABLE); 23 | } 24 | } 25 | 26 | @Test protected void isnt_inheritable() { 27 | assertThrows(AssertionError.class, () -> { 28 | super.isnt_inheritable(); 29 | }); 30 | } 31 | 32 | @Test void is_inheritable() throws Exception { 33 | super.is_inheritable(currentTraceContext); 34 | } 35 | 36 | @BeforeEach void ensureNoOtherTestsTaint() { 37 | INHERITABLE.set(null); 38 | CurrentTraceContext.Default.DEFAULT.set(null); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /brave-tests/src/test/java/brave/propagation/ThreadLocalCurrentTraceContextTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.test.propagation.CurrentTraceContextTest; 8 | import java.util.function.Supplier; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | 13 | class ThreadLocalCurrentTraceContextTest extends CurrentTraceContextTest { 14 | @Override protected Class> builderSupplier() { 15 | return BuilderSupplier.class; 16 | } 17 | 18 | /** Since the default thread-local is static, this helps code avoid leaks made by others. */ 19 | @Test void clear_unleaks() { 20 | currentTraceContext.newScope(context); // leak a scope 21 | 22 | assertThat(currentTraceContext.get()).isEqualTo(context); 23 | 24 | ((ThreadLocalCurrentTraceContext) currentTraceContext).clear(); 25 | 26 | assertThat(currentTraceContext.get()).isNull(); 27 | } 28 | 29 | static class BuilderSupplier implements Supplier { 30 | @Override public CurrentTraceContext.Builder get() { 31 | return ThreadLocalCurrentTraceContext.newBuilder(); 32 | } 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /brave-tests/src/test/java/brave/propagation/TraceContextClassLoaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static brave.test.util.ClassLoaders.assertRunIsUnloadable; 10 | 11 | class TraceContextClassLoaderTest { 12 | 13 | @Test void unloadable_afterBasicUsage() { 14 | assertRunIsUnloadable(BasicUsage.class, getClass().getClassLoader()); 15 | } 16 | 17 | static class BasicUsage implements Runnable { 18 | @Override public void run() { 19 | TraceContext.newBuilder().traceId(1).spanId(2).build(); 20 | } 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /brave-tests/src/test/java/brave/propagation/URLConnectionSetterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.propagation.Propagation.Setter; 8 | import brave.test.propagation.PropagationSetterTest; 9 | import java.io.IOException; 10 | import java.net.URI; 11 | import java.net.URLConnection; 12 | 13 | /** Example setter test */ 14 | class URLConnectionSetterTest extends PropagationSetterTest { 15 | final URLConnection request; 16 | 17 | public URLConnectionSetterTest() throws IOException { 18 | request = new URLConnection(URI.create("http://127.0.0.1:9999").toURL()) { 19 | @Override public void connect() { 20 | } 21 | }; 22 | } 23 | 24 | @Override protected URLConnection request() { 25 | return request; 26 | } 27 | 28 | @Override protected Setter setter() { 29 | return URLConnection::setRequestProperty; 30 | } 31 | 32 | @Override protected Iterable read(URLConnection request, String key) { 33 | return request.getRequestProperties().get(key); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /brave-tests/src/test/java/brave/test/ITRemoteTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test; 6 | 7 | import brave.handler.MutableSpan; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class ITRemoteTest { 13 | static final class ITRemoteDummy extends ITRemote { 14 | } 15 | 16 | @Test void tracer_includesClassName() { 17 | ITRemoteDummy itRemote = new ITRemoteDummy(); 18 | itRemote.tracing.tracer().newTrace().start(1L).finish(1L); 19 | 20 | MutableSpan span = itRemote.testSpanHandler.takeLocalSpan(); 21 | assertThat(span.localServiceName()) 22 | .isEqualTo("ITRemoteDummy"); // much better than "unknown" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /brave/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave,\ 5 | brave.baggage,\ 6 | brave.handler,\ 7 | brave.propagation,\ 8 | brave.sampler,\ 9 | brave.internal;braveinternal=true;mandatory:=braveinternal 10 | -------------------------------------------------------------------------------- /brave/src/it/no_deps/README.md: -------------------------------------------------------------------------------- 1 | # no_deps 2 | This tests that Brave has no dependencies, not even on Zipkin 3 | -------------------------------------------------------------------------------- /brave/src/it/no_deps/src/test/java/brave/no_deps/TracingTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.no_deps; 6 | 7 | import brave.ScopedSpan; 8 | import brave.Tracing; 9 | import brave.handler.SpanHandler; 10 | 11 | import org.junit.jupiter.api.Test; 12 | 13 | class TracingTest { 14 | @Test void basicUsage() { 15 | try (Tracing tracing = Tracing.newBuilder().addSpanHandler(new SpanHandler() { 16 | // avoid NOOP short-circuiting tracing 17 | }).build()) { 18 | ScopedSpan parent = tracing.tracer().startScopedSpan("parent"); 19 | tracing.tracer().newChild(parent.context()).finish(); 20 | parent.finish(); 21 | } 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/Clock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | /** 8 | * Epoch microseconds used for {@link brave.Span#start(long)}, {@link brave.Span#finish(long)} and 9 | * {@link brave.Span#annotate(long, String)}. 10 | * 11 | *

This should use the most precise value possible. For example, {@code gettimeofday} or 12 | * multiplying {@link System#currentTimeMillis} by 1000. 13 | * 14 | *

See Instrumenting a service for 15 | * more. 16 | * 17 | *

Note: This type is safe to implement as a lambda, or use as a method reference as it 18 | * is effectively a {@code FunctionalInterface}. It isn't annotated as such because the project has 19 | * a minimum Java language level 6. 20 | * 21 | * @since 4.0 22 | */ 23 | // @FunctionalInterface, except Java language level 6. Do not add methods as it will break API! 24 | public interface Clock { 25 | 26 | long currentTimeMicroseconds(); 27 | } 28 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/CurrentSpanCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | /** 8 | * Provides a mechanism for end users to be able to customise the current span. 9 | * 10 | *

Handles the case of there being no current span in scope. 11 | */ 12 | public final class CurrentSpanCustomizer implements SpanCustomizer { 13 | 14 | private final Tracer tracer; 15 | 16 | /** Creates a span customizer that will affect the current span in scope if present */ 17 | public static CurrentSpanCustomizer create(Tracing tracing) { 18 | return new CurrentSpanCustomizer(tracing); 19 | } 20 | 21 | CurrentSpanCustomizer(Tracing tracing) { 22 | this.tracer = tracing.tracer(); 23 | } 24 | 25 | /** {@inheritDoc} */ 26 | @Override public SpanCustomizer name(String name) { 27 | return tracer.currentSpanCustomizer().name(name); 28 | } 29 | 30 | /** {@inheritDoc} */ 31 | @Override public SpanCustomizer tag(String key, String value) { 32 | return tracer.currentSpanCustomizer().tag(key, value); 33 | } 34 | 35 | /** {@inheritDoc} */ 36 | @Override public SpanCustomizer annotate(String value) { 37 | return tracer.currentSpanCustomizer().annotate(value); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/NoopSpanCustomizer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | /** 8 | * Performs no operations as the span represented by this is not sampled to report to the tracing 9 | * system. 10 | */ 11 | // Preferred to a constant NOOP in SpanCustomizer as the latter ends up in a hierarchy with Span 12 | public enum NoopSpanCustomizer implements SpanCustomizer { 13 | INSTANCE; 14 | 15 | @Override public SpanCustomizer name(String name) { 16 | return this; 17 | } 18 | 19 | @Override public SpanCustomizer tag(String key, String value) { 20 | return this; 21 | } 22 | 23 | @Override public SpanCustomizer annotate(String value) { 24 | return this; 25 | } 26 | 27 | @Override public String toString() { 28 | return "NoopSpanCustomizer{}"; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/SpanCustomizerShield.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | /** This reduces exposure of methods on {@link Span} to those exposed on {@link SpanCustomizer}. */ 8 | final class SpanCustomizerShield implements SpanCustomizer { 9 | final Span delegate; 10 | 11 | SpanCustomizerShield(Span delegate) { 12 | this.delegate = delegate; 13 | } 14 | 15 | @Override public SpanCustomizer name(String name) { 16 | delegate.name(name); 17 | return this; 18 | } 19 | 20 | @Override public SpanCustomizer annotate(String value) { 21 | delegate.annotate(value); 22 | return this; 23 | } 24 | 25 | @Override public SpanCustomizer tag(String key, String value) { 26 | delegate.tag(key, value); 27 | return this; 28 | } 29 | 30 | @Override public String toString() { 31 | return "SpanCustomizer(" + delegate + ")"; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/CorrelationContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal; 6 | 7 | /** 8 | * Dispatches methods to synchronize fields with a context such as SLF4J MDC. 9 | * 10 | *

This is internal: All subtypes of {@link CorrelationContext} are sealed 11 | * to this repository until we better understand implications of making this a public type. 12 | */ 13 | // NOTE: revert to abstract class with protected signatures if this is ever promoted to the 14 | // brave.propagation package. 15 | public interface CorrelationContext { 16 | /** Returns the string property of the specified name or {@code null}. */ 17 | // same as BaggageContext#getValue(BaggageField, TraceContext) 18 | @Nullable String getValue(String name); 19 | 20 | /** Returns false if the update was ignored. */ 21 | // same as BaggageContext#updateValue(BaggageField, TraceContext, String) 22 | boolean update(String name, @Nullable String value); 23 | } 24 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/Nullable.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal; 6 | 7 | /** 8 | * Libraries such as Guice and AutoValue will process any annotation named {@code Nullable}. This 9 | * avoids a dependency on one of the many jsr305 jars, causes problems in OSGi and Java 9 projects 10 | * (where a project is also using jax-ws). 11 | */ 12 | @java.lang.annotation.Documented 13 | @java.lang.annotation.Retention(java.lang.annotation.RetentionPolicy.RUNTIME) 14 | public @interface Nullable { 15 | } 16 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/RecyclableBuffers.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal; 6 | 7 | public final class RecyclableBuffers { 8 | 9 | private static final ThreadLocal PARSE_BUFFER = new ThreadLocal(); 10 | 11 | /** 12 | * Returns a {@link ThreadLocal} reused {@code char[]} for use when decoding bytes into an ID hex 13 | * string. The buffer should be immediately copied into a {@link String} after decoding within the 14 | * same method. 15 | */ 16 | public static char[] parseBuffer() { 17 | char[] idBuffer = PARSE_BUFFER.get(); 18 | if (idBuffer == null) { 19 | idBuffer = new char[32 + 1 + 16 + 3 + 16]; // traceid128-spanid-1-parentid 20 | PARSE_BUFFER.set(idBuffer); 21 | } 22 | return idBuffer; 23 | } 24 | 25 | private RecyclableBuffers() { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/Throwables.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal; 6 | 7 | public final class Throwables { 8 | // Taken from RxJava throwIfFatal, which was taken from scala 9 | public static void propagateIfFatal(Throwable t) { 10 | if (t instanceof VirtualMachineError) { 11 | throw (VirtualMachineError) t; 12 | } else if (t instanceof ThreadDeath) { 13 | throw (ThreadDeath) t; 14 | } else if (t instanceof LinkageError) { 15 | throw (LinkageError) t; 16 | } 17 | } 18 | 19 | Throwables() { 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/baggage/BaggageContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal.baggage; 6 | 7 | import brave.baggage.BaggageField; 8 | import brave.internal.Nullable; 9 | import brave.propagation.TraceContext; 10 | import brave.propagation.TraceContextOrSamplingFlags; 11 | 12 | /** Internal type that implements context storage for the field. */ 13 | public abstract class BaggageContext { 14 | @Nullable 15 | public abstract String getValue(BaggageField field, TraceContextOrSamplingFlags extracted); 16 | 17 | @Nullable public abstract String getValue(BaggageField field, TraceContext context); 18 | 19 | /** Returns false if the update was ignored. */ 20 | public abstract boolean updateValue(BaggageField field, TraceContextOrSamplingFlags extracted, 21 | @Nullable String value); 22 | 23 | /** Returns false if the update was ignored. */ 24 | public abstract boolean updateValue(BaggageField field, TraceContext context, 25 | @Nullable String value); 26 | 27 | /** Appropriate for constants or immutable fields defined in {@link TraceContext}. */ 28 | public static abstract class ReadOnly extends BaggageContext { 29 | @Override public boolean updateValue(BaggageField field, TraceContextOrSamplingFlags extracted, 30 | @Nullable String value) { 31 | return false; 32 | } 33 | 34 | @Override public boolean updateValue(BaggageField field, TraceContext context, String value) { 35 | return false; 36 | } 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/collect/LongBitSet.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal.collect; 6 | 7 | import java.util.BitSet; 8 | 9 | /** 10 | * This is more efficient than {@link BitSet} as this doesn't implicitly allocate arrays. 11 | */ 12 | public final class LongBitSet { 13 | public static final int MAX_SIZE = Long.SIZE; 14 | 15 | public static int size(long bitset) { 16 | return Long.bitCount(bitset); 17 | } 18 | 19 | public static boolean isSet(long bitset, long i) { 20 | return (bitset & (1 << i)) != 0; 21 | } 22 | 23 | public static long setBit(long bitset, long i) { 24 | return bitset | (1 << i); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/internal/recorder/TickClock.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal.recorder; 6 | 7 | import brave.Clock; 8 | import brave.internal.Platform; 9 | 10 | final class TickClock implements Clock { 11 | final Platform platform; 12 | final long baseEpochMicros; 13 | final long baseTickNanos; 14 | 15 | TickClock(Platform platform, long baseEpochMicros, long baseTickNanos) { 16 | this.platform = platform; 17 | this.baseEpochMicros = baseEpochMicros; 18 | this.baseTickNanos = baseTickNanos; 19 | } 20 | 21 | @Override public long currentTimeMicroseconds() { 22 | return ((platform.nanoTime() - baseTickNanos) / 1000) + baseEpochMicros; 23 | } 24 | 25 | @Override public String toString() { 26 | return "TickClock{" 27 | + "baseEpochMicros=" + baseEpochMicros + ", " 28 | + "baseTickNanos=" + baseTickNanos 29 | + "}"; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/propagation/B3SinglePropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * Implements the propagation format described in {@link B3SingleFormat}. 11 | * 12 | *

Use {@link B3Propagation#newFactoryBuilder()} to control inject formats. 13 | */ 14 | public final class B3SinglePropagation { 15 | public static final Propagation.Factory FACTORY = B3Propagation.newFactoryBuilder() 16 | .injectFormat(B3Propagation.Format.SINGLE) 17 | .injectFormat(Span.Kind.CLIENT, B3Propagation.Format.SINGLE) 18 | .injectFormat(Span.Kind.SERVER, B3Propagation.Format.SINGLE) 19 | .build(); 20 | } 21 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/sampler/Matcher.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.sampler; 6 | 7 | /** 8 | * Returns true if this rule matches the input parameters 9 | * 10 | *

Implement {@link #hashCode()} and {@link #equals(Object)} if you want to replace existing 11 | * rules by something besides object identity. 12 | * 13 | * @see Matchers 14 | * @since 5.8 15 | */ 16 | public interface Matcher

{ 17 | boolean matches(P parameters); 18 | } 19 | -------------------------------------------------------------------------------- /brave/src/main/java/brave/sampler/SamplerFunction.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.sampler; 6 | 7 | import brave.Request; 8 | import brave.internal.Nullable; 9 | 10 | /** 11 | * Decides whether to start a new trace based on request properties such as an HTTP path. 12 | * 13 | *

Ex. Here's a sampler that only traces api requests 14 | *

{@code
15 |  * serverSampler = new SamplerFunction() {
16 |  *   @Override public Boolean trySample(HttpRequest request) {
17 |  *     return request.path().startsWith("/api");
18 |  *   }
19 |  * });
20 |  * }
21 | * 22 | * @param type of the input, for example a request or method 23 | * @see SamplerFunctions 24 | * @see Request 25 | * @since 5.8 26 | */ 27 | // interface, not abstract type, to allow backporting of existing samplers. 28 | // This implies we cannot add new methods later, as the bytecode level of Brave core is 1.6 29 | public interface SamplerFunction { 30 | /** 31 | * Returns an overriding sampling decision for a new trace. Returning null is typically used to 32 | * defer to the {@link brave.Tracing#sampler() trace ID sampler}. 33 | * 34 | * @param arg parameter to evaluate for a sampling decision. null input results in a null result 35 | * @return true to sample a new trace or false to deny. Null defers the decision. 36 | * @since 5.8 37 | */ 38 | @Nullable Boolean trySample(@Nullable T arg); 39 | } 40 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/GarbageCollectors.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | import java.lang.ref.WeakReference; 8 | 9 | /** 10 | * Utilities for working with the garbage collector in tests. 11 | */ 12 | public final class GarbageCollectors { 13 | 14 | /** 15 | * Runs the garbage collector and waits until all of the provided {@link WeakReference} are 16 | * cleared, indicating the referenced objects have been collected. 17 | */ 18 | public static void blockOnGC() { 19 | System.gc(); 20 | try { 21 | Thread.sleep(200); 22 | } catch (InterruptedException e) { 23 | Thread.currentThread().interrupt(); 24 | throw new AssertionError(e); 25 | } 26 | } 27 | 28 | private GarbageCollectors() {} 29 | } 30 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/RealSpanCustomizerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | import brave.test.TestSpanHandler; 8 | import org.junit.jupiter.api.AfterEach; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static org.assertj.core.api.Assertions.assertThat; 12 | import static org.assertj.core.api.Assertions.entry; 13 | 14 | class RealSpanCustomizerTest { 15 | TestSpanHandler spans = new TestSpanHandler(); 16 | Tracing tracing = Tracing.newBuilder().addSpanHandler(spans).build(); 17 | Span span = tracing.tracer().newTrace(); 18 | SpanCustomizer spanCustomizer = span.customizer(); 19 | 20 | @AfterEach void close() { 21 | tracing.close(); 22 | } 23 | 24 | @Test void name() { 25 | spanCustomizer.name("foo"); 26 | span.flush(); 27 | 28 | assertThat(spans.get(0).name()) 29 | .isEqualTo("foo"); 30 | } 31 | 32 | @Test void annotate() { 33 | spanCustomizer.annotate("foo"); 34 | span.flush(); 35 | 36 | assertThat(spans.get(0).containsAnnotation("foo")) 37 | .isTrue(); 38 | } 39 | 40 | @Test void tag() { 41 | spanCustomizer.tag("foo", "bar"); 42 | span.flush(); 43 | 44 | assertThat(spans).flatExtracting(s -> s.tags().entrySet()) 45 | .containsExactly(entry("foo", "bar")); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/RequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class RequestTest { 12 | @Test void toString_mentionsDelegate() { 13 | class IceCreamRequest extends Request { 14 | @Override public Span.Kind spanKind() { 15 | return Span.Kind.SERVER; 16 | } 17 | 18 | @Override public Object unwrap() { 19 | return "chocolate"; 20 | } 21 | } 22 | assertThat(new IceCreamRequest()) 23 | .hasToString("IceCreamRequest{chocolate}"); 24 | } 25 | 26 | @Test void toString_doesntStackoverflowWhenUnwrapIsThis() { 27 | class BuggyRequest extends Request { 28 | @Override public Object unwrap() { 29 | return this; 30 | } 31 | 32 | @Override public Span.Kind spanKind() { 33 | return Span.Kind.SERVER; 34 | } 35 | } 36 | assertThat(new BuggyRequest()) 37 | .hasToString("BuggyRequest"); 38 | } 39 | 40 | @Test void toString_doesntNPEWhenUnwrapIsNull() { 41 | class NoRequest extends Request { 42 | @Override public Object unwrap() { 43 | return null; 44 | } 45 | 46 | @Override public Span.Kind spanKind() { 47 | return Span.Kind.SERVER; 48 | } 49 | } 50 | assertThat(new NoRequest()) 51 | .hasToString("NoRequest"); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/SpanCustomizerShieldTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class SpanCustomizerShieldTest { 12 | Tracing tracing = Tracing.newBuilder().build(); 13 | 14 | @Test void doesNotStackOverflowOnToString() { 15 | Span span = tracing.tracer().newTrace(); 16 | SpanCustomizerShield shield = new SpanCustomizerShield(span); 17 | assertThat(shield.toString()) 18 | .isNotEmpty() 19 | .isEqualTo("SpanCustomizer(RealSpan(" + span.context().traceIdString() + "/" + span.context() 20 | .spanIdString() + "))"); 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/baggage/Access.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.baggage; 6 | 7 | import brave.internal.baggage.BaggageCodec; 8 | 9 | public abstract class Access { 10 | /** {@link BaggageCodec} is not yet a public api */ 11 | public static BaggagePropagationConfig newBaggagePropagationConfig( 12 | BaggageCodec baggageCodec, int maxDynamicFields) { 13 | return new BaggagePropagationConfig(baggageCodec, maxDynamicFields); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/features/finagle_context/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** 6 | * This shows how you can reuse finagle's trace context in Brave 7 | */ 8 | package brave.features.finagle_context; 9 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/features/handler/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** 6 | * Shows how {@link brave.handler.SpanHandler} related work. 7 | */ 8 | package brave.features.handler; 9 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/features/opentracing/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** 6 | * It was difficult to implement OpenTracing directly within Brave 3, particularly as spans were 7 | * spread across 3 different tracing abstractions. Now, {@link brave.Span} can implement {@link 8 | * io.opentracing.Span} directly, at least the features that can be mapped to Zipkin. 9 | */ 10 | package brave.features.opentracing; 11 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/features/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.features; 6 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/features/propagation/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | /** 6 | * Before, we had the same algorithm for encoding B3 copy pasted a couple times. We now have a type 7 | * {@link brave.propagation.Propagation} which supplies an implementation such as B3. This includes 8 | * common functions such as how to extract and inject header-based requests. 9 | */ 10 | package brave.features.propagation; 11 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/internal/InternalPropagationTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal; 6 | 7 | import brave.propagation.SamplingFlags; 8 | import brave.propagation.TraceContext; 9 | import org.junit.jupiter.api.Test; 10 | 11 | import static brave.internal.InternalPropagation.FLAG_SAMPLED; 12 | import static brave.internal.InternalPropagation.FLAG_SAMPLED_SET; 13 | import static brave.internal.InternalPropagation.sampled; 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | class InternalPropagationTest { 17 | @Test void set_sampled_true() { 18 | assertThat(sampled(true, 0)) 19 | .isEqualTo(FLAG_SAMPLED_SET + FLAG_SAMPLED); 20 | } 21 | 22 | @Test void set_sampled_false() { 23 | assertThat(sampled(false, FLAG_SAMPLED_SET | FLAG_SAMPLED)) 24 | .isEqualTo(FLAG_SAMPLED_SET); 25 | } 26 | 27 | static { 28 | SamplingFlags.EMPTY.toString(); // ensure wired 29 | } 30 | 31 | @Test void shallowCopy() { 32 | TraceContext context = TraceContext.newBuilder().traceId(1).spanId(2).debug(true) 33 | .addExtra(1L).build(); 34 | 35 | assertThat(InternalPropagation.instance.shallowCopy(context)) 36 | .isNotSameAs(context) 37 | .usingRecursiveComparison() 38 | .isEqualTo(context); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/internal/extra/BasicMapExtra.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal.extra; 6 | 7 | final class BasicMapExtra extends MapExtra { 8 | static final class FactoryBuilder 9 | extends MapExtraFactory.Builder { 10 | @Override protected Factory build() { 11 | return new Factory(this); 12 | } 13 | } 14 | 15 | static final class Factory extends MapExtraFactory { 16 | Factory(FactoryBuilder builder) { 17 | super(builder); 18 | } 19 | 20 | @Override protected BasicMapExtra create() { 21 | return new BasicMapExtra(this); 22 | } 23 | } 24 | 25 | BasicMapExtra(Factory factory) { 26 | super(factory); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/internal/recorder/TickClockTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.internal.recorder; 6 | 7 | import brave.internal.Platform; 8 | import org.junit.jupiter.api.Test; 9 | import org.junit.jupiter.api.extension.ExtendWith; 10 | import org.mockito.Mock; 11 | import org.mockito.junit.jupiter.MockitoExtension; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.when; 15 | 16 | @ExtendWith(MockitoExtension.class) 17 | class TickClockTest { 18 | @Mock Platform platform; 19 | 20 | @Test void relativeTimestamp_incrementsAccordingToNanoTick() { 21 | TickClock clock = new TickClock(platform, 1000L /* 1ms */, 0L /* 0ns */); 22 | 23 | when(platform.nanoTime()).thenReturn(1000L); // 1 microsecond = 1000 nanoseconds 24 | 25 | assertThat(clock.currentTimeMicroseconds()).isEqualTo(1001L); // 1ms + 1us 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/propagation/PropagationConstantsTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.Tracing; 8 | import org.junit.jupiter.api.Test; 9 | 10 | /** Ensures there's no NPE when tracing builder uses defaults */ 11 | class PropagationConstantsTest { 12 | 13 | @Test void eagerReferencePropagationConstantPriorToUse() { 14 | Propagation foo = Propagation.B3_STRING; 15 | Tracing.newBuilder().build().close(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/propagation/PropagationFactoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static org.assertj.core.api.Assertions.assertThat; 10 | 11 | class PropagationFactoryTest { 12 | Propagation.Factory factory = new Propagation.Factory() { 13 | @Override public Propagation get() { 14 | return null; 15 | } 16 | }; 17 | 18 | /** 64 bit trace IDs are not consistently mandatory across propagation, yet. */ 19 | @Test void requires128BitTraceId_defaultsToFalse() { 20 | assertThat(factory.requires128BitTraceId()) 21 | .isFalse(); 22 | } 23 | 24 | /** join (reusing span ID on client and server side) is rarely supported outside B3. */ 25 | @Test void supportsJoin_defaultsToFalse() { 26 | assertThat(B3Propagation.FACTORY.supportsJoin()) 27 | .isTrue(); 28 | assertThat(factory.supportsJoin()) 29 | .isFalse(); 30 | } 31 | 32 | @Test void decorate_defaultsToReturnSameInstance() { 33 | TraceContext context = TraceContext.newBuilder().traceId(1).spanId(1).build(); 34 | assertThat(factory.decorate(context)) 35 | .isSameAs(context); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/propagation/ThreadLocalSpanTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.propagation; 6 | 7 | import brave.Tracing; 8 | import brave.test.TestSpanHandler; 9 | import org.junit.jupiter.api.AfterEach; 10 | import org.junit.jupiter.api.Test; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | 14 | class ThreadLocalSpanTest { 15 | StrictCurrentTraceContext currentTraceContext = StrictCurrentTraceContext.create(); 16 | TestSpanHandler spans = new TestSpanHandler(); 17 | Tracing tracing = Tracing.newBuilder() 18 | .currentTraceContext(currentTraceContext) 19 | .addSpanHandler(spans) 20 | .build(); 21 | 22 | ThreadLocalSpan threadLocalSpan = ThreadLocalSpan.create(tracing.tracer()); 23 | 24 | @AfterEach void close() { 25 | tracing.close(); 26 | currentTraceContext.close(); 27 | } 28 | 29 | @Test void next() { 30 | assertThat(threadLocalSpan.next()) 31 | .isEqualTo(threadLocalSpan.remove()); 32 | } 33 | 34 | @Test void next_extracted() { 35 | assertThat(threadLocalSpan.next(TraceContextOrSamplingFlags.DEBUG)) 36 | .isEqualTo(threadLocalSpan.remove()); 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/sampler/BoundarySamplerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.sampler; 6 | 7 | import org.assertj.core.data.Percentage; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.data.Percentage.withPercentage; 11 | 12 | class BoundarySamplerTest extends SamplerTest { 13 | @Override Sampler newSampler(float probability) { 14 | return BoundarySampler.create(probability); 15 | } 16 | 17 | @Override Percentage expectedErrorProbability() { 18 | return withPercentage(11); 19 | } 20 | 21 | @Test void acceptsOneInTenThousandProbability() { 22 | newSampler(0.0001f); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/sampler/CountingSamplerTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.sampler; 6 | 7 | import org.assertj.core.data.Percentage; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.data.Percentage.withPercentage; 11 | import static org.junit.jupiter.api.Assertions.assertThrows; 12 | 13 | class CountingSamplerTest extends SamplerTest { 14 | @Override Sampler newSampler(float probability) { 15 | return CountingSampler.create(probability); 16 | } 17 | 18 | @Override Percentage expectedErrorProbability() { 19 | return withPercentage(0); 20 | } 21 | 22 | @Test void probabilityMinimumOnePercent() { 23 | assertThrows(IllegalArgumentException.class, () -> { 24 | newSampler(0.0001f); 25 | }); 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /brave/src/test/java/brave/test/TestSpanHandler.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test; 6 | 7 | import brave.handler.MutableSpan; 8 | import brave.handler.SpanHandler; 9 | import brave.propagation.TraceContext; 10 | import java.util.ArrayList; 11 | import java.util.Iterator; 12 | import java.util.List; 13 | 14 | // copy of what's in brave-tests 15 | public final class TestSpanHandler extends SpanHandler implements Iterable { 16 | final List spans = new ArrayList<>(); 17 | 18 | public MutableSpan get(int i) { 19 | return spans.get(i); 20 | } 21 | 22 | public List spans() { 23 | return spans; 24 | } 25 | 26 | @Override public boolean end(TraceContext context, MutableSpan span, Cause cause) { 27 | spans.add(span); 28 | return true; 29 | } 30 | 31 | @Override public Iterator iterator() { 32 | return spans.iterator(); 33 | } 34 | 35 | public void clear() { 36 | spans.clear(); 37 | } 38 | 39 | @Override public String toString() { 40 | return "TestSpanHandler{" + spans + "}"; 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /brave/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /build-bin/configure_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | # This script sets up anything needed for `./deploy`. Do not assume `configure_test` was called. 4 | # 5 | # See [README.md] for an explanation of this and how CI should use it. 6 | build-bin/gpg/configure_gpg 7 | build-bin/maven/maven_go_offline 8 | 9 | # openzipkin/brave publishes Javadoc to https://zipkin.io/brave/ on release 10 | build-bin/git/login_git 11 | -------------------------------------------------------------------------------- /build-bin/configure_test: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | # This script sets up anything needed for `./test`. This should not login to anything, as that 4 | # should be done in `configure_deploy`. 5 | # 6 | # See [README.md] for an explanation of this and how CI should use it. 7 | 8 | # Docker (testcontainers) tests 9 | build-bin/docker/configure_docker 10 | build-bin/maven/maven_go_offline 11 | -------------------------------------------------------------------------------- /build-bin/deploy: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | # This script deploys a master or release version. 4 | # 5 | # See [README.md] for an explanation of this and how CI should use it. 6 | version=${1:-master} 7 | 8 | # Use implicit version when master, if we can.. 9 | if [ "${version}" = "master" ]; then 10 | version=$(sed -En 's/.*(.*)<\/version>.*/\1/p' pom.xml| head -1) 11 | fi 12 | 13 | build-bin/maven/maven_deploy -pl -:brave-bom 14 | 15 | # openzipkin/brave publishes Javadoc to gh-pages (https://zipkin.io/brave/) on release 16 | case ${version} in 17 | *-SNAPSHOT ) 18 | ;; 19 | * ) 20 | build-bin/javadoc_to_gh_pages ${version} 21 | ;; 22 | esac 23 | -------------------------------------------------------------------------------- /build-bin/deploy_bom: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | # Deploy the Bill of Materials (BOM) separately as it is unhooked from the main project intentionally 4 | build-bin/maven/maven_deploy -f brave-bom/pom.xml 5 | -------------------------------------------------------------------------------- /build-bin/docker/configure_docker: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | # Defends against build outages caused by Docker Hub (docker.io) pull rate limits. 8 | # 9 | # It should not login to anything, as that should be done in `configure_docker_push` 10 | 11 | set -ue 12 | 13 | # The below sets up testcontainers configuration, which will be ignored if it isn't used. Even if 14 | # this is Docker related, it is coupled to integration tests configuration invoked with Maven. 15 | # * See https://www.testcontainers.org/supported_docker_environment/image_registry_rate_limiting/ 16 | # * checks.disable=true - saves time and a docker.io pull of alpine 17 | # * ryuk doesn't count against docker.io rate limits because Docker approved testcontainers as OSS 18 | echo checks.disable=true >> ~/.testcontainers.properties 19 | 20 | # We don't use any docker.io images, but add a Google's mirror in case something implicitly does 21 | # * See https://cloud.google.com/container-registry/docs/pulling-cached-images 22 | echo '{ "registry-mirrors": ["https://mirror.gcr.io"] }' | sudo tee /etc/docker/daemon.json 23 | sudo service docker restart 24 | -------------------------------------------------------------------------------- /build-bin/git/login_git: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | set -ue 8 | 9 | # Allocate commits to CI, not the owner of the deploy key 10 | git config user.name "zipkinci" 11 | git config user.email "zipkinci+zipkin-dev@googlegroups.com" 12 | 13 | # Setup https authentication credentials, used by ./mvnw release:prepare 14 | git config credential.helper "store --file=.git/credentials" 15 | echo "https://$GH_TOKEN:@github.com" > .git/credentials 16 | -------------------------------------------------------------------------------- /build-bin/git/version_from_trigger_tag: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | set -ue 8 | 9 | # This script echos a `MAJOR.MINOR.PATCH` version tag based on.. 10 | # * arg1: XXXXX- prefix 11 | # * arg2: XXXXX-MAJOR.MINOR.PATCH git trigger tag 12 | # 13 | # The script exits 1 if the prefix doesn't match. On success, the tag is deleted if it exists. 14 | # 15 | # Note: In CI, `build-bin/git/login_git` must be called before invoking this. 16 | 17 | trigger_tag_prefix=${1?required. Ex docker- to match docker-1.2.3} 18 | trigger_tag=${2?trigger_tag is required. Ex ${trigger_tag_prefix}1.2.3} 19 | 20 | # Checking sed output to determine success as exit code handling in sed or awk is awkward 21 | version=$(echo "${trigger_tag}" | sed -En "s/^${trigger_tag_prefix}([0-9]+\.[0-9]+\.[0-9]+)$/\1/p") 22 | 23 | if [ -z "$version" ]; then 24 | >&2 echo invalid trigger tag: ${trigger_tag} 25 | exit 1; 26 | fi 27 | 28 | # try to cleanup the trigger tag if it exists, but don't fail if it doesn't 29 | git tag -d ${trigger_tag} 2>&- >&- || true 30 | git push origin :${trigger_tag} 2>&- >&- || true 31 | 32 | echo $version 33 | -------------------------------------------------------------------------------- /build-bin/gpg/configure_gpg: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | set -ue 8 | 9 | # This script prepares GPG, needed to sign jars for Sonatype deployment during `maven_deploy` 10 | 11 | # ensure GPG commands work non-interactively 12 | export GPG_TTY=$(tty) 13 | # import signing key used for jar files 14 | echo ${GPG_SIGNING_KEY} | base64 --decode | gpg --batch --passphrase ${GPG_PASSPHRASE} --import 15 | -------------------------------------------------------------------------------- /build-bin/maven/maven_deploy: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | set -ue 8 | 9 | export MAVEN_OPTS="$($(dirname "$0")/maven_opts)" 10 | 11 | # This script deploys a SNAPSHOT or release version to Sonatype. 12 | # 13 | # Note: In CI, `configure_maven_deploy` must be called before invoking this. 14 | ./mvnw --batch-mode -s ./.settings.xml -Prelease -nsu -DskipTests clean deploy $@ 15 | -------------------------------------------------------------------------------- /build-bin/maven/maven_go_offline: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | # This is a go-offline that properly works with multi-module builds 8 | 9 | set -ue 10 | 11 | export MAVEN_OPTS="$($(dirname "$0")/maven_opts)" 12 | if [ -x ./mvnw ]; then alias mvn=${PWD}/mvnw; fi 13 | 14 | ( 15 | if [ "${MAVEN_PROJECT_BASEDIR:-.}" != "." ]; then cd ${MAVEN_PROJECT_BASEDIR}; fi 16 | mvn -q --batch-mode -nsu -Prelease de.qaware.maven:go-offline-maven-plugin:resolve-dependencies "$@" 17 | ) 18 | -------------------------------------------------------------------------------- /build-bin/maven/maven_opts: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # 3 | # Copyright The OpenZipkin Authors 4 | # SPDX-License-Identifier: Apache-2.0 5 | # 6 | 7 | # This script checks each variable value, so it isn't important to fail on unbound (set -u) 8 | set -e 9 | 10 | maven_project_basedir=${MAVEN_PROJECT_BASEDIR:-.} 11 | pom="${maven_project_basedir}/pom.xml" 12 | 13 | # fail if there's no pom 14 | test -f "${pom}" 15 | 16 | arch=$(uname -m) 17 | case ${arch} in 18 | arm64* ) 19 | arch=arm64 20 | ;; 21 | aarch64* ) 22 | arch=arm64 23 | ;; 24 | esac 25 | 26 | maven_opts="${MAVEN_OPTS:-}" 27 | if [ ${arch} = "arm64" ] && [ -f /etc/alpine-release ]; then 28 | # Defensively avoid arm64+alpine problems with posix_spawn 29 | maven_opts="${maven_opts} -Djdk.lang.Process.launchMechanism=vfork" 30 | fi 31 | 32 | echo ${maven_opts} 33 | -------------------------------------------------------------------------------- /build-bin/test: -------------------------------------------------------------------------------- 1 | #!/bin/sh -ue 2 | 3 | # This script runs the tests of the project. 4 | # 5 | # See [README.md] for an explanation of this and how CI should use it. 6 | 7 | # We use install, not verify, because maven-invoker-tests need brave-tests 8 | # installed into the local repository before it can run. 9 | # 10 | # We avoid -T1C because some plugins don't work in parallel and also ITs are 11 | # difficult to debug when failures are in parallel. 12 | ./mvnw install -nsu "$@" 13 | -------------------------------------------------------------------------------- /context/jfr/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.context.jfr 7 | -------------------------------------------------------------------------------- /context/jfr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | io.zipkin.brave 11 | brave-context-parent 12 | 6.3.1-SNAPSHOT 13 | 14 | 4.0.0 15 | 16 | brave-context-jfr 17 | Brave Context: JDK Flight Recorder 18 | 19 | 20 | 21 | brave.context.jfr 22 | 23 | 24 | 11 25 | 11 26 | 11 27 | 28 | ${project.basedir}/../.. 29 | 30 | 31 | 32 | 33 | 34 | maven-compiler-plugin 35 | 36 | ${main.java.version} 37 | 38 | --add-modules 39 | jdk.jfr 40 | 41 | 42 | 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /context/jfr/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) [%X{traceId}/%X{spanId}] - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /context/log4j12/README.md: -------------------------------------------------------------------------------- 1 | # brave-context-log4j12 2 | This adds trace and span IDs to the Log4J v1.2 Mapped Diagnostic Context (MDC) so that you 3 | can search or aggregate logs accordingly. 4 | 5 | To enable this, configure `brave.Tracing` with `MDCScopeDecorator` like so: 6 | 7 | ```java 8 | correlationContext = new Log4jContext(); 9 | tracing = Tracing.newBuilder() 10 | .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() 11 | .addScopeDecorator(MDCScopeDecorator.get()) 12 | .build() 13 | ) 14 | ... 15 | .build(); 16 | ``` 17 | 18 | Then, in your log configuration, you can use `traceId` and `spanId`. 19 | 20 | Here's an example log4j.properties pattern: 21 | 22 | ```xml 23 | appender.console.layout.ConversionPattern = %d{ABSOLUTE} [%X{traceId}/%X{spanId}] %-5p [%t] %C{2} (%F:%L) - %m%n 24 | ``` 25 | 26 | When a trace is in progress, it would log statements like this: 27 | ``` 28 | 11:01:29,799 [e2ffceb485bdfb1d/e2ffceb485bdfb1d] INFO [main] c.a.FooController (FooController.java:30) - I got here! 29 | ``` 30 | 31 | Users could then copy/paste the trace ID into the zipkin UI, or use log 32 | correlation to further debug a problem. 33 | 34 | ## Log4J 1.2.x MDC is inheritable 35 | 36 | Log4J 1.2.x MDC uses an inheritable thread local by default. This means 37 | trace identifiers could leak onto new threads and mislable log lines. If 38 | this is a problem, consider Log4J 2.x or SLF4J which do not inherit by 39 | default. 40 | -------------------------------------------------------------------------------- /context/log4j12/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.CorrelationContext 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.context.log4j12 8 | -------------------------------------------------------------------------------- /context/log4j12/src/it/log4j12/README.md: -------------------------------------------------------------------------------- 1 | # log4j12 2 | This tests that MDCScopeDecorator does not rely on Log4J 2+ APIs. 3 | -------------------------------------------------------------------------------- /context/log4j12/src/it/log4j12/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=INFO, console 2 | log4j.appender.console=org.apache.log4j.ConsoleAppender 3 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.console.layout.ConversionPattern=[%d{dd MMM yyyy HH:mm:ss,SSS}] [%X{traceId}/%X{spanId} - sampled=%X{sampled}] : %m%n 5 | 6 | -------------------------------------------------------------------------------- /context/log4j12/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) [%X{traceId}/%X{spanId} - sampled=%X{sampled}] - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /context/log4j2/README.md: -------------------------------------------------------------------------------- 1 | # brave-context-log4j2 2 | This adds trace and span IDs to the Log4J 2 Thread Context so that you 3 | can search or aggregate logs accordingly. 4 | 5 | To enable this, configure `brave.Tracing` with `ThreadLocalCurrentTraceContext` like so: 6 | 7 | ```java 8 | tracing = Tracing.newBuilder() 9 | .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() 10 | .addScopeDecorator(ThreadContextScopeDecorator.get()) 11 | .build() 12 | ) 13 | ... 14 | .build(); 15 | ``` 16 | 17 | Then, in your log configuration, you can use `traceId` and `spanId`. 18 | 19 | Here's an example log4j2.properties pattern: 20 | 21 | ```xml 22 | appender.console.layout.pattern = %d{ABSOLUTE} [%X{traceId}/%X{spanId}] %-5p [%t] %C{2} (%F:%L) - %m%n 23 | ``` 24 | 25 | When a trace is in progress, it would log statements like this: 26 | ``` 27 | 11:01:29,799 [e2ffceb485bdfb1d/e2ffceb485bdfb1d] INFO [main] c.a.FooController (FooController.java:30) - I got here! 28 | ``` 29 | 30 | Users could then copy/paste the trace ID into the zipkin UI, or use log 31 | correlation to further debug a problem. 32 | -------------------------------------------------------------------------------- /context/log4j2/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.CorrelationContext 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.context.log4j2 8 | -------------------------------------------------------------------------------- /context/log4j2/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) [%X{traceId}/%X{spanId} - sampled=%X{sampled}] - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /context/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 4.0.0 10 | 11 | 12 | io.zipkin.brave 13 | brave-parent 14 | 6.3.1-SNAPSHOT 15 | 16 | 17 | brave-context-parent 18 | Brave: Trace Contexts 19 | pom 20 | 21 | 22 | ${project.basedir}/.. 23 | 24 | 25 | 26 | jfr 27 | slf4j 28 | log4j12 29 | log4j2 30 | 31 | 32 | 33 | 34 | ${project.groupId} 35 | brave 36 | ${project.version} 37 | 38 | 39 | ${project.groupId} 40 | brave-tests 41 | ${project.version} 42 | test 43 | 44 | 45 | 46 | -------------------------------------------------------------------------------- /context/slf4j/README.md: -------------------------------------------------------------------------------- 1 | # brave-context-slf4j 2 | This adds trace and span IDs to the SLF4J Mapped Diagnostic Context (MDC) 3 | so that you can search or aggregate logs accordingly. 4 | 5 | To enable this, configure `brave.Tracing` with `MDCScopeDecorator` like so: 6 | 7 | ```java 8 | correlationContext = new SLF4JContext(); 9 | tracing = Tracing.newBuilder() 10 | .currentTraceContext(ThreadLocalCurrentTraceContext.newBuilder() 11 | .addScopeDecorator(MDCScopeDecorator.get() 12 | .build() 13 | ) 14 | ... 15 | .build(); 16 | ``` 17 | 18 | Then, in your log configuration, you can use `traceId`, `parentId`, `spanId` and `sampled`. 19 | 20 | Here's an example logback configuration: 21 | 22 | ```xml 23 | %d [%X{traceId}/%X{spanId}] [%thread] %-5level %logger{36} - %msg%n 24 | ``` 25 | 26 | When a trace is in progress, it would log statements like this: 27 | ``` 28 | 2017-05-02 23:36:04,789 [fcd015bf6f8b05ba/fcd015bf6f8b05ba] [main] INFO c.a.FooController - I got here! 29 | ``` 30 | 31 | Users could then copy/paste the trace ID into the zipkin UI, or use log 32 | correlation to further debug a problem. 33 | -------------------------------------------------------------------------------- /context/slf4j/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.CorrelationContext 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.context.slf4j 8 | -------------------------------------------------------------------------------- /context/slf4j/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) [%X{traceId}/%X{spanId} - sampled=%X{sampled}] - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/benchmarks/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-benchmarks 2 | 3 | This module includes [JMH](http://openjdk.java.net/projects/code-tools/jmh/) 4 | benchmarks for Brave instrumentation. You can use these to measure overhead 5 | of using Brave. 6 | 7 | ### Running the benchmark 8 | From the project directory, run this to build the benchmarks: 9 | 10 | ```bash 11 | $ ./mvnw install -pl instrumentation/benchmarks -am -Dmaven.test.skip.exec=true` 12 | ``` 13 | 14 | and the following to run them: 15 | 16 | ```bash 17 | $ java -jar instrumentation/benchmarks/target/benchmarks.jar 18 | ``` 19 | -------------------------------------------------------------------------------- /instrumentation/benchmarks/src/test/assembly/test-jar.xml: -------------------------------------------------------------------------------- 1 | 7 | 9 | 12 | test-jar 13 | 14 | jar 15 | 16 | false 17 | 18 | 19 | / 20 | true 21 | true 22 | test 23 | 24 | 25 | 26 | 27 | ${project.build.directory}/test-classes 28 | / 29 | 30 | **/* 31 | 32 | true 33 | 34 | 35 | 36 | -------------------------------------------------------------------------------- /instrumentation/benchmarks/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Licensed to the Apache Software Foundation (ASF) under one or more 3 | # contributor license agreements. See the NOTICE file distributed with 4 | # this work for additional information regarding copyright ownership. 5 | # The ASF licenses this file to You under the Apache License, Version 2.0 6 | # (the "License"); you may not use this file except in compliance with 7 | # the License. You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | # 17 | appenders=console 18 | appender.console.type=Console 19 | appender.console.name=STDOUT 20 | appender.console.layout.type=PatternLayout 21 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 22 | rootLogger.level=info 23 | rootLogger.appenderRefs=stdout 24 | rootLogger.appenderRef.stdout.ref=STDOUT 25 | -------------------------------------------------------------------------------- /instrumentation/dubbo/RATIONALE.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-dubbo rationale 2 | See [RPC](../rpc/RATIONALE.md) for general RPC rationale. 3 | 4 | ## Error code words not numbers 5 | As per normal rationale, we use code names, not numbers, for Dubbo, as defined 6 | in `RpcException`'s constants. In short, this makes trace data more intuitive 7 | and easier to search. 8 | -------------------------------------------------------------------------------- /instrumentation/dubbo/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Platform 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.dubbo 8 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/main/java/brave/dubbo/DubboClientResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import brave.internal.Nullable; 8 | import brave.rpc.RpcClientResponse; 9 | import org.apache.dubbo.rpc.Result; 10 | import org.apache.dubbo.rpc.RpcException; 11 | 12 | final class DubboClientResponse extends RpcClientResponse implements DubboResponse { 13 | final DubboClientRequest request; 14 | @Nullable final Result result; 15 | @Nullable final Throwable error; 16 | 17 | DubboClientResponse( 18 | DubboClientRequest request, @Nullable Result result, @Nullable Throwable error) { 19 | if (request == null) throw new NullPointerException("request == null"); 20 | this.request = request; 21 | this.result = result; 22 | this.error = error; 23 | } 24 | 25 | @Override public Result result() { 26 | return result; 27 | } 28 | 29 | @Override public Result unwrap() { 30 | return result; 31 | } 32 | 33 | @Override public DubboClientRequest request() { 34 | return request; 35 | } 36 | 37 | @Override public Throwable error() { 38 | return error; 39 | } 40 | 41 | /** Returns the string form of the {@link RpcException#getCode()} */ 42 | @Override public String errorCode() { 43 | return DubboParser.errorCode(error); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/main/java/brave/dubbo/DubboRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import brave.rpc.RpcClientRequest; 8 | import brave.rpc.RpcServerRequest; 9 | import brave.rpc.RpcTracing; 10 | import org.apache.dubbo.rpc.Invocation; 11 | import org.apache.dubbo.rpc.Invoker; 12 | 13 | /** 14 | * Used to access Dubbo specific aspects of a client or server request. 15 | * 16 | *

Here's an example that adds default tags, and if Dubbo, Java arguments: 17 | *

{@code
18 |  * rpcTracing = rpcTracingBuilder
19 |  *   .clientRequestParser((req, context, span) -> {
20 |  *      RpcRequestParser.DEFAULT.parse(req, context, span);
21 |  *      if (req instanceof DubboRequest) {
22 |  *        tagArguments(((DubboRequest) req).invocation().getArguments());
23 |  *      }
24 |  *   }).build();
25 |  * }
26 | * 27 | *

Note: Do not implement this type directly. An implementation will be 28 | * either as {@link RpcClientRequest} or an {@link RpcServerRequest}. 29 | * 30 | * @see RpcTracing#clientRequestParser() 31 | * @see RpcTracing#serverRequestParser() 32 | * @see DubboResponse 33 | * @since 5.12 34 | */ 35 | // Note: Unlike Alibaba Dubbo, Apache Dubbo is Java 8+. 36 | // This means we can add default methods later should needs arise. 37 | public interface DubboRequest { 38 | Invoker invoker(); 39 | 40 | Invocation invocation(); 41 | } 42 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/main/java/brave/dubbo/DubboResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import brave.internal.Nullable; 8 | import brave.rpc.RpcClientResponse; 9 | import brave.rpc.RpcServerResponse; 10 | import brave.rpc.RpcTracing; 11 | import org.apache.dubbo.rpc.Result; 12 | 13 | /** 14 | * Used to access Dubbo specific aspects of a client or server response. 15 | * 16 | *

Here's an example that adds default tags, and if Dubbo, the Java result: 17 | *

{@code
18 |  * rpcTracing = rpcTracingBuilder
19 |  *   .clientResponseParser((res, context, span) -> {
20 |  *      RpcResponseParser.DEFAULT.parse(res, context, span);
21 |  *      if (res instanceof DubboResponse) {
22 |  *        DubboResponse dubboResponse = (DubboResponse) res;
23 |  *        if (res.result() != null) {
24 |  *          tagJavaResult(res.result().value());
25 |  *        }
26 |  *      }
27 |  *   }).build();
28 |  * }
29 | * 30 | *

Note: Do not implement this type directly. An implementation will be 31 | * either as {@link RpcClientResponse} or an {@link RpcServerResponse}. 32 | * 33 | * @see RpcTracing#clientResponseParser() 34 | * @see RpcTracing#serverResponseParser() 35 | * @see DubboResponse 36 | * @since 5.12 37 | */ 38 | public interface DubboResponse { 39 | DubboRequest request(); 40 | 41 | @Nullable Result result(); 42 | } 43 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/main/java/brave/dubbo/DubboServerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import brave.internal.Nullable; 8 | import brave.rpc.RpcServerResponse; 9 | import org.apache.dubbo.rpc.Result; 10 | import org.apache.dubbo.rpc.RpcException; 11 | 12 | final class DubboServerResponse extends RpcServerResponse implements DubboResponse { 13 | final DubboServerRequest request; 14 | @Nullable final Result result; 15 | @Nullable final Throwable error; 16 | 17 | DubboServerResponse( 18 | DubboServerRequest request, @Nullable Result result, @Nullable Throwable error) { 19 | if (request == null) throw new NullPointerException("request == null"); 20 | this.request = request; 21 | this.result = result; 22 | this.error = error; 23 | } 24 | 25 | @Override public Result result() { 26 | return result; 27 | } 28 | 29 | @Override public Result unwrap() { 30 | return result; 31 | } 32 | 33 | @Override public DubboServerRequest request() { 34 | return request; 35 | } 36 | 37 | @Override public Throwable error() { 38 | return error; 39 | } 40 | 41 | /** Returns the string form of the {@link RpcException#getCode()} */ 42 | @Override public String errorCode() { 43 | return DubboParser.errorCode(error); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/main/resources/META-INF/dubbo/org.apache.dubbo.rpc.Filter: -------------------------------------------------------------------------------- 1 | tracing=brave.dubbo.TracingFilter 2 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/test/java/brave/dubbo/DubboServerResponseTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import org.apache.dubbo.rpc.Invocation; 8 | import org.apache.dubbo.rpc.Invoker; 9 | import org.apache.dubbo.rpc.Result; 10 | import org.apache.dubbo.rpc.RpcException; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.apache.dubbo.rpc.RpcException.TIMEOUT_EXCEPTION; 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | import static org.mockito.Mockito.mock; 16 | 17 | public class DubboServerResponseTest { 18 | Invoker invoker = mock(Invoker.class); 19 | Invocation invocation = mock(Invocation.class); 20 | Result result = mock(Result.class); 21 | RpcException error = new RpcException(TIMEOUT_EXCEPTION); 22 | DubboServerRequest request = new DubboServerRequest(invoker, invocation); 23 | DubboServerResponse response = new DubboServerResponse(request, result, error); 24 | 25 | @Test void request() { 26 | assertThat(response.request()).isSameAs(request); 27 | } 28 | 29 | @Test void result() { 30 | assertThat(response.result()).isSameAs(result); 31 | } 32 | 33 | @Test void unwrap() { 34 | assertThat(response.unwrap()).isSameAs(result); 35 | } 36 | 37 | @Test void error() { 38 | assertThat(response.error()).isSameAs(error); 39 | } 40 | 41 | @Test void errorCode() { 42 | assertThat(response.errorCode()).isEqualTo("TIMEOUT_EXCEPTION"); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/test/java/brave/dubbo/GraterService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | public interface GraterService { 8 | String sayHello(String name); 9 | } 10 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/test/java/brave/dubbo/GreeterService.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | public interface GreeterService { 8 | String sayHello(String name); 9 | 10 | String sayGoodbye(String name); 11 | } 12 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/test/java/brave/dubbo/PickUnusedPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.dubbo; 6 | 7 | import java.io.IOException; 8 | import java.net.ServerSocket; 9 | 10 | class PickUnusedPort { 11 | static int get() { 12 | try { 13 | ServerSocket serverSocket = new ServerSocket(0); 14 | int port = serverSocket.getLocalPort(); 15 | serverSocket.close(); 16 | return port; 17 | } catch (IOException e) { 18 | throw new AssertionError(e); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /instrumentation/dubbo/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # mute logs that have to do with config re-loading, which is constant during tests 11 | logger.model.name=org.apache.dubbo.rpc.model.ApplicationModel 12 | logger.model.level=off 13 | logger.config.name=org.apache.dubbo.config.AbstractConfig 14 | logger.config.level=off 15 | logger.server.name=org.apache.dubbo.remoting.transport.AbstractServer 16 | logger.server.level=off 17 | logger.spring-extension.name=org.apache.dubbo.config.spring.extension.SpringExtensionFactory 18 | logger.spring-extension.level=off 19 | 20 | # mute dispatcher error as we intentionally dispatch to an unknown route 21 | logger.dispatcher.name=org.apache.dubbo.remoting.transport.dispatcher 22 | logger.dispatcher.level=off 23 | 24 | # mute exception filter as we intentionally test exception paths 25 | logger.exception-filter.name=org.apache.dubbo.rpc.filter.ExceptionFilter 26 | logger.exception-filter.level=off 27 | -------------------------------------------------------------------------------- /instrumentation/grpc/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Platform,MapPropagationFields,PropagationFieldsFactory 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.grpc 8 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/it/grpc_floor/README.md: -------------------------------------------------------------------------------- 1 | # grpc_floor 2 | This tests that GrpcTracing does not require gRPC >1.2 3 | 4 | Note: this uses manually generated protoc sources to remove a compile dependency on protoc. 5 | protoc used gRPC <1.9 did not include aarch64 support, which is something that should be irrelevant 6 | in Java code generators (because Java is platform independent). Also, gRPC 1.9 breaks grpc-trace-bin 7 | propagation, which is something we otherwise want to test. The easiest way out was to check-in 8 | generated sources that match the floor gRPC version 1.2. 9 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/it/grpc_floor/src/main/java/io/grpc/examples/helloworld/HelloReplyOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: helloworld.proto 3 | 4 | package io.grpc.examples.helloworld; 5 | 6 | public interface HelloReplyOrBuilder extends 7 | // @@protoc_insertion_point(interface_extends:helloworld.HelloReply) 8 | com.google.protobuf.MessageOrBuilder { 9 | 10 | /** 11 | * string message = 1; 12 | */ 13 | java.lang.String getMessage(); 14 | /** 15 | * string message = 1; 16 | */ 17 | com.google.protobuf.ByteString 18 | getMessageBytes(); 19 | } 20 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/it/grpc_floor/src/main/java/io/grpc/examples/helloworld/HelloRequestOrBuilder.java: -------------------------------------------------------------------------------- 1 | // Generated by the protocol buffer compiler. DO NOT EDIT! 2 | // source: helloworld.proto 3 | 4 | package io.grpc.examples.helloworld; 5 | 6 | public interface HelloRequestOrBuilder extends 7 | // @@protoc_insertion_point(interface_extends:helloworld.HelloRequest) 8 | com.google.protobuf.MessageOrBuilder { 9 | 10 | /** 11 | * string name = 1; 12 | */ 13 | java.lang.String getName(); 14 | /** 15 | * string name = 1; 16 | */ 17 | com.google.protobuf.ByteString 18 | getNameBytes(); 19 | } 20 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/it/grpc_floor/src/test/java/brave/grpc12/ITTracingClientInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc_floor; 6 | 7 | import brave.grpc.BaseITTracingClientInterceptor; 8 | import io.grpc.ManagedChannelBuilder; 9 | 10 | class ITTracingClientInterceptor extends BaseITTracingClientInterceptor { 11 | @Override protected ManagedChannelBuilder usePlainText(ManagedChannelBuilder builder) { 12 | return builder.usePlaintext(true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/it/grpc_floor/src/test/java/brave/grpc12/ITTracingServerInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc_floor; 6 | 7 | import brave.grpc.BaseITTracingServerInterceptor; 8 | import io.grpc.ManagedChannelBuilder; 9 | 10 | class ITTracingServerInterceptor extends BaseITTracingServerInterceptor { 11 | @Override protected ManagedChannelBuilder usePlainText(ManagedChannelBuilder builder) { 12 | return builder.usePlaintext(true); 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/main/java/brave/grpc/GrpcParser.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import brave.internal.Nullable; 8 | 9 | final class GrpcParser { 10 | @Nullable static String method(String fullMethodName) { 11 | int index = fullMethodName.lastIndexOf('/'); 12 | if (index == -1 || index == 0) return null; 13 | return fullMethodName.substring(index + 1); 14 | } 15 | 16 | @Nullable static String service(String fullMethodName) { 17 | int index = fullMethodName.lastIndexOf('/'); 18 | if (index == -1 || index == 0) return null; 19 | return fullMethodName.substring(0, index); 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/main/java/brave/grpc/GrpcPropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import brave.baggage.BaggagePropagation; 8 | import brave.propagation.Propagation; 9 | import io.grpc.Metadata; 10 | import io.grpc.Metadata.Key; 11 | import java.util.LinkedHashMap; 12 | import java.util.Map; 13 | 14 | final class GrpcPropagation { 15 | /** Creates constant keys for use in propagating trace identifiers or baggage. */ 16 | static Map> nameToKey(Propagation propagation) { 17 | Map> result = new LinkedHashMap>(); 18 | for (String keyName : propagation.keys()) { 19 | result.put(keyName, Key.of(keyName, Metadata.ASCII_STRING_MARSHALLER)); 20 | } 21 | for (String keyName : BaggagePropagation.allKeyNames(propagation)) { 22 | result.put(keyName, Key.of(keyName, Metadata.ASCII_STRING_MARSHALLER)); 23 | } 24 | return result; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/java/brave/grpc/GrpcParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static brave.grpc.TestObjects.METHOD_DESCRIPTOR; 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | class GrpcParserTest { 13 | @Test void method() { 14 | assertThat(GrpcParser.method(METHOD_DESCRIPTOR.getFullMethodName())) 15 | .isEqualTo("SayHello"); 16 | } 17 | 18 | @Test void method_malformed() { 19 | assertThat(GrpcParser.method("/")).isNull(); 20 | } 21 | 22 | @Test void service() { 23 | assertThat(GrpcParser.service(METHOD_DESCRIPTOR.getFullMethodName())) 24 | .isEqualTo("helloworld.Greeter"); 25 | } 26 | 27 | @Test void service_malformed() { 28 | assertThat(GrpcParser.service("/")).isNull(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/java/brave/grpc/ITTracingClientInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import io.grpc.ManagedChannelBuilder; 8 | 9 | class ITTracingClientInterceptor extends BaseITTracingClientInterceptor { 10 | @Override protected ManagedChannelBuilder usePlainText(ManagedChannelBuilder builder) { 11 | return builder.usePlaintext(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/java/brave/grpc/ITTracingServerInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import io.grpc.ManagedChannelBuilder; 8 | 9 | class ITTracingServerInterceptor extends BaseITTracingServerInterceptor { 10 | @Override protected ManagedChannelBuilder usePlainText(ManagedChannelBuilder builder) { 11 | return builder.usePlaintext(); 12 | } 13 | } 14 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/java/brave/grpc/PickUnusedPort.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import java.io.IOException; 8 | import java.net.ServerSocket; 9 | 10 | class PickUnusedPort { 11 | static int get() { 12 | try { 13 | ServerSocket serverSocket = new ServerSocket(0); 14 | int port = serverSocket.getLocalPort(); 15 | serverSocket.close(); 16 | return port; 17 | } catch (IOException e) { 18 | throw new AssertionError(e); 19 | } 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/java/brave/grpc/TestObjects.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.grpc; 6 | 7 | import io.grpc.MethodDescriptor; 8 | import java.io.ByteArrayInputStream; 9 | import java.io.InputStream; 10 | 11 | final class TestObjects { 12 | // Allows invoker tests to run without needing to compile protos 13 | static final MethodDescriptor METHOD_DESCRIPTOR = 14 | MethodDescriptor.newBuilder() 15 | .setType(MethodDescriptor.MethodType.UNARY) 16 | .setFullMethodName("helloworld.Greeter/SayHello") 17 | .setRequestMarshaller(VoidMarshaller.INSTANCE) 18 | .setResponseMarshaller(VoidMarshaller.INSTANCE) 19 | .build(); 20 | 21 | enum VoidMarshaller implements MethodDescriptor.Marshaller { 22 | INSTANCE; 23 | 24 | @Override public InputStream stream(Void value) { 25 | return new ByteArrayInputStream(new byte[0]); 26 | } 27 | 28 | @Override public Void parse(InputStream stream) { 29 | return null; 30 | } 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/proto/helloworld.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | 3 | option java_multiple_files = true; 4 | option java_package = "io.grpc.examples.helloworld"; 5 | option java_outer_classname = "HelloWorldProto"; 6 | 7 | package helloworld; 8 | 9 | // The greeting service definition. 10 | service Greeter { 11 | // Sends a greeting 12 | rpc SayHello (HelloRequest) returns (HelloReply); 13 | rpc SayHelloWithManyReplies (HelloRequest) returns (stream HelloReply); 14 | } 15 | 16 | // intentionally different to test service not found 17 | service Grater { 18 | // Sends a greeting 19 | rpc SeyHallo (HelloRequest) returns (HelloReply); 20 | } 21 | 22 | // The request message containing the user's name. 23 | message HelloRequest { 24 | string name = 1; 25 | } 26 | 27 | // The response message containing the greetings 28 | message HelloReply { 29 | string message = 1; 30 | } 31 | 32 | -------------------------------------------------------------------------------- /instrumentation/grpc/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) [%X{traceId}/%X{spanId}] - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # our tests intentionally create errors, but we don't to see them normally 11 | logger.SerializingExecutor.name=io.grpc.internal.SerializingExecutor 12 | logger.SerializingExecutor.level=off 13 | -------------------------------------------------------------------------------- /instrumentation/http-tests-jakarta/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-http-tests-jakarta 2 | 3 | This module contains test base classes used to ensure instrumentation 4 | work portably. 5 | -------------------------------------------------------------------------------- /instrumentation/http-tests-jakarta/src/main/java/brave/test/jakarta/http/Jetty11ServerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test.jakarta.http; 6 | 7 | import brave.test.http.ServletContainer.ServerController; 8 | import org.eclipse.jetty.server.Connector; 9 | import org.eclipse.jetty.server.Server; 10 | import org.eclipse.jetty.server.ServerConnector; 11 | 12 | public final class Jetty11ServerController implements ServerController { 13 | @Override public Server newServer(int port) { 14 | Server result = new Server(); 15 | ServerConnector connector = new ServerConnector(result); 16 | connector.setPort(port); 17 | connector.setIdleTimeout(1000 * 60 * 60); 18 | result.setConnectors(new Connector[] {connector}); 19 | return result; 20 | } 21 | 22 | @Override public int getLocalPort(Server server) { 23 | return ((ServerConnector) server.getConnectors()[0]).getLocalPort(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /instrumentation/http-tests-jakarta/src/main/resources/jetty-logging.properties: -------------------------------------------------------------------------------- 1 | org.eclipse.jetty.LEVEL=WARN -------------------------------------------------------------------------------- /instrumentation/http-tests/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-http-tests 2 | 3 | This module contains test base classes used to ensure instrumentation 4 | work portably. 5 | -------------------------------------------------------------------------------- /instrumentation/http-tests/src/main/java/brave/test/http/Jetty9ServerController.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.test.http; 6 | 7 | import brave.test.http.ServletContainer.ServerController; 8 | import org.eclipse.jetty.server.Connector; 9 | import org.eclipse.jetty.server.Server; 10 | import org.eclipse.jetty.server.ServerConnector; 11 | 12 | public final class Jetty9ServerController implements ServerController { 13 | @Override public Server newServer(int port) { 14 | Server result = new Server(); 15 | ServerConnector connector = new ServerConnector(result); 16 | connector.setPort(port); 17 | connector.setIdleTimeout(1000 * 60 * 60); 18 | result.setConnectors(new Connector[] {connector}); 19 | return result; 20 | } 21 | 22 | @Override public int getLocalPort(Server server) { 23 | return ((ServerConnector) server.getConnectors()[0]).getLocalPort(); 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /instrumentation/http-tests/src/main/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/http/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.http 7 | -------------------------------------------------------------------------------- /instrumentation/http/src/main/java/brave/http/HttpClientResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.http; 6 | 7 | import brave.Span; 8 | import brave.internal.Nullable; 9 | 10 | /** 11 | * Marks an interface for use in {@link HttpClientHandler#handleReceive(HttpClientResponse, Span)}. 12 | * This gives a standard type to consider when parsing an incoming context. 13 | * 14 | * @see HttpClientRequest 15 | * @since 5.7 16 | */ 17 | public abstract class HttpClientResponse extends HttpResponse { 18 | @Override public final Span.Kind spanKind() { 19 | return Span.Kind.CLIENT; 20 | } 21 | 22 | /** {@inheritDoc} */ 23 | @Override @Nullable public HttpClientRequest request() { 24 | return null; 25 | } 26 | 27 | @Override public Throwable error() { 28 | return null; // error() was added in v5.10, but this type was added in v5.7 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instrumentation/http/src/main/java/brave/http/HttpServerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.http; 6 | 7 | import brave.Span; 8 | import brave.internal.Nullable; 9 | 10 | /** 11 | * Marks an interface for use in {@link HttpServerHandler#handleSend(Object, Throwable, Span)}. This 12 | * gives a standard type to consider when parsing an outgoing context. 13 | * 14 | * @see HttpServerRequest 15 | * @since 5.7 16 | */ 17 | public abstract class HttpServerResponse extends HttpResponse { 18 | @Override public final Span.Kind spanKind() { 19 | return Span.Kind.SERVER; 20 | } 21 | 22 | /** {@inheritDoc} */ 23 | @Override @Nullable public HttpServerRequest request() { 24 | return null; 25 | } 26 | 27 | @Override public Throwable error() { 28 | return null; // error() was added in v5.10, but this type was added in v5.7 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instrumentation/http/src/test/java/brave/http/HttpResponseParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.http; 6 | 7 | import org.junit.jupiter.api.Test; 8 | 9 | import static brave.http.HttpResponseParser.Default.catchAllName; 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class HttpResponseParserTest { 13 | 14 | @Test void catchAllName_redirect() { 15 | assertThat(catchAllName("GET", 307)) 16 | .isEqualTo("GET redirected"); // zipkin will implicitly lowercase this 17 | } 18 | 19 | @Test void routeBasedName_notFound() { 20 | assertThat(catchAllName("DELETE", 404)) 21 | .isEqualTo("DELETE not_found"); // zipkin will implicitly lowercase this 22 | } 23 | 24 | @Test void notCatchAll() { 25 | assertThat(catchAllName("GET", 304)) 26 | .isNull(); // not redirect 27 | assertThat(catchAllName("DELETE", 500)) 28 | .isNull(); // not redirect or not found 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instrumentation/httpasyncclient/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-httpasyncclient 2 | This module contains a tracing decorator for [Apache HttpAsyncClient](https://hc.apache.org/httpcomponents-asyncclient-dev/) 4.0+. 3 | `TracingHttpAsyncClientBuilder` adds trace headers to outgoing requests. It 4 | then reports to Zipkin how long each request takes, along with relevant 5 | tags like the http url. 6 | 7 | To enable tracing, create your client using `TracingHttpAsyncClientBuilder`. 8 | 9 | ```java 10 | httpasyncclient = TracingHttpAsyncClientBuilder.create(tracing).build(); 11 | ``` 12 | -------------------------------------------------------------------------------- /instrumentation/httpasyncclient/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.httpasyncclient 7 | -------------------------------------------------------------------------------- /instrumentation/httpclient/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-httpclient 2 | This module contains a tracing decorator for [Apache HttpClient](http://hc.apache.org/httpcomponents-client-4.3.x/index.html) 4.3+. 3 | `TracingHttpClientBuilder` adds trace headers to outgoing requests. It 4 | then reports to Zipkin how long each request takes, along with relevant 5 | tags like the http url. 6 | 7 | To enable tracing, create your client using `TracingHttpClientBuilder`. 8 | 9 | ```java 10 | httpclient = TracingHttpClientBuilder.create(tracing).build(); 11 | ``` 12 | 13 | You can also use `TracingCachingHttpClientBuilder` if you depend on 14 | `org.apache.httpcomponents:httpclient-cache` 15 | -------------------------------------------------------------------------------- /instrumentation/httpclient/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.httpclient 7 | -------------------------------------------------------------------------------- /instrumentation/httpclient/src/it/httpclient_floor/README.md: -------------------------------------------------------------------------------- 1 | # httpclient_floor 2 | This tests that TracingHttpClientBuilder can be used with httpclient 4.3 3 | -------------------------------------------------------------------------------- /instrumentation/httpclient/src/it/httpclient_floor/src/test/java/brave/httpclient_v43/ITTracingCachingHttpClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient_floor; 6 | 7 | class ITTracingCachingHttpClientBuilder 8 | extends brave.httpclient.ITTracingCachingHttpClientBuilder { 9 | } 10 | -------------------------------------------------------------------------------- /instrumentation/httpclient/src/it/httpclient_floor/src/test/java/brave/httpclient_v43/ITTracingHttpClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient_floor; 6 | 7 | class ITTracingHttpClientBuilder extends brave.httpclient.ITTracingHttpClientBuilder { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/httpclient/src/main/java/brave/httpclient/TracingHttpClientBuilder.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient; 6 | 7 | import brave.Tracing; 8 | import brave.http.HttpTracing; 9 | import org.apache.http.impl.client.HttpClientBuilder; 10 | import org.apache.http.impl.execchain.ClientExecChain; 11 | 12 | public final class TracingHttpClientBuilder extends HttpClientBuilder { 13 | 14 | public static HttpClientBuilder create(Tracing tracing) { 15 | return new TracingHttpClientBuilder(HttpTracing.create(tracing)); 16 | } 17 | 18 | public static HttpClientBuilder create(HttpTracing httpTracing) { 19 | return new TracingHttpClientBuilder(httpTracing); 20 | } 21 | 22 | final HttpTracing httpTracing; 23 | 24 | TracingHttpClientBuilder(HttpTracing httpTracing) { // intentionally hidden 25 | if (httpTracing == null) throw new NullPointerException("HttpTracing == null"); 26 | this.httpTracing = httpTracing; 27 | } 28 | 29 | @Override protected ClientExecChain decorateProtocolExec(ClientExecChain protocolExec) { 30 | return new TracingProtocolExec(httpTracing, protocolExec); 31 | } 32 | 33 | @Override protected ClientExecChain decorateMainExec(ClientExecChain exec) { 34 | return new TracingMainExec(httpTracing, exec); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-httpclient5 2 | This module contains a tracing decorator for [Apache HttpClient](http://hc.apache.org/httpcomponents-client-5.2.x/index.html) 5.2+. 3 | `HttpClient5Tracing` adds trace headers to outgoing requests. It 4 | then reports to Zipkin how long each request takes, along with relevant 5 | tags like the http url. 6 | 7 | To enable tracing, create your client using `HttpClient5Tracing`. 8 | 9 | ```java 10 | HttpClientBuilder httpClientBuilder = HttpClients.custom(); 11 | httpclient = HttpClient5Tracing.newBuilder(httpTracing).create(httpClientBuilder); 12 | ``` 13 | 14 | `HttpClient5Tracing` also supports `CachingHttpClientBuilder`, `HttpAsyncClientBuilder`, 15 | `CachingHttpAsyncClientBuilder`, `H2AsyncClientBuilder` and `CachingH2AsyncClientBuilder`. 16 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.httpclient5 7 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/src/main/java/brave/httpclient5/HttpResponseWrapper.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient5; 6 | 7 | import brave.http.HttpClientResponse; 8 | import brave.internal.Nullable; 9 | import org.apache.hc.core5.http.HttpResponse; 10 | 11 | final class HttpResponseWrapper extends HttpClientResponse { 12 | @Nullable final HttpRequestWrapper request; 13 | @Nullable final HttpResponse response; 14 | @Nullable final Throwable error; 15 | 16 | HttpResponseWrapper(@Nullable HttpResponse response, @Nullable HttpRequestWrapper request, 17 | @Nullable Throwable error) { 18 | this.request = request; 19 | this.response = response; 20 | this.error = error; 21 | } 22 | 23 | @Override 24 | @Nullable 25 | public Object unwrap() { 26 | return response; 27 | } 28 | 29 | @Override 30 | @Nullable 31 | public HttpRequestWrapper request() { 32 | return request; 33 | } 34 | 35 | @Override 36 | public Throwable error() { 37 | return error; 38 | } 39 | 40 | @Override 41 | public int statusCode() { 42 | if (response == null) { 43 | return 0; 44 | } 45 | return response.getCode(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/src/main/java/brave/httpclient5/TraceContextCloseScopeInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient5; 6 | 7 | import org.apache.hc.core5.http.EntityDetails; 8 | import org.apache.hc.core5.http.HttpRequest; 9 | import org.apache.hc.core5.http.HttpRequestInterceptor; 10 | import org.apache.hc.core5.http.HttpResponse; 11 | import org.apache.hc.core5.http.HttpResponseInterceptor; 12 | import org.apache.hc.core5.http.protocol.HttpContext; 13 | 14 | class TraceContextCloseScopeInterceptor implements HttpRequestInterceptor, 15 | HttpResponseInterceptor { 16 | 17 | @Override public void process(HttpRequest httpRequest, EntityDetails entityDetails, 18 | HttpContext httpContext) { 19 | HttpClientUtils.closeScope(httpContext); 20 | } 21 | 22 | @Override public void process(HttpResponse httpResponse, 23 | EntityDetails entityDetails, HttpContext httpContext) { 24 | HttpClientUtils.closeScope(httpContext); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/src/main/java/brave/httpclient5/TraceContextOpenScopeInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient5; 6 | 7 | import brave.propagation.CurrentTraceContext; 8 | import org.apache.hc.core5.http.EntityDetails; 9 | import org.apache.hc.core5.http.HttpRequest; 10 | import org.apache.hc.core5.http.HttpRequestInterceptor; 11 | import org.apache.hc.core5.http.HttpResponse; 12 | import org.apache.hc.core5.http.HttpResponseInterceptor; 13 | import org.apache.hc.core5.http.protocol.HttpContext; 14 | 15 | class TraceContextOpenScopeInterceptor implements HttpRequestInterceptor, 16 | HttpResponseInterceptor { 17 | 18 | final CurrentTraceContext currentTraceContext; 19 | 20 | public TraceContextOpenScopeInterceptor(CurrentTraceContext currentTraceContext) { 21 | this.currentTraceContext = currentTraceContext; 22 | } 23 | 24 | @Override public void process(HttpRequest httpRequest, EntityDetails entityDetails, 25 | HttpContext httpContext) { 26 | HttpClientUtils.openScope(httpContext, currentTraceContext); 27 | } 28 | 29 | @Override public void process(HttpResponse httpResponse, 30 | EntityDetails entityDetails, HttpContext httpContext) { 31 | HttpClientUtils.openScope(httpContext, currentTraceContext); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/httpclient5/src/test/java/brave/httpclient5/HttpResponseWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.httpclient5; 6 | 7 | import org.apache.hc.core5.http.HttpRequest; 8 | import org.apache.hc.core5.http.HttpResponse; 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.ExtendWith; 11 | import org.mockito.Mock; 12 | import org.mockito.junit.jupiter.MockitoExtension; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | import static org.mockito.Mockito.when; 16 | 17 | @ExtendWith(MockitoExtension.class) 18 | public class HttpResponseWrapperTest { 19 | @Mock HttpRequest request; 20 | @Mock HttpResponse response; 21 | 22 | @Test void request() { 23 | assertThat( 24 | new HttpResponseWrapper(response, new HttpRequestWrapper(request, null), null).request() 25 | .unwrap()) 26 | .isSameAs(request); 27 | } 28 | 29 | @Test void statusCode() { 30 | when(response.getCode()).thenReturn(200); 31 | assertThat(new HttpResponseWrapper(response, new HttpRequestWrapper(request, null), 32 | null).statusCode()).isEqualTo(200); 33 | } 34 | 35 | @Test void statusCode_zeroWhenNoResponse() { 36 | assertThat(new HttpResponseWrapper(null, new HttpRequestWrapper(request, null), 37 | null).statusCode()).isZero(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /instrumentation/jakarta-jms/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | io.zipkin.brave 11 | brave-instrumentation-parent 12 | 6.3.1-SNAPSHOT 13 | 14 | 4.0.0 15 | 16 | brave-instrumentation-jakarta-jms 17 | Brave Instrumentation: JMS (Jakarta) - Relocation Artifact 18 | 19 | 20 | true 21 | 22 | 23 | 24 | 25 | brave-instrumentation-jms-jakarta 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /instrumentation/jaxrs2/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.jaxrs2 5 | -------------------------------------------------------------------------------- /instrumentation/jaxrs2/src/test/java/brave/jaxrs2/ClientResponseContextWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jaxrs2; 6 | 7 | import brave.jaxrs2.TracingClientFilter.ClientResponseContextWrapper; 8 | import javax.ws.rs.client.ClientRequestContext; 9 | import javax.ws.rs.client.ClientResponseContext; 10 | import org.junit.jupiter.api.Test; 11 | import org.junit.jupiter.api.extension.ExtendWith; 12 | import org.mockito.Mock; 13 | import org.mockito.junit.jupiter.MockitoExtension; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | import static org.mockito.Mockito.when; 17 | 18 | @ExtendWith(MockitoExtension.class) 19 | public class ClientResponseContextWrapperTest { 20 | @Mock ClientRequestContext request; 21 | @Mock ClientResponseContext response; 22 | 23 | @Test void request() { 24 | assertThat(new ClientResponseContextWrapper(request, response).request().unwrap()) 25 | .isSameAs(request); 26 | } 27 | 28 | @Test void statusCode() { 29 | when(response.getStatus()).thenReturn(200); 30 | 31 | assertThat(new ClientResponseContextWrapper(request, response).statusCode()).isEqualTo(200); 32 | } 33 | 34 | @Test void statusCode_zeroWhenNegative() { 35 | when(response.getStatus()).thenReturn(-1); 36 | 37 | assertThat(new ClientResponseContextWrapper(request, response).statusCode()).isZero(); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /instrumentation/jaxrs2/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/jdbi3/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-jdbi3 2 | 3 | This includes [TracingSqlLogger][TracingSqlLogger] for the Jdbi instance that 4 | reports via Brave how long each query takes, along with relevant tags like the 5 | query. 6 | 7 | Example Usage: 8 | ```java 9 | SqlLogger sqlLogger = JdbiTracing.create(tracing).sqlLogger(); 10 | jdbi.getConfig(SqlStatements.class).setSqlLogger(sqlLogger); 11 | ``` 12 | 13 | --- 14 | [TracingSqlLogger]: src/main/java/brave/jdbi3/TracingSqlLogger.java 15 | -------------------------------------------------------------------------------- /instrumentation/jdbi3/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/jersey-server-jakarta/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.jakarta.jersey.server 7 | -------------------------------------------------------------------------------- /instrumentation/jersey-server-jakarta/src/test/java/brave/jakarta/jersey/server/ContainerRequestWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jersey.server; 6 | 7 | import brave.jakarta.jersey.server.TracingApplicationEventListener.ContainerRequestWrapper; 8 | import java.net.URI; 9 | import org.glassfish.jersey.server.ContainerRequest; 10 | import org.glassfish.jersey.server.ExtendedUriInfo; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | import static org.mockito.Mockito.when; 16 | 17 | public class ContainerRequestWrapperTest { 18 | ContainerRequest request = mock(ContainerRequest.class); 19 | 20 | @Test void path_prefixesSlashWhenMissing() { 21 | when(request.getPath(false)).thenReturn("bar"); 22 | 23 | assertThat(new ContainerRequestWrapper(request).path()) 24 | .isEqualTo("/bar"); 25 | } 26 | 27 | @Test void url_derivedFromExtendedUriInfo() { 28 | ExtendedUriInfo uriInfo = mock(ExtendedUriInfo.class); 29 | when(request.getUriInfo()).thenReturn(uriInfo); 30 | when(uriInfo.getRequestUri()).thenReturn(URI.create("http://foo:8080/bar?hello=world")); 31 | 32 | assertThat(new ContainerRequestWrapper(request).url()) 33 | .isEqualTo("http://foo:8080/bar?hello=world"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /instrumentation/jersey-server-jakarta/src/test/java/brave/jakarta/jersey/server/EventParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jersey.server; 6 | 7 | import brave.SpanCustomizer; 8 | import org.glassfish.jersey.server.ContainerRequest; 9 | import org.glassfish.jersey.server.ExtendedUriInfo; 10 | import org.glassfish.jersey.server.monitoring.RequestEvent; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.mockito.Mock; 14 | import org.mockito.junit.jupiter.MockitoExtension; 15 | 16 | import static org.mockito.Mockito.verifyNoMoreInteractions; 17 | import static org.mockito.Mockito.when; 18 | 19 | @ExtendWith(MockitoExtension.class) 20 | public class EventParserTest { 21 | @Mock RequestEvent event; 22 | @Mock ContainerRequest request; 23 | @Mock ExtendedUriInfo uriInfo; 24 | @Mock SpanCustomizer customizer; 25 | 26 | EventParser eventParser = new EventParser(); 27 | 28 | @Test void requestMatched_missingResourceMethodOk() { 29 | when(event.getContainerRequest()).thenReturn(request); 30 | when(request.getUriInfo()).thenReturn(uriInfo); 31 | 32 | eventParser.requestMatched(event, customizer); 33 | 34 | verifyNoMoreInteractions(customizer); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /instrumentation/jersey-server-jakarta/src/test/java/brave/jakarta/jersey/server/TracingApplicationEventListenerInjectionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jersey.server; 6 | 7 | import brave.Tracing; 8 | import brave.http.HttpTracing; 9 | import com.google.inject.AbstractModule; 10 | import com.google.inject.Guice; 11 | import com.google.inject.Injector; 12 | import org.junit.jupiter.api.AfterEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | 17 | public class TracingApplicationEventListenerInjectionTest { 18 | Tracing tracing = Tracing.newBuilder().build(); 19 | 20 | Injector injector = Guice.createInjector(new AbstractModule() { 21 | @Override protected void configure() { 22 | bind(HttpTracing.class).toInstance(HttpTracing.create(tracing)); 23 | } 24 | }); 25 | 26 | @AfterEach void close() { 27 | tracing.close(); 28 | } 29 | 30 | @Test void onlyRequiresHttpTracing() { 31 | assertThat(injector.getInstance(TracingApplicationEventListener.class)) 32 | .isNotNull(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /instrumentation/jersey-server-jakarta/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # mute logs that do not effect our tests 11 | logger.wadl.name=org.glassfish.jersey.server.wadl.WadlFeature 12 | logger.wadl.level=off 13 | logger.model.name=org.glassfish.jersey.internal.inject.Providers 14 | logger.model.level=off 15 | -------------------------------------------------------------------------------- /instrumentation/jersey-server/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.jersey.server 7 | -------------------------------------------------------------------------------- /instrumentation/jersey-server/src/test/java/brave/jersey/server/ContainerRequestWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jersey.server; 6 | 7 | import brave.jersey.server.TracingApplicationEventListener.ContainerRequestWrapper; 8 | import java.net.URI; 9 | import org.glassfish.jersey.server.ContainerRequest; 10 | import org.glassfish.jersey.server.ExtendedUriInfo; 11 | import org.junit.jupiter.api.Test; 12 | 13 | import static org.assertj.core.api.Assertions.assertThat; 14 | import static org.mockito.Mockito.mock; 15 | import static org.mockito.Mockito.when; 16 | 17 | public class ContainerRequestWrapperTest { 18 | ContainerRequest request = mock(ContainerRequest.class); 19 | 20 | @Test void path_prefixesSlashWhenMissing() { 21 | when(request.getPath(false)).thenReturn("bar"); 22 | 23 | assertThat(new ContainerRequestWrapper(request).path()) 24 | .isEqualTo("/bar"); 25 | } 26 | 27 | @Test void url_derivedFromExtendedUriInfo() { 28 | ExtendedUriInfo uriInfo = mock(ExtendedUriInfo.class); 29 | when(request.getUriInfo()).thenReturn(uriInfo); 30 | when(uriInfo.getRequestUri()).thenReturn(URI.create("http://foo:8080/bar?hello=world")); 31 | 32 | assertThat(new ContainerRequestWrapper(request).url()) 33 | .isEqualTo("http://foo:8080/bar?hello=world"); 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /instrumentation/jersey-server/src/test/java/brave/jersey/server/EventParserTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jersey.server; 6 | 7 | import brave.SpanCustomizer; 8 | import org.glassfish.jersey.server.ContainerRequest; 9 | import org.glassfish.jersey.server.ExtendedUriInfo; 10 | import org.glassfish.jersey.server.monitoring.RequestEvent; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.mockito.Mock; 14 | import org.mockito.junit.jupiter.MockitoExtension; 15 | 16 | import static org.mockito.Mockito.verifyNoMoreInteractions; 17 | import static org.mockito.Mockito.when; 18 | 19 | @ExtendWith(MockitoExtension.class) 20 | public class EventParserTest { 21 | @Mock RequestEvent event; 22 | @Mock ContainerRequest request; 23 | @Mock ExtendedUriInfo uriInfo; 24 | @Mock SpanCustomizer customizer; 25 | 26 | EventParser eventParser = new EventParser(); 27 | 28 | @Test void requestMatched_missingResourceMethodOk() { 29 | when(event.getContainerRequest()).thenReturn(request); 30 | when(request.getUriInfo()).thenReturn(uriInfo); 31 | 32 | eventParser.requestMatched(event, customizer); 33 | 34 | verifyNoMoreInteractions(customizer); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /instrumentation/jersey-server/src/test/java/brave/jersey/server/TracingApplicationEventListenerInjectionTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jersey.server; 6 | 7 | import brave.Tracing; 8 | import brave.http.HttpTracing; 9 | import com.google.inject.AbstractModule; 10 | import com.google.inject.Guice; 11 | import com.google.inject.Injector; 12 | import org.junit.jupiter.api.AfterEach; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static org.assertj.core.api.Assertions.assertThat; 16 | 17 | public class TracingApplicationEventListenerInjectionTest { 18 | Tracing tracing = Tracing.newBuilder().build(); 19 | 20 | Injector injector = Guice.createInjector(new AbstractModule() { 21 | @Override protected void configure() { 22 | bind(HttpTracing.class).toInstance(HttpTracing.create(tracing)); 23 | } 24 | }); 25 | 26 | @AfterEach void close() { 27 | tracing.close(); 28 | } 29 | 30 | @Test void onlyRequiresHttpTracing() { 31 | assertThat(injector.getInstance(TracingApplicationEventListener.class)) 32 | .isNotNull(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /instrumentation/jersey-server/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # mute logs that do not effect our tests 11 | logger.wadl.name=org.glassfish.jersey.server.wadl.WadlFeature 12 | logger.wadl.level=off 13 | logger.model.name=org.glassfish.jersey.internal.inject.Providers 14 | logger.model.level=off 15 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Throwables 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.jakarta.jms 8 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/it/jms30/README.md: -------------------------------------------------------------------------------- 1 | # Jakarta JMS 3.0 2 | This tests that JmsTracing does work on Jakarta JMS 3.0 APIs 3 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/it/jms30/src/test/java/brave/jms/ITJmsTracingMessageConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | class ITJmsTracingMessageConsumer extends ITTracingMessageConsumer { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/it/jms30/src/test/java/brave/jms/ITJmsTracingMessageProducer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | class ITJmsTracingMessageProducer extends ITTracingMessageProducer { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/main/java/brave/jakarta/jms/MessageProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | import brave.internal.Nullable; 8 | import jakarta.jms.Message; 9 | 10 | import static brave.internal.Throwables.propagateIfFatal; 11 | import static brave.jakarta.jms.JmsTracing.log; 12 | 13 | class MessageProperties { 14 | /** 15 | * Same as {@link Message#getStringProperty(String)}, just doesn't throw or coerce non-strings to 16 | * strings. 17 | */ 18 | @Nullable static String getPropertyIfString(Message message, String name) { 19 | try { 20 | Object o = message.getObjectProperty(name); 21 | if (o instanceof String) return o.toString(); 22 | return null; 23 | } catch (Throwable t) { 24 | propagateIfFatal(t); 25 | log(t, "error getting property {0} from message {1}", name, message); 26 | return null; 27 | } 28 | } 29 | 30 | /** Same as {@link Message#setStringProperty(String, String)}, just doesn't throw. */ 31 | static void setStringProperty(Message message, String name, String value) { 32 | try { 33 | message.setStringProperty(name, value); 34 | } catch (Throwable t) { 35 | propagateIfFatal(t); 36 | log(t, "error setting property {0} on message {1}", name, message); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/main/java/brave/jakarta/jms/TracingConnectionConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | import jakarta.jms.ConnectionConsumer; 8 | import jakarta.jms.JMSException; 9 | import jakarta.jms.ServerSessionPool; 10 | 11 | final class TracingConnectionConsumer implements ConnectionConsumer { 12 | static ConnectionConsumer create(ConnectionConsumer delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("connectionConsumer == null"); 14 | if (delegate instanceof TracingConnectionConsumer) return delegate; 15 | return new TracingConnectionConsumer(delegate, jmsTracing); 16 | } 17 | 18 | final ConnectionConsumer delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingConnectionConsumer(ConnectionConsumer delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public ServerSessionPool getServerSessionPool() throws JMSException { 27 | return TracingServerSessionPool.create(delegate.getServerSessionPool(), jmsTracing); 28 | } 29 | 30 | @Override public void close() throws JMSException { 31 | delegate.close(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/main/java/brave/jakarta/jms/TracingServerSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | import jakarta.jms.JMSException; 8 | import jakarta.jms.ServerSession; 9 | import jakarta.jms.Session; 10 | 11 | final class TracingServerSession implements ServerSession { 12 | static ServerSession create(ServerSession delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("serverSession == null"); 14 | if (delegate instanceof TracingServerSession) return delegate; 15 | return new TracingServerSession(delegate, jmsTracing); 16 | } 17 | 18 | final ServerSession delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingServerSession(ServerSession delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public Session getSession() throws JMSException { 27 | return TracingSession.create(delegate.getSession(), jmsTracing); 28 | } 29 | 30 | @Override public void start() throws JMSException { 31 | delegate.start(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/main/java/brave/jakarta/jms/TracingServerSessionPool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | import jakarta.jms.JMSException; 8 | import jakarta.jms.ServerSession; 9 | import jakarta.jms.ServerSessionPool; 10 | 11 | final class TracingServerSessionPool implements ServerSessionPool { 12 | static ServerSessionPool create(ServerSessionPool delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("serverSessionPool == null"); 14 | if (delegate instanceof TracingServerSessionPool) return delegate; 15 | return new TracingServerSessionPool(delegate, jmsTracing); 16 | } 17 | 18 | final ServerSessionPool delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingServerSessionPool(ServerSessionPool delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public ServerSession getServerSession() throws JMSException { 27 | return TracingServerSession.create(delegate.getServerSession(), jmsTracing); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/main/java/brave/jakarta/jms/TracingXAJMSContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jakarta.jms; 6 | 7 | import jakarta.jms.JMSContext; 8 | import jakarta.jms.XAJMSContext; 9 | import javax.transaction.xa.XAResource; 10 | 11 | final class TracingXAJMSContext extends TracingJMSContext implements XAJMSContext { 12 | static XAJMSContext create(XAJMSContext delegate, JmsTracing jmsTracing) { 13 | if (delegate instanceof TracingXAJMSContext) return delegate; 14 | return new TracingXAJMSContext(delegate, jmsTracing); 15 | } 16 | 17 | TracingXAJMSContext(XAJMSContext delegate, JmsTracing jmsTracing) { 18 | super(delegate, jmsTracing); 19 | } 20 | 21 | @Override public JMSContext getContext() { 22 | return this; 23 | } 24 | 25 | @Override public XAResource getXAResource() { 26 | return ((XAJMSContext) delegate).getXAResource(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /instrumentation/jms-jakarta/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # don't log about missing DLQ config 11 | logger.artemis-server.name=org.apache.activemq.artemis.core.server 12 | logger.artemis-server.level=off 13 | -------------------------------------------------------------------------------- /instrumentation/jms/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Throwables 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.jms 8 | -------------------------------------------------------------------------------- /instrumentation/jms/src/it/jms11/README.md: -------------------------------------------------------------------------------- 1 | # Jms 1.1 2 | This tests that JmsTracing does not rely on JMS 2.0 apis 3 | -------------------------------------------------------------------------------- /instrumentation/jms/src/it/jms11/src/test/java/brave/jms/ITJmsTracingMessageConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | class ITJmsTracingMessageConsumer extends ITJms_1_1_TracingMessageConsumer { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/jms/src/it/jms11/src/test/java/brave/jms/ITJmsTracingMessageProducer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | class ITJmsTracingMessageProducer extends ITJms_1_1_TracingMessageProducer { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/JMS2_0.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import java.lang.annotation.ElementType; 8 | import java.lang.annotation.RetentionPolicy; 9 | 10 | /** 11 | * Indicates a type or method is only available since JMS 2.0, mainly to be careful so we don't 12 | * break JMS 1.1. 13 | * 14 | *

For example, a wrapped method on a type present in JMS 1.1, but defined in JMS 2.0, should 15 | * not use {@linkplain Override}. 16 | */ 17 | @java.lang.annotation.Documented 18 | @java.lang.annotation.Retention(RetentionPolicy.SOURCE) 19 | @java.lang.annotation.Target({ElementType.TYPE, ElementType.METHOD}) @interface JMS2_0 { 20 | } -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/MessageProperties.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import brave.internal.Nullable; 8 | import javax.jms.Message; 9 | 10 | import static brave.internal.Throwables.propagateIfFatal; 11 | import static brave.jms.JmsTracing.log; 12 | 13 | class MessageProperties { 14 | /** 15 | * Same as {@link Message#getStringProperty(String)}, just doesn't throw or coerce non-strings to 16 | * strings. 17 | */ 18 | @Nullable static String getPropertyIfString(Message message, String name) { 19 | try { 20 | Object o = message.getObjectProperty(name); 21 | if (o instanceof String) return o.toString(); 22 | return null; 23 | } catch (Throwable t) { 24 | propagateIfFatal(t); 25 | log(t, "error getting property {0} from message {1}", name, message); 26 | return null; 27 | } 28 | } 29 | 30 | /** Same as {@link Message#setStringProperty(String, String)}, just doesn't throw. */ 31 | static void setStringProperty(Message message, String name, String value) { 32 | try { 33 | message.setStringProperty(name, value); 34 | } catch (Throwable t) { 35 | propagateIfFatal(t); 36 | log(t, "error setting property {0} on message {1}", name, message); 37 | } 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/TracingConnectionConsumer.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import javax.jms.ConnectionConsumer; 8 | import javax.jms.JMSException; 9 | import javax.jms.ServerSessionPool; 10 | 11 | final class TracingConnectionConsumer implements ConnectionConsumer { 12 | static ConnectionConsumer create(ConnectionConsumer delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("connectionConsumer == null"); 14 | if (delegate instanceof TracingConnectionConsumer) return delegate; 15 | return new TracingConnectionConsumer(delegate, jmsTracing); 16 | } 17 | 18 | final ConnectionConsumer delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingConnectionConsumer(ConnectionConsumer delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public ServerSessionPool getServerSessionPool() throws JMSException { 27 | return TracingServerSessionPool.create(delegate.getServerSessionPool(), jmsTracing); 28 | } 29 | 30 | @Override public void close() throws JMSException { 31 | delegate.close(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/TracingServerSession.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import javax.jms.JMSException; 8 | import javax.jms.ServerSession; 9 | import javax.jms.Session; 10 | 11 | final class TracingServerSession implements ServerSession { 12 | static ServerSession create(ServerSession delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("serverSession == null"); 14 | if (delegate instanceof TracingServerSession) return delegate; 15 | return new TracingServerSession(delegate, jmsTracing); 16 | } 17 | 18 | final ServerSession delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingServerSession(ServerSession delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public Session getSession() throws JMSException { 27 | return TracingSession.create(delegate.getSession(), jmsTracing); 28 | } 29 | 30 | @Override public void start() throws JMSException { 31 | delegate.start(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/TracingServerSessionPool.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import javax.jms.JMSException; 8 | import javax.jms.ServerSession; 9 | import javax.jms.ServerSessionPool; 10 | 11 | final class TracingServerSessionPool implements ServerSessionPool { 12 | static ServerSessionPool create(ServerSessionPool delegate, JmsTracing jmsTracing) { 13 | if (delegate == null) throw new NullPointerException("serverSessionPool == null"); 14 | if (delegate instanceof TracingServerSessionPool) return delegate; 15 | return new TracingServerSessionPool(delegate, jmsTracing); 16 | } 17 | 18 | final ServerSessionPool delegate; 19 | final JmsTracing jmsTracing; 20 | 21 | TracingServerSessionPool(ServerSessionPool delegate, JmsTracing jmsTracing) { 22 | this.delegate = delegate; 23 | this.jmsTracing = jmsTracing; 24 | } 25 | 26 | @Override public ServerSession getServerSession() throws JMSException { 27 | return TracingServerSession.create(delegate.getServerSession(), jmsTracing); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /instrumentation/jms/src/main/java/brave/jms/TracingXAJMSContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.jms; 6 | 7 | import javax.jms.JMSContext; 8 | import javax.jms.XAJMSContext; 9 | import javax.transaction.xa.XAResource; 10 | 11 | @JMS2_0 final class TracingXAJMSContext extends TracingJMSContext implements XAJMSContext { 12 | static XAJMSContext create(XAJMSContext delegate, JmsTracing jmsTracing) { 13 | if (delegate instanceof TracingXAJMSContext) return delegate; 14 | return new TracingXAJMSContext(delegate, jmsTracing); 15 | } 16 | 17 | TracingXAJMSContext(XAJMSContext delegate, JmsTracing jmsTracing) { 18 | super(delegate, jmsTracing); 19 | } 20 | 21 | @Override public JMSContext getContext() { 22 | return this; 23 | } 24 | 25 | @Override public XAResource getXAResource() { 26 | return ((XAJMSContext) delegate).getXAResource(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /instrumentation/jms/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | 10 | # don't log about missing DLQ config 11 | logger.artemis-server.name=org.apache.activemq.artemis.core.server 12 | logger.artemis-server.level=off 13 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.kafka.clients 7 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/it/kafka_floor/README.md: -------------------------------------------------------------------------------- 1 | # kafka_floor 2 | This tests that KafkaPropagation can be used with kafka-client v<2 3 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/it/kafka_floor/src/test/java/brave/kafka1/clients/ITKafkaTracing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka_floor.clients; 6 | 7 | class ITKafkaTracing extends brave.kafka.clients.ITKafkaTracing { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/main/java/brave/kafka/clients/KafkaHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import brave.internal.Nullable; 8 | import org.apache.kafka.common.header.Header; 9 | import org.apache.kafka.common.header.Headers; 10 | 11 | import static brave.kafka.clients.KafkaTracing.log; 12 | import static java.nio.charset.StandardCharsets.UTF_8; 13 | 14 | final class KafkaHeaders { 15 | static void replaceHeader(Headers headers, String key, String value) { 16 | try { 17 | headers.remove(key); 18 | headers.add(key, value.getBytes(UTF_8)); 19 | } catch (IllegalStateException e) { 20 | log(e, "error setting header {0} in headers {1}", key, headers); 21 | } 22 | } 23 | 24 | @Nullable static String lastStringHeader(Headers headers, String key) { 25 | Header header = headers.lastHeader(key); 26 | if (header == null || header.value() == null) return null; 27 | return new String(header.value(), UTF_8); 28 | } 29 | 30 | KafkaHeaders() { 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/main/java/brave/kafka/clients/KafkaTags.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import org.apache.kafka.clients.consumer.Consumer; 8 | import org.apache.kafka.clients.consumer.ConsumerRecord; 9 | import org.apache.kafka.clients.producer.Producer; 10 | 11 | /** 12 | * Tagging policy is not yet dynamic. The descriptions below reflect static policy. 13 | */ 14 | final class KafkaTags { 15 | /** 16 | * Added on {@link KafkaTracing#producer(Producer) producer} and {@link 17 | * KafkaTracing#nextSpan(ConsumerRecord) processor} spans when the key not null or empty. 18 | * 19 | *

Note: this is not added on {@link KafkaTracing#consumer(Consumer) consumer} spans 20 | * as they represent a bulk task (potentially multiple keys). 21 | */ 22 | static final String KAFKA_KEY_TAG = "kafka.key"; 23 | static final String KAFKA_TOPIC_TAG = "kafka.topic"; 24 | } 25 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/test/java/brave/kafka/clients/ITKafka.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import brave.messaging.MessagingTracing; 8 | import brave.test.ITRemote; 9 | import brave.test.util.AssertableCallback; 10 | import org.apache.kafka.clients.producer.Callback; 11 | import org.apache.kafka.clients.producer.RecordMetadata; 12 | 13 | abstract class ITKafka extends ITRemote { 14 | MessagingTracing messagingTracing = MessagingTracing.create(tracing); 15 | KafkaTracing kafkaTracing = KafkaTracing.create(messagingTracing); 16 | 17 | /** {@link #join()} waits for the callback to complete without any errors */ 18 | static final class BlockingCallback implements Callback { 19 | final AssertableCallback delegate = new AssertableCallback<>(); 20 | 21 | void join() { 22 | delegate.join(); 23 | } 24 | 25 | @Override public void onCompletion(RecordMetadata metadata, Exception exception) { 26 | if (exception != null) { 27 | delegate.onError(exception); 28 | } else { 29 | delegate.onSuccess(metadata); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/test/java/brave/kafka/clients/KafkaConsumerRequestSetterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import brave.propagation.Propagation; 8 | import brave.test.propagation.PropagationSetterTest; 9 | import java.util.stream.Collectors; 10 | import java.util.stream.StreamSupport; 11 | import org.apache.kafka.clients.consumer.ConsumerRecord; 12 | 13 | import static java.nio.charset.StandardCharsets.UTF_8; 14 | 15 | public class KafkaConsumerRequestSetterTest extends PropagationSetterTest { 16 | KafkaConsumerRequest request = new KafkaConsumerRequest( 17 | new ConsumerRecord<>("topic", 0, 1L, "key", "value") 18 | ); 19 | 20 | @Override protected KafkaConsumerRequest request() { 21 | return request; 22 | } 23 | 24 | @Override protected Propagation.Setter setter() { 25 | return KafkaConsumerRequest.SETTER; 26 | } 27 | 28 | @Override protected Iterable read(KafkaConsumerRequest request, String key) { 29 | return StreamSupport.stream(request.delegate.headers().headers(key).spliterator(), false) 30 | .map(h -> new String(h.value(), UTF_8)) 31 | .collect(Collectors.toList()); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/test/java/brave/kafka/clients/KafkaConsumerRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import org.apache.kafka.clients.consumer.ConsumerRecord; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class KafkaConsumerRequestTest { 13 | ConsumerRecord record = new ConsumerRecord<>("top", 0, 1, "key", "value"); 14 | KafkaConsumerRequest request = new KafkaConsumerRequest(record); 15 | 16 | @Test void operation() { 17 | assertThat(request.operation()).isEqualTo("receive"); 18 | } 19 | 20 | @Test void topic() { 21 | assertThat(request.channelKind()).isEqualTo("topic"); 22 | assertThat(request.channelName()).isEqualTo(record.topic()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/test/java/brave/kafka/clients/KafkaProducerRequestTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.clients; 6 | 7 | import org.apache.kafka.clients.producer.ProducerRecord; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class KafkaProducerRequestTest { 13 | ProducerRecord record = new ProducerRecord<>("top", "key", "value"); 14 | KafkaProducerRequest request = new KafkaProducerRequest(record); 15 | 16 | @Test void operation() { 17 | assertThat(request.operation()).isEqualTo("send"); 18 | } 19 | 20 | @Test void topic() { 21 | assertThat(request.channelKind()).isEqualTo("topic"); 22 | assertThat(request.channelName()).isEqualTo(record.topic()); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /instrumentation/kafka-clients/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | # uncomment to include kafka consumer configuration in test logs 10 | #logger.kafka-clients.name=org.apache.kafka.clients 11 | #logger.kafka-clients.level=info 12 | logger.kafkaunit.name=com.github.charithe.kafka 13 | logger.kafkaunit.level=off 14 | logger.kafka.name=zipkin2.collector.kafka 15 | logger.kafka.level=debug 16 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.kafka.streams 5 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/KafkaHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import brave.internal.Nullable; 8 | import org.apache.kafka.common.header.Header; 9 | import org.apache.kafka.common.header.Headers; 10 | 11 | import static java.nio.charset.StandardCharsets.UTF_8; 12 | 13 | final class KafkaHeaders { 14 | static void replaceHeader(Headers headers, String key, String value) { 15 | headers.remove(key); 16 | headers.add(key, value.getBytes(UTF_8)); 17 | } 18 | 19 | @Nullable static String lastStringHeader(Headers headers, String key) { 20 | Header header = headers.lastHeader(key); 21 | if (header == null || header.value() == null) return null; 22 | return new String(header.value(), UTF_8); 23 | } 24 | 25 | KafkaHeaders() { 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/KafkaStreamsPropagation.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import brave.propagation.Propagation.Getter; 8 | import brave.propagation.Propagation.Setter; 9 | import org.apache.kafka.common.header.Headers; 10 | import org.apache.kafka.streams.processor.api.ProcessingContext; 11 | 12 | final class KafkaStreamsPropagation { 13 | /** 14 | * Used by {@link KafkaStreamsTracing#nextSpan(ProcessingContext, Headers)} to extract a trace 15 | * context from a prior stage. 16 | */ 17 | static final Getter GETTER = new Getter() { 18 | @Override public String get(Headers headers, String key) { 19 | return KafkaHeaders.lastStringHeader(headers, key); 20 | } 21 | 22 | @Override public String toString() { 23 | return "Headers::lastHeader"; 24 | } 25 | }; 26 | 27 | /** Used to inject the trace context between stages. */ 28 | static final Setter SETTER = new Setter() { 29 | @Override public void put(Headers headers, String key, String value) { 30 | KafkaHeaders.replaceHeader(headers, key, value); 31 | } 32 | 33 | @Override public String toString() { 34 | return "Headers::replaceHeader"; 35 | } 36 | }; 37 | 38 | KafkaStreamsPropagation() { 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/KafkaStreamsTags.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import org.apache.kafka.streams.processor.ProcessorContext; 8 | 9 | /** 10 | * Tagging policy is not yet dynamic. The descriptions below reflect static policy. 11 | */ 12 | class KafkaStreamsTags { 13 | /** 14 | * Added on {@link KafkaStreamsTracing#nextSpan(ProcessorContext)} when the key not null or 15 | * empty. 16 | */ 17 | static final String KAFKA_STREAMS_APPLICATION_ID_TAG = "kafka.streams.application.id"; 18 | static final String KAFKA_STREAMS_TASK_ID_TAG = "kafka.streams.task.id"; 19 | } 20 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/TracingFixedKeyProcessorContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import brave.propagation.TraceContext; 8 | import org.apache.kafka.common.header.Headers; 9 | import org.apache.kafka.streams.processor.api.FixedKeyProcessorContext; 10 | import org.apache.kafka.streams.processor.api.FixedKeyRecord; 11 | 12 | /** Injects the initialization tracing context to record headers on forward */ 13 | final class TracingFixedKeyProcessorContext 14 | extends TracingProcessingContext> 15 | implements FixedKeyProcessorContext { 16 | 17 | TracingFixedKeyProcessorContext(FixedKeyProcessorContext delegate, 18 | TraceContext.Injector injector, TraceContext context) { 19 | super(delegate, injector, context); 20 | } 21 | 22 | @Override public void forward(FixedKeyRecord r) { 23 | injector.inject(context, r.headers()); 24 | delegate.forward(r); 25 | } 26 | 27 | @Override 28 | public void forward(FixedKeyRecord r, String s) { 29 | injector.inject(context, r.headers()); 30 | delegate.forward(r, s); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/TracingFixedKeyProcessorSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import org.apache.kafka.streams.processor.api.FixedKeyProcessor; 8 | import org.apache.kafka.streams.processor.api.FixedKeyProcessorSupplier; 9 | 10 | class TracingFixedKeyProcessorSupplier 11 | implements FixedKeyProcessorSupplier { 12 | final KafkaStreamsTracing kafkaStreamsTracing; 13 | final String spanName; 14 | final FixedKeyProcessorSupplier delegateProcessorSupplier; 15 | 16 | TracingFixedKeyProcessorSupplier(KafkaStreamsTracing kafkaStreamsTracing, 17 | String spanName, 18 | FixedKeyProcessorSupplier processorSupplier) { 19 | this.kafkaStreamsTracing = kafkaStreamsTracing; 20 | this.spanName = spanName; 21 | this.delegateProcessorSupplier = processorSupplier; 22 | } 23 | 24 | /** This wraps process method to enable tracing. */ 25 | @Override public FixedKeyProcessor get() { 26 | return new TracingFixedKeyProcessor<>(kafkaStreamsTracing, spanName, 27 | delegateProcessorSupplier.get()); 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/TracingProcessorContext.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import brave.propagation.TraceContext; 8 | import brave.propagation.TraceContext.Injector; 9 | import org.apache.kafka.common.header.Headers; 10 | import org.apache.kafka.streams.processor.api.ProcessorContext; 11 | import org.apache.kafka.streams.processor.api.Record; 12 | 13 | /** Injects the initialization tracing context to record headers on forward */ 14 | final class TracingProcessorContext 15 | extends TracingProcessingContext> 16 | implements ProcessorContext { 17 | 18 | TracingProcessorContext(ProcessorContext delegate, 19 | Injector injector, TraceContext context) { 20 | super(delegate, injector, context); 21 | } 22 | 23 | @Override public void forward(Record r) { 24 | injector.inject(context, r.headers()); 25 | delegate.forward(r); 26 | } 27 | 28 | @Override 29 | public void forward(Record r, String s) { 30 | injector.inject(context, r.headers()); 31 | delegate.forward(r, s); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/main/java/brave/kafka/streams/TracingProcessorSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import org.apache.kafka.streams.processor.api.Processor; 8 | import org.apache.kafka.streams.processor.api.ProcessorSupplier; 9 | 10 | class TracingProcessorSupplier 11 | implements ProcessorSupplier { 12 | final KafkaStreamsTracing kafkaStreamsTracing; 13 | final String spanName; 14 | final ProcessorSupplier delegateProcessorSupplier; 15 | 16 | TracingProcessorSupplier(KafkaStreamsTracing kafkaStreamsTracing, 17 | String spanName, 18 | ProcessorSupplier processorSupplier) { 19 | this.kafkaStreamsTracing = kafkaStreamsTracing; 20 | this.spanName = spanName; 21 | this.delegateProcessorSupplier = processorSupplier; 22 | } 23 | 24 | /** This wraps process method to enable tracing. */ 25 | @Override public Processor get() { 26 | return new TracingProcessor<>(kafkaStreamsTracing, spanName, delegateProcessorSupplier.get()); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/test/java/brave/kafka/streams/ITKafkaStreams.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import brave.messaging.MessagingTracing; 8 | import brave.test.ITRemote; 9 | import brave.test.util.AssertableCallback; 10 | import org.apache.kafka.clients.producer.Callback; 11 | import org.apache.kafka.clients.producer.RecordMetadata; 12 | 13 | abstract class ITKafkaStreams extends ITRemote { 14 | MessagingTracing messagingTracing = MessagingTracing.create(tracing); 15 | KafkaStreamsTracing kafkaStreamsTracing = KafkaStreamsTracing.create(messagingTracing); 16 | 17 | /** {@link #join()} waits for the callback to complete without any errors */ 18 | static final class BlockingCallback implements Callback { 19 | final AssertableCallback delegate = new AssertableCallback<>(); 20 | 21 | void join() { 22 | delegate.join(); 23 | } 24 | 25 | @Override public void onCompletion(RecordMetadata metadata, Exception exception) { 26 | if (exception != null) { 27 | delegate.onError(exception); 28 | } else { 29 | delegate.onSuccess(metadata); 30 | } 31 | } 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/test/java/brave/kafka/streams/KafkaHeadersTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.kafka.streams; 6 | 7 | import org.apache.kafka.clients.consumer.ConsumerRecord; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class KafkaHeadersTest { 13 | ConsumerRecord record = new ConsumerRecord<>("top", 0, 1, "key", "value"); 14 | 15 | @Test void lastStringHeader() { 16 | record.headers().add("b3", new byte[] {'1'}); 17 | 18 | assertThat(KafkaHeaders.lastStringHeader(record.headers(), "b3")) 19 | .isEqualTo("1"); 20 | } 21 | 22 | @Test void lastStringHeader_null() { 23 | assertThat(KafkaHeaders.lastStringHeader(record.headers(), "b3")).isNull(); 24 | } 25 | 26 | @Test void replaceHeader() { 27 | KafkaHeaders.replaceHeader(record.headers(), "b3", "1"); 28 | 29 | assertThat(record.headers().lastHeader("b3").value()) 30 | .containsExactly('1'); 31 | } 32 | 33 | @Test void replaceHeader_replace() { 34 | record.headers().add("b3", new byte[0]); 35 | KafkaHeaders.replaceHeader(record.headers(), "b3", "1"); 36 | 37 | assertThat(record.headers().lastHeader("b3").value()) 38 | .containsExactly('1'); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /instrumentation/kafka-streams/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | # uncomment to include kafka consumer configuration in test logs 10 | #logger.kafka-clients.name=org.apache.kafka.clients 11 | #logger.kafka-clients.level=info 12 | logger.kafkaunit.name=com.github.charithe.kafka 13 | logger.kafkaunit.level=off 14 | logger.kafka.name=zipkin2.collector.kafka 15 | logger.kafka.level=debug 16 | -------------------------------------------------------------------------------- /instrumentation/messaging/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.messaging 7 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/main/java/brave/messaging/ConsumerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging; 6 | 7 | import brave.Span; 8 | 9 | import static brave.Span.Kind.CONSUMER; 10 | 11 | /** 12 | * Marks an interface for use in extraction and {@link MessagingRuleSampler}. This gives a standard 13 | * type to consider when parsing an incoming context. 14 | * 15 | * @since 5.9 16 | */ 17 | public abstract class ConsumerRequest extends MessagingRequest { 18 | @Override public Span.Kind spanKind() { 19 | return CONSUMER; 20 | } 21 | } 22 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/main/java/brave/messaging/ConsumerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * @see ConsumerRequest 11 | * @since 5.13 12 | */ 13 | public abstract class ConsumerResponse extends MessagingResponse { 14 | @Override public final Span.Kind spanKind() { 15 | return Span.Kind.CONSUMER; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/main/java/brave/messaging/MessagingResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging; 6 | 7 | import brave.Response; 8 | import brave.internal.Nullable; 9 | 10 | /** 11 | * Abstract response type used for parsing and sampling of messaging clients and servers. 12 | * 13 | * @see ProducerResponse 14 | * @see ConsumerResponse 15 | * @since 5.13 16 | */ 17 | public abstract class MessagingResponse extends Response { 18 | /** 19 | * Information about the request that initiated this messaging response or {@code null} if 20 | * unknown. 21 | * 22 | * @since 5.13 23 | */ 24 | @Override @Nullable public MessagingRequest request() { 25 | return null; 26 | } 27 | } 28 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/main/java/brave/messaging/ProducerRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * Marks an interface for use in injection and {@link MessagingRuleSampler}. This gives a standard 11 | * type to consider when parsing an outgoing context. 12 | * 13 | * @since 5.9 14 | */ 15 | public abstract class ProducerRequest extends MessagingRequest { 16 | @Override public Span.Kind spanKind() { 17 | return Span.Kind.PRODUCER; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/main/java/brave/messaging/ProducerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * @see ProducerRequest 11 | * @since 5.13 12 | */ 13 | public abstract class ProducerResponse extends MessagingResponse { 14 | @Override public final Span.Kind spanKind() { 15 | return Span.Kind.PRODUCER; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /instrumentation/messaging/src/test/java/brave/messaging/features/ExampleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.messaging.features; 6 | 7 | import brave.Tracing; 8 | import brave.messaging.MessagingRuleSampler; 9 | import brave.messaging.MessagingTracing; 10 | import brave.sampler.RateLimitingSampler; 11 | import brave.sampler.Sampler; 12 | import brave.sampler.SamplerFunctions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static brave.messaging.MessagingRequestMatchers.channelNameEquals; 16 | import static brave.messaging.MessagingRequestMatchers.operationEquals; 17 | import static org.mockito.Mockito.mock; 18 | 19 | public class ExampleTest { 20 | Tracing tracing = mock(Tracing.class); 21 | MessagingTracing messagingTracing; 22 | 23 | // This mainly shows that we don't accidentally rely on package-private access 24 | @Test void showConstruction() { 25 | messagingTracing = MessagingTracing.newBuilder(tracing) 26 | .consumerSampler(MessagingRuleSampler.newBuilder() 27 | .putRule(channelNameEquals("alerts"), Sampler.NEVER_SAMPLE) 28 | .putRule(operationEquals("receive"), RateLimitingSampler.create(100)) 29 | .build()) 30 | .producerSampler(SamplerFunctions.neverSample()) 31 | .build(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/mongodb/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.mongodb 5 | -------------------------------------------------------------------------------- /instrumentation/mongodb/src/it/mongodb_floor/README.md: -------------------------------------------------------------------------------- 1 | # mongodb_floor 2 | This tests that MongoDBTracing can be used with mongodb <5 3 | -------------------------------------------------------------------------------- /instrumentation/mongodb/src/it/mongodb_floor/src/test/java/brave/mongodb_v3/ITMongoDBTracing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.mongodb_floor; 6 | 7 | class ITMongoDBTracing extends brave.mongodb.ITMongoDBTracing { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/mongodb/src/test/java/brave/mongodb/MongoDBDriverTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.mongodb; 6 | 7 | import brave.Span; 8 | import com.mongodb.ServerAddress; 9 | import org.junit.jupiter.api.Test; 10 | import org.junit.jupiter.api.extension.ExtendWith; 11 | import org.mockito.Mock; 12 | import org.mockito.junit.jupiter.MockitoExtension; 13 | 14 | import static org.mockito.Mockito.verify; 15 | import static org.mockito.Mockito.when; 16 | 17 | @ExtendWith(MockitoExtension.class) 18 | public class MongoDBDriverTest { 19 | @Mock ServerAddress serverAddress; 20 | @Mock Span span; 21 | 22 | @Test void setRemoteIpAndPort() { 23 | when(serverAddress.getHost()).thenReturn("127.0.0.1"); 24 | when(serverAddress.getPort()).thenReturn(27017); 25 | 26 | MongoDBDriver.get().setRemoteIpAndPort(span, serverAddress); 27 | 28 | verify(span).remoteIpAndPort("127.0.0.1", 27017); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /instrumentation/mongodb/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/mysql/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-mysql 2 | 3 | This includes a MySQL statement interceptor that will report to Zipkin 4 | how long each statement takes, along with relevant tags like the query. 5 | 6 | To use it, append `?statementInterceptors=brave.mysql.TracingStatementInterceptor` 7 | to the end of the connection url. 8 | 9 | By default the service name corresponding to your database uses the format 10 | `mysql-${database}`, but you can append another property `zipkinServiceName` to customise it. 11 | 12 | `?statementInterceptors=brave.mysql.TracingStatementInterceptor&zipkinServiceName=myDatabaseService` 13 | 14 | The current tracing component is used at runtime. Until you have 15 | instantiated `brave.Tracing`, no traces will appear. 16 | -------------------------------------------------------------------------------- /instrumentation/mysql/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.mysql 5 | -------------------------------------------------------------------------------- /instrumentation/mysql/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/mysql6/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-mysql6 2 | 3 | This includes a mysql-connector-java 6+ statement interceptor that will report to Zipkin 4 | how long each statement takes, along with relevant tags like the query. 5 | 6 | To use it, append `?statementInterceptors=brave.mysql6.TracingStatementInterceptor` 7 | to the end of the connection url. 8 | 9 | By default the service name corresponding to your database uses the format 10 | `mysql-${database}`, but you can append another property `zipkinServiceName` to customise it. 11 | 12 | `?statementInterceptors=brave.mysql6.TracingStatementInterceptor&zipkinServiceName=myDatabaseService` 13 | 14 | The current tracing component is used at runtime. Until you have 15 | instantiated `brave.Tracing`, no traces will appear. 16 | -------------------------------------------------------------------------------- /instrumentation/mysql6/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.mysql6 5 | -------------------------------------------------------------------------------- /instrumentation/mysql6/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | io.zipkin.brave 11 | brave-instrumentation-parent 12 | 6.3.1-SNAPSHOT 13 | 14 | 4.0.0 15 | 16 | brave-instrumentation-mysql6 17 | Brave Instrumentation: MySQL6 18 | 19 | 20 | 21 | brave.mysql6 22 | 23 | ${project.basedir}/../.. 24 | 25 | 6.0.6 26 | 27 | 28 | 29 | 30 | mysql 31 | mysql-connector-java 32 | ${mysql-connector-java6.version} 33 | provided 34 | 35 | 36 | 37 | ${project.groupId} 38 | brave-tests 39 | ${project.version} 40 | test 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /instrumentation/mysql6/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/mysql8/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-mysql8 2 | 3 | This includes a mysql-connector-java 8+ query interceptor that will report to Zipkin 4 | how long each query takes, along with relevant tags like the query. 5 | 6 | To use it, append `?queryInterceptors=brave.mysql8.TracingQueryInterceptor` 7 | to the end of the connection url. 8 | 9 | It is also recommended to add the exception interceptor so errors are added to the span, e.g., 10 | `?queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor` 11 | 12 | By default, the service name corresponding to your database uses the format 13 | `mysql-${database}`, but you can append another property `zipkinServiceName` to customise it. 14 | 15 | `?queryInterceptors=brave.mysql8.TracingQueryInterceptor&exceptionInterceptors=brave.mysql8.TracingExceptionInterceptor&zipkinServiceName=myDatabaseService` 16 | 17 | The current tracing component is used at runtime. Until you have 18 | instantiated `brave.Tracing`, no traces will appear. 19 | -------------------------------------------------------------------------------- /instrumentation/mysql8/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.mysql8 5 | -------------------------------------------------------------------------------- /instrumentation/mysql8/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/netty-codec-http/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-netty-codec-http 2 | 3 | This module contains a tracing decorators for [Netty's Http Codec](https://github.com/netty/netty/tree/4.1/codec-http) 4.x. 4 | 5 | `NettyHttpTracing.serverHandler()` extracts trace state from incoming requests, 6 | and reports to Zipkin how long each take, along with relevant tags like the 7 | http url. 8 | 9 | ## Configuration 10 | 11 | To enable tracing for an http server you need to add it to your pipeline: 12 | ```java 13 | NettyHttpTracing nettyHttpTracing = NettyHttpTracing.create(httpTracing); 14 | ChannelPipeline pipeline = ch.pipeline(); 15 | ... add your infrastructure handlers, in particular HttpRequestDecoder and HttpResponseEncoder 16 | pipeline.addLast("tracing", nettyHttpTracing.serverHandler()); 17 | ... add your application handlers 18 | ``` 19 | -------------------------------------------------------------------------------- /instrumentation/netty-codec-http/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Platform 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.netty.http 8 | -------------------------------------------------------------------------------- /instrumentation/netty-codec-http/src/main/java/brave/netty/http/NettyHttpTracing.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.netty.http; 6 | 7 | import brave.Span; 8 | import brave.Tracing; 9 | import brave.http.HttpServerRequest; 10 | import brave.http.HttpTracing; 11 | import io.netty.channel.ChannelDuplexHandler; 12 | import io.netty.util.AttributeKey; 13 | 14 | public final class NettyHttpTracing { 15 | static final AttributeKey REQUEST_ATTRIBUTE = 16 | AttributeKey.valueOf(HttpServerRequest.class.getName()); 17 | static final AttributeKey SPAN_ATTRIBUTE = AttributeKey.valueOf(Span.class.getName()); 18 | 19 | public static NettyHttpTracing create(Tracing tracing) { 20 | return new NettyHttpTracing(HttpTracing.create(tracing)); 21 | } 22 | 23 | public static NettyHttpTracing create(HttpTracing httpTracing) { 24 | return new NettyHttpTracing(httpTracing); 25 | } 26 | 27 | final ChannelDuplexHandler serverHandler; 28 | 29 | NettyHttpTracing(HttpTracing httpTracing) { // intentionally hidden constructor 30 | serverHandler = new TracingHttpServerHandler(httpTracing); 31 | } 32 | 33 | /** 34 | * Returns a duplex handler that traces {@link io.netty.handler.codec.http.HttpRequest} messages. 35 | */ 36 | public ChannelDuplexHandler serverHandler() { 37 | return serverHandler; 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /instrumentation/netty-codec-http/src/test/java/brave/netty/http/HttpResponseWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.netty.http; 6 | 7 | import brave.http.HttpServerRequest; 8 | import brave.netty.http.TracingHttpServerHandler.HttpResponseWrapper; 9 | import io.netty.handler.codec.http.HttpResponse; 10 | import io.netty.handler.codec.http.HttpResponseStatus; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.mockito.Mock; 14 | import org.mockito.junit.jupiter.MockitoExtension; 15 | 16 | import static org.assertj.core.api.Assertions.assertThat; 17 | import static org.mockito.Mockito.when; 18 | 19 | @ExtendWith(MockitoExtension.class) 20 | public class HttpResponseWrapperTest { 21 | @Mock HttpServerRequest request; 22 | @Mock HttpResponse response; 23 | @Mock HttpResponseStatus status; 24 | 25 | @Test void request() { 26 | assertThat(new HttpResponseWrapper(request, response, null).request()) 27 | .isSameAs(request); 28 | } 29 | 30 | @Test void statusCode() { 31 | when(response.status()).thenReturn(status); 32 | when(status.code()).thenReturn(200); 33 | 34 | assertThat(new HttpResponseWrapper(request, response, null).statusCode()).isEqualTo(200); 35 | } 36 | 37 | @Test void statusCode_zeroNoResponse() { 38 | assertThat(new HttpResponseWrapper(request, response, null).statusCode()).isZero(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /instrumentation/netty-codec-http/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=info 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-okhttp3 2 | This module contains a tracing decorators for [OkHttp](https://github.com/square/okhttp) 3.x. 3 | 4 | ## TracingCallFactory 5 | `TracingCallFactory` adds trace headers to outgoing requests. It 6 | then reports to Zipkin how long each request takes, along with relevant 7 | tags like the http url. 8 | 9 | To enable tracing, wrap your client using `TracingCallFactory`. 10 | 11 | ```java 12 | callFactory = TracingCallFactory.create(httpTracing, okhttp); 13 | ``` 14 | 15 | ## TracingInterceptor 16 | Sometimes code must use `OkHttpClient`, not `Call.Factory`. When this is 17 | the case, you can add the network interceptor `TracingInterceptor`. Make 18 | sure you wrap the dispatcher's executor service. 19 | 20 | ```java 21 | new OkHttpClient.Builder() 22 | .dispatcher(new Dispatcher( 23 | httpTracing.tracing().currentTraceContext() 24 | .executorService(new Dispatcher().executorService()) 25 | )) 26 | .addNetworkInterceptor(TracingInterceptor.create(httpTracing)) 27 | .build() 28 | ``` 29 | 30 | Note that when the keep-alive pool is full (backlog situation), this 31 | approach can result in broken traces. This limitation is not the case 32 | when using the call factory approach. 33 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | okhttp3;version="[3.11, 5)",\ 3 | okio;version="[1.15,3)",\ 4 | * 5 | Export-Package: \ 6 | brave.okhttp3 7 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/it/okhttp3_floor/README.md: -------------------------------------------------------------------------------- 1 | # okhttp3_floor 2 | This tests that TracingCallFactory can be used with okhttp3 <3.12 3 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/it/okhttp3_floor/src/test/java/brave/okhttp3_v3/ITTracingCallFactory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.okhttp3_floor; 6 | 7 | class ITTracingCallFactory extends brave.okhttp3.ITTracingCallFactory { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/it/okhttp3_floor/src/test/java/brave/okhttp3_v3/ITTracingInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.okhttp3_floor; 6 | 7 | class ITTracingInterceptor extends brave.okhttp3.ITTracingInterceptor { 8 | } 9 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/test/java/brave/okhttp3/ResponseWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.okhttp3; 6 | 7 | import brave.okhttp3.TracingInterceptor.RequestWrapper; 8 | import brave.okhttp3.TracingInterceptor.ResponseWrapper; 9 | import okhttp3.Protocol; 10 | import okhttp3.Request; 11 | import okhttp3.Response; 12 | import org.junit.jupiter.api.Test; 13 | 14 | import static org.assertj.core.api.Assertions.assertThat; 15 | 16 | public class ResponseWrapperTest { 17 | RequestWrapper request = 18 | new RequestWrapper(new Request.Builder().url("http://localhost/foo").build()); 19 | Response.Builder responseBuilder = new Response.Builder() 20 | .request(request.delegate) 21 | .protocol(Protocol.HTTP_1_1); 22 | 23 | @Test void request() { 24 | Response response = responseBuilder.code(200).message("ok").build(); 25 | 26 | assertThat(new ResponseWrapper(request, response, null).request()) 27 | .isSameAs(request); 28 | } 29 | 30 | @Test void statusCode() { 31 | Response response = responseBuilder.code(200).message("ok").build(); 32 | 33 | assertThat(new ResponseWrapper(request, response, null).statusCode()).isEqualTo(200); 34 | } 35 | 36 | @Test void statusCode_zero() { 37 | Response response = responseBuilder.code(0).message("ice cream!").build(); 38 | 39 | assertThat(new ResponseWrapper(request, response, null).statusCode()).isZero(); 40 | assertThat(new ResponseWrapper(request, null, null).statusCode()).isZero(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/test/java/brave/okhttp3/TracingInterceptorTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.okhttp3; 6 | 7 | import brave.Span; 8 | import brave.Tracing; 9 | import okhttp3.Interceptor; 10 | import org.junit.jupiter.api.AfterEach; 11 | import org.junit.jupiter.api.Test; 12 | import org.junit.jupiter.api.extension.ExtendWith; 13 | import org.mockito.Mock; 14 | import org.mockito.junit.jupiter.MockitoExtension; 15 | 16 | import static org.mockito.Mockito.verify; 17 | import static org.mockito.Mockito.verifyNoMoreInteractions; 18 | import static org.mockito.Mockito.when; 19 | 20 | @ExtendWith(MockitoExtension.class) 21 | public class TracingInterceptorTest { 22 | Tracing tracing = Tracing.newBuilder().build(); 23 | @Mock Interceptor.Chain chain; 24 | @Mock Span span; 25 | 26 | @Test void parseRouteAddress_skipsOnNoop() { 27 | when(span.isNoop()).thenReturn(true); 28 | TracingInterceptor.parseRouteAddress(chain, span); 29 | 30 | verify(span).isNoop(); 31 | verifyNoMoreInteractions(span); 32 | } 33 | 34 | @AfterEach void close() { 35 | tracing.close(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /instrumentation/okhttp3/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/rocketmq-client/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.rocketmq.client 7 | -------------------------------------------------------------------------------- /instrumentation/rocketmq-client/src/test/java/brave/rocketmq/client/MessagePropertiesTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.rocketmq.client; 6 | 7 | import org.apache.rocketmq.common.message.Message; 8 | import org.junit.jupiter.api.Test; 9 | 10 | import static org.assertj.core.api.Assertions.assertThat; 11 | 12 | public class MessagePropertiesTest { 13 | Message message = new Message(); 14 | 15 | @Test void putUserProperty_noProperties() { 16 | message.putUserProperty("b3", "1"); 17 | 18 | assertThat(message.getProperty("b3")) 19 | .isEqualTo("1"); 20 | } 21 | 22 | @Test void putUserProperty_replace() { 23 | message.putUserProperty("b3", String.valueOf((byte) 0)); 24 | message.putUserProperty("b3", "1"); 25 | 26 | assertThat(message.getUserProperty("b3")) 27 | .isEqualTo("1"); 28 | } 29 | 30 | @Test void getUserProperty_hasProperties() { 31 | message = new Message("topic", new byte[0]); 32 | message.putUserProperty("b3", "1"); 33 | 34 | assertThat(message.getProperty("b3")) 35 | .isEqualTo("1"); 36 | } 37 | 38 | @Test void getUserProperty_null() { 39 | assertThat(message.getProperty("b3")).isNull(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /instrumentation/rocketmq-client/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | # stop huge spam 10 | logger.dockerclient.name=org.testcontainers.dockerclient 11 | logger.dockerclient.level=off 12 | -------------------------------------------------------------------------------- /instrumentation/rpc/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.rpc 7 | -------------------------------------------------------------------------------- /instrumentation/rpc/src/main/java/brave/rpc/RpcClientResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.rpc; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * Marks an interface for use in {@link RpcClientHandler#handleReceive(RpcClientResponse, Span)}. 11 | * This gives a standard type to consider when parsing an incoming context. 12 | * 13 | * @see RpcClientRequest 14 | * @since 5.10 15 | */ 16 | public abstract class RpcClientResponse extends RpcResponse { 17 | @Override public final Span.Kind spanKind() { 18 | return Span.Kind.CLIENT; 19 | } 20 | 21 | /** 22 | * Like {@link RpcRequest#parseRemoteIpAndPort(Span)} for when the client library cannot read 23 | * socket information before a request is made. 24 | * 25 | *

To reduce overhead, only implement this when not implementing {@link 26 | * RpcRequest#parseRemoteIpAndPort(Span)}. 27 | * 28 | * @since 5.10 29 | */ 30 | // This is on the response object because clients often don't know their final IP until after the 31 | // request started. 32 | public boolean parseRemoteIpAndPort(Span span) { 33 | return false; 34 | } 35 | } 36 | -------------------------------------------------------------------------------- /instrumentation/rpc/src/main/java/brave/rpc/RpcServerResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.rpc; 6 | 7 | import brave.Span; 8 | 9 | /** 10 | * Marks an interface for use in {@link RpcServerHandler#handleSend(RpcServerResponse, Span)}. This 11 | * gives a standard type to consider when parsing an incoming context. 12 | * 13 | * @see RpcClientRequest 14 | * @since 5.10 15 | */ 16 | public abstract class RpcServerResponse extends RpcResponse { 17 | @Override public final Span.Kind spanKind() { 18 | return Span.Kind.SERVER; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /instrumentation/rpc/src/test/java/brave/rpc/RpcClientRequestSetterTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.rpc; 6 | 7 | import brave.propagation.Propagation.Setter; 8 | import brave.test.propagation.PropagationSetterTest; 9 | import java.util.Collections; 10 | import java.util.LinkedHashMap; 11 | import java.util.Map; 12 | 13 | import static brave.rpc.RpcClientRequest.SETTER; 14 | 15 | public class RpcClientRequestSetterTest extends PropagationSetterTest { 16 | Map propagationFields = new LinkedHashMap<>(); 17 | 18 | @Override protected RpcClientRequest request() { 19 | return new RpcClientRequest() { 20 | @Override public Object unwrap() { 21 | return null; 22 | } 23 | 24 | @Override public String method() { 25 | return null; 26 | } 27 | 28 | @Override public String service() { 29 | return null; 30 | } 31 | 32 | @Override protected void propagationField(String keyName, String value) { 33 | propagationFields.put(keyName, value); 34 | } 35 | }; 36 | } 37 | 38 | @Override protected Setter setter() { 39 | return SETTER; 40 | } 41 | 42 | @Override protected Iterable read(RpcClientRequest request, String key) { 43 | String result = propagationFields.get(key); 44 | return result != null ? Collections.singletonList(result) : Collections.emptyList(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /instrumentation/rpc/src/test/java/brave/rpc/features/ExampleTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.rpc.features; 6 | 7 | import brave.Tracing; 8 | import brave.rpc.RpcRuleSampler; 9 | import brave.rpc.RpcTracing; 10 | import brave.sampler.RateLimitingSampler; 11 | import brave.sampler.Sampler; 12 | import brave.sampler.SamplerFunctions; 13 | import org.junit.jupiter.api.Test; 14 | 15 | import static brave.rpc.RpcRequestMatchers.methodEquals; 16 | import static brave.rpc.RpcRequestMatchers.serviceEquals; 17 | import static org.mockito.Mockito.mock; 18 | 19 | public class ExampleTest { 20 | Tracing tracing = mock(Tracing.class); 21 | RpcTracing rpcTracing; 22 | 23 | // This mainly shows that we don't accidentally rely on package-private access 24 | @Test void showConstruction() { 25 | rpcTracing = RpcTracing.newBuilder(tracing) 26 | .serverSampler(RpcRuleSampler.newBuilder() 27 | .putRule(serviceEquals("scribe"), Sampler.NEVER_SAMPLE) 28 | .putRule(methodEquals("Report"), RateLimitingSampler.create(100)) 29 | .build()) 30 | .clientSampler(SamplerFunctions.neverSample()) 31 | .build(); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/servlet-jakarta/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Throwables 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.jakarta.servlet 8 | -------------------------------------------------------------------------------- /instrumentation/servlet/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use need to import to support brave.internal.Throwables 2 | # brave.internal.Nullable is not used at runtime. 3 | Import-Package: \ 4 | brave.internal;braveinternal=true,\ 5 | * 6 | Export-Package: \ 7 | brave.servlet 8 | -------------------------------------------------------------------------------- /instrumentation/servlet/src/it/servlet25/README.md: -------------------------------------------------------------------------------- 1 | # servlet-25 2 | This tests that TracingFilter does not rely on Servlet 3+ apis 3 | -------------------------------------------------------------------------------- /instrumentation/spring-rabbit/bnd.bnd: -------------------------------------------------------------------------------- 1 | # We use brave.internal.Nullable, but it is not used at runtime. 2 | Import-Package: \ 3 | !brave.internal*,\ 4 | * 5 | Export-Package: \ 6 | brave.spring.rabbit 7 | -------------------------------------------------------------------------------- /instrumentation/spring-rabbit/src/main/java/brave/spring/rabbit/MessageHeaders.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.rabbit; 6 | 7 | import brave.internal.Nullable; 8 | import org.springframework.amqp.core.Message; 9 | import org.springframework.amqp.core.MessageProperties; 10 | 11 | class MessageHeaders { 12 | /** 13 | * If {@link MessageProperties} exist, this returns {@link MessageProperties#getHeader(String)} if 14 | * it is a string. 15 | */ 16 | @Nullable static String getHeaderIfString(Message message, String name) { 17 | MessageProperties properties = message.getMessageProperties(); 18 | if (properties == null) return null; 19 | Object o = properties.getHeader(name); 20 | if (o instanceof String) return o.toString(); 21 | return null; 22 | } 23 | 24 | /** 25 | * If {@link MessageProperties} exist, this invokes {@link MessageProperties#setHeader(String, 26 | * Object)}. 27 | */ 28 | static void setHeader(Message message, String name, String value) { 29 | MessageProperties properties = message.getMessageProperties(); 30 | if (properties == null) return; 31 | properties.setHeader(name, value); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/spring-rabbit/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | # stop huge spam 10 | logger.dockerclient.name=org.testcontainers.dockerclient 11 | logger.dockerclient.level=off 12 | -------------------------------------------------------------------------------- /instrumentation/spring-web/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-spring-web 2 | This module contains tracing interceptors for [Spring RestTemplate](https://spring.io/guides/gs/consuming-rest/). 3 | `TracingClientHttpRequestInterceptor` and `TracingAsyncClientHttpRequestInterceptor` add trace 4 | headers to outgoing requests. They then report to Zipkin how long each request took, along with 5 | relevant tags like the http url. 6 | 7 | ## Configuration 8 | 9 | Tracing always needs a bean of type `HttpTracing` configured. Make sure 10 | it is in place before proceeding. Here's an example in [XML](https://github.com/openzipkin/brave-webmvc-example/blob/master/webmvc25/src/main/webapp/WEB-INF/spring-webmvc-servlet.xml) and [Java](https://github.com/openzipkin/brave-webmvc-example/blob/master/webmvc4/src/main/java/brave/webmvc/TracingConfiguration.java). 11 | 12 | Then, wire `TracingClientHttpRequestInterceptor` and add it with the 13 | `RestTemplate.setInterceptors` method. If you are using `AsyncRestTemplate` and Spring 4.3+, you can 14 | wire `AsyncTracingClientHttpRequestInterceptor` and add it via `AsyncRestTemplate.setInterceptors`. 15 | -------------------------------------------------------------------------------- /instrumentation/spring-web/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.spring.web 5 | -------------------------------------------------------------------------------- /instrumentation/spring-web/src/it/spring3/README.md: -------------------------------------------------------------------------------- 1 | # spring3 2 | This tests that TracingClientHttpRequestInterceptor can be used without Spring 4 3 | -------------------------------------------------------------------------------- /instrumentation/spring-web/src/test/java/brave/spring/web/HttpRequestWrapperTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.web; 6 | 7 | import brave.spring.web.TracingClientHttpRequestInterceptor.HttpRequestWrapper; 8 | import java.net.URI; 9 | import org.junit.jupiter.api.Test; 10 | import org.springframework.http.HttpRequest; 11 | 12 | import static org.assertj.core.api.Assertions.assertThat; 13 | import static org.mockito.Mockito.mock; 14 | import static org.mockito.Mockito.when; 15 | 16 | public class HttpRequestWrapperTest { 17 | HttpRequest request = mock(HttpRequest.class); 18 | 19 | @Test void path() { 20 | when(request.getURI()).thenReturn(URI.create("http://localhost/api")); 21 | 22 | assertThat(new HttpRequestWrapper(request).path()) 23 | .isEqualTo("/api"); 24 | } 25 | 26 | // NOTE: While technically possible, it is not easy to make URI.getPath() return null! 27 | @Test void path_emptyToSlash() { 28 | when(request.getURI()).thenReturn(URI.create("http://localhost")); 29 | 30 | assertThat(new HttpRequestWrapper(request).path()) 31 | .isEqualTo("/"); 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /instrumentation/spring-web/src/test/java/brave/spring/web/TracingAsyncClientHttpRequestInterceptorAutowireTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.web; 6 | 7 | import brave.Tracing; 8 | import brave.http.HttpTracing; 9 | import org.junit.jupiter.api.AfterEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.http.client.AsyncClientHttpRequestInterceptor; 15 | 16 | public class TracingAsyncClientHttpRequestInterceptorAutowireTest { 17 | 18 | @Configuration static class HttpTracingConfiguration { 19 | @Bean HttpTracing httpTracing() { 20 | return HttpTracing.create(Tracing.newBuilder().build()); 21 | } 22 | } 23 | 24 | @AfterEach void close() { 25 | Tracing.current().close(); 26 | } 27 | 28 | @Test void autowiredWithBeanConfig() { 29 | AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 30 | ctx.register(HttpTracingConfiguration.class); 31 | ctx.register(TracingAsyncClientHttpRequestInterceptor.class); 32 | ctx.refresh(); 33 | 34 | ctx.getBean(AsyncClientHttpRequestInterceptor.class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /instrumentation/spring-web/src/test/java/brave/spring/web/TracingClientHttpRequestInterceptorAutowireTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.web; 6 | 7 | import brave.Tracing; 8 | import brave.http.HttpTracing; 9 | import org.junit.jupiter.api.AfterEach; 10 | import org.junit.jupiter.api.Test; 11 | import org.springframework.context.annotation.AnnotationConfigApplicationContext; 12 | import org.springframework.context.annotation.Bean; 13 | import org.springframework.context.annotation.Configuration; 14 | import org.springframework.http.client.ClientHttpRequestInterceptor; 15 | 16 | public class TracingClientHttpRequestInterceptorAutowireTest { 17 | 18 | @Configuration static class HttpTracingConfiguration { 19 | @Bean HttpTracing httpTracing() { 20 | return HttpTracing.create(Tracing.newBuilder().build()); 21 | } 22 | } 23 | 24 | @AfterEach void close() { 25 | Tracing.current().close(); 26 | } 27 | 28 | @Test void autowiredWithBeanConfig() { 29 | AnnotationConfigApplicationContext ctx = new AnnotationConfigApplicationContext(); 30 | ctx.register(HttpTracingConfiguration.class); 31 | ctx.register(TracingClientHttpRequestInterceptor.class); 32 | ctx.refresh(); 33 | 34 | ctx.getBean(ClientHttpRequestInterceptor.class); 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /instrumentation/spring-web/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.spring.webmvc 5 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/src/it/servlet25/README.md: -------------------------------------------------------------------------------- 1 | # servlet-25 2 | This tests that TracingHandlerInterceptor does not rely on Servlet 3+ apis 3 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/src/it/servlet25/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/src/it/spring2/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/src/test/java/brave/spring/webmvc/ITSpanCustomizingHandlerInterceptor.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.webmvc; 6 | 7 | import brave.test.http.Jetty9ServerController; 8 | import java.util.EnumSet; 9 | import javax.servlet.DispatcherType; 10 | import org.eclipse.jetty.servlet.ServletContextHandler; 11 | import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; 12 | 13 | class ITSpanCustomizingHandlerInterceptor extends BaseITSpanCustomizingHandlerInterceptor { 14 | public ITSpanCustomizingHandlerInterceptor() { 15 | super(new Jetty9ServerController()); 16 | } 17 | 18 | @Override protected void addDelegatingTracingFilter(ServletContextHandler handler) { 19 | handler.addFilter(DelegatingTracingFilter.class, "/*", EnumSet.allOf(DispatcherType.class)); 20 | } 21 | 22 | @Override 23 | protected void registerTestController(AnnotationConfigWebApplicationContext appContext) { 24 | appContext.register(Servlet3TestController.class); // the test resource 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /instrumentation/spring-webmvc/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /instrumentation/vertx-web/README.md: -------------------------------------------------------------------------------- 1 | # brave-instrumentation-vertx-web 2 | 3 | This module contains a routing context handler for [Vert.x Web](http://vertx.io/docs/vertx-web/js/) 4 | This extracts trace state from incoming requests. Then, it reports to 5 | Zipkin how long each request takes, along with relevant tags like the 6 | http url. Register this as an failure handler to ensure any errors are 7 | also sent to Zipkin. 8 | 9 | To enable tracing you need to set `order`, `handler` and `failureHandler` 10 | hooks: 11 | ```java 12 | vertxWebTracing = VertxWebTracing.create(httpTracing); 13 | routingContextHandler = vertxWebTracing.routingContextHandler(); 14 | router.route() 15 | .order(-1) // applies before routes 16 | .handler(routingContextHandler) 17 | .failureHandler(routingContextHandler); 18 | 19 | // any routes you add are now traced, such as the below 20 | router.route("/foo").handler(ctx -> { 21 | ctx.response().end("bar"); 22 | }); 23 | ``` -------------------------------------------------------------------------------- /instrumentation/vertx-web/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.vertx.web 5 | -------------------------------------------------------------------------------- /spring-beans/bnd.bnd: -------------------------------------------------------------------------------- 1 | Import-Package: \ 2 | * 3 | Export-Package: \ 4 | brave.spring.beans 5 | -------------------------------------------------------------------------------- /spring-beans/src/it/spring2/README.md: -------------------------------------------------------------------------------- 1 | # spring2 2 | This tests that the brave.spring.beans package does not rely on Spring 3+ APIs. 3 | -------------------------------------------------------------------------------- /spring-beans/src/it/spring2/src/test/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | log4j.rootLogger=WARN, console 2 | log4j.appender.console=org.apache.log4j.ConsoleAppender 3 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 4 | log4j.appender.console.layout.ConversionPattern=[%d{dd MMM yyyy HH:mm:ss,SSS}] - %m%n 5 | 6 | -------------------------------------------------------------------------------- /spring-beans/src/main/java/brave/spring/beans/SingleBaggageFieldFactoryBean.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright The OpenZipkin Authors 3 | * SPDX-License-Identifier: Apache-2.0 4 | */ 5 | package brave.spring.beans; 6 | 7 | import brave.baggage.BaggageField; 8 | import brave.baggage.BaggagePropagationConfig; 9 | import brave.baggage.BaggagePropagationConfig.SingleBaggageField; 10 | import java.util.Collections; 11 | import java.util.List; 12 | import org.springframework.beans.factory.FactoryBean; 13 | 14 | /** Spring XML config does not support chained builders. This converts accordingly */ 15 | public class SingleBaggageFieldFactoryBean implements FactoryBean { 16 | BaggageField field; 17 | List keyNames = Collections.emptyList(); 18 | 19 | @Override public SingleBaggageField getObject() { 20 | SingleBaggageField.Builder builder = SingleBaggageField.newBuilder(field); 21 | if (keyNames != null) { 22 | for (String keyName : keyNames) { 23 | builder.addKeyName(keyName); 24 | } 25 | } 26 | return builder.build(); 27 | } 28 | 29 | @Override public Class getObjectType() { 30 | return BaggagePropagationConfig.class; 31 | } 32 | 33 | @Override public boolean isSingleton() { 34 | return true; 35 | } 36 | 37 | public void setField(BaggageField field) { 38 | this.field = field; 39 | } 40 | 41 | public void setKeyNames(List keyNames) { 42 | if (keyNames == null) return; 43 | this.keyNames = keyNames; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /spring-beans/src/test/resources/log4j2.properties: -------------------------------------------------------------------------------- 1 | appenders=console 2 | appender.console.type=Console 3 | appender.console.name=STDOUT 4 | appender.console.layout.type=PatternLayout 5 | appender.console.layout.pattern=%d{ABSOLUTE} %-5p [%t] %C{2} (%F:%L) - %m%n 6 | rootLogger.level=warn 7 | rootLogger.appenderRefs=stdout 8 | rootLogger.appenderRef.stdout.ref=STDOUT 9 | -------------------------------------------------------------------------------- /src/etc/header.txt: -------------------------------------------------------------------------------- 1 | Copyright The OpenZipkin Authors 2 | SPDX-License-Identifier: Apache-2.0 3 | -------------------------------------------------------------------------------- /src/it/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 8 | 9 | 10 | 11 | it-repo 12 | 13 | true 14 | 15 | 16 | 17 | local.central 18 | @localRepositoryUrl@ 19 | 20 | true 21 | 22 | 23 | true 24 | 25 | 26 | 27 | 28 | 29 | local.central 30 | @localRepositoryUrl@ 31 | 32 | true 33 | 34 | 35 | true 36 | 37 | 38 | 39 | 40 | 41 | 42 | --------------------------------------------------------------------------------