Code Monkey home page Code Monkey logo

tracer's Introduction

Tracer: Distributed system tracing

Highway at Night

Build Status Coverage Status Javadoc Release Maven Central

Tracer is a library that manages custom trace identifiers and carries them through distributed systems. Traditionally traces are transported as custom HTTP headers, usually generated by clients on the very first request. Traces are added to any subsequent requests and responses, especially to transitive dependencies. Having a consistent trace across different services in a system allows to correlate requests and responses beyond the traditional single client-server communication.

This library historically originates from a closed-source implementation called Flow-ID. The goal was to create a clean open source version in which we could get rid of all the drawbacks of the old implementation, e.g. strong-coupling to internal libraries, single hard-coded header and limited testability.

  • Status: Under development and used in production

Features

  • Tracing of HTTP requests and responses
  • Customization by having a pluggable trace format and lifecycle listeners for easy integration
  • Support for Servlet containers, Apache’s HTTP client, and (via its elegant API) other frameworks
  • Convenient Spring Boot Auto Configuration
  • Sensible defaults

Dependencies

  • Java 8
  • Any build tool using Maven Central, or direct download
  • Servlet Container (optional)
  • Apache HTTP Client (optional)
  • Spring Boot (optional)

Installation

Selectively add the following dependencies to your project:

<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-core</artifactId>
    <version>${tracer.version}</version>
</dependency>
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-servlet</artifactId>
    <version>${tracer.version}</version>
</dependency>
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-httpclient</artifactId>
    <version>${tracer.version}</version>
</dependency>
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-hystrix</artifactId>
    <version>${tracer.version}</version>
</dependency>
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-aspectj</artifactId>
    <version>${tracer.version}</version>
</dependency>
<dependency>
    <groupId>org.zalando</groupId>
    <artifactId>tracer-spring-boot-starter</artifactId>
    <version>${tracer.version}</version>
</dependency>

Usage

After adding the dependency, create a Tracer and specify the name of the traces you want to manage:

Tracer tracer = Tracer.create("X-Trace-ID");

If you need access to the current trace's value, call getValue() on it:

Trace trace = tracer.get("X-Trace-ID"); // this is a live-view that can be a shared as a singleton
entity.setLastModifiedBy(trace.getValue());

By default there can only be one trace active at a time. Sometimes it can be useful to stack traces:

Tracer tracer = Tracer.builder()
    .stacked(true)
    .trace("X-Trace-ID")
    .build();

Generators

When starting a new trace, Tracer will create trace value by means of pre-configured generator. You can override this on a per-trace level by adding the following to your setup:

Tracer tracer = Tracer.builder()
        .trace("X-Trace-ID", new CustomGenerator())
        .build();

There are several generator implementations included.

UUIDGenerator

This is the default generator implementation. It creates 36 characters long, random-based UUID string as a trace value.

FlowIDGenerator

This generator was created for historical reasons. It basically renders a UUID as a base64-encoded byte array, e.g. REcCvlqMSReeo7adheiYFA. The length of generated value is 22 characters.

PhraseGenerator

Phrase generator provides over 10^9 different phrases like:

tender_goodall_likes_evil_panini
nostalgic_boyd_helps_agitated_noyce
pensive_allen_tells_fervent_einstein

The generated phrase is 22 to 61 character long.

Listeners

For some use cases, e.g. integration with other frameworks and libraries, it might be useful to register a listener that gets notified every time a trace is either started or stopped.

Tracer tracer = Tracer.builder()
        .trace("X-Trace-ID")
        .listener(new CustomTraceListener())
        .build();

Tracer comes with a very useful listener by default, the MDCTraceListener:

Tracer tracer = Tracer.builder()
        .trace("X-Trace-ID")
        .listener(new MDCTraceListener())
        .build();

It allows you to add the trace id to every log line:

<PatternLayout pattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} [%X{X-Trace-ID}] - %msg%n"/>

Another built-in listener is the LoggingTraceListener which logs the start and end of every trace.

Servlet

On the server side is a single filter that you must be register in your filter chain. Make sure it runs very early — otherwise you might miss some crucial information when debugging.

You have to register the TracerFilter as a Filter in your filter chain:

context.addFilter("TracerFilter", new TracerFilter(tracer))
    .addMappingForUrlPatterns(EnumSet.of(REQUEST, ASYNC, ERROR), true, "/*");

Apache HTTP Client

Many client-side HTTP libraries on the JVM use the Apache HTTPClient, which is why Tracer comes with a request interceptor:

DefaultHttpClient client = new DefaultHttpClient();
client.addRequestInterceptor(new TracerHttpRequestInterceptor(tracer));

Hystrix

Tracer comes with built-in Hystrix support in form of a custom HystrixConcurrencyStrategy:

final HystrixPlugins plugins = HystrixPlugins.getInstance();
final HystrixConcurrencyStrategy delegate = HystrixConcurrencyStrategyDefault.getInstance(); // or another
plugins.registerConcurrencyStrategy(new TracerConcurrencyStrategy(tracer, delegate));

AspectJ

For background jobs and tests, you can use the built-in aspect:

@Traced
public void performBackgroundJob() {
    // do work
}

or you can manage the lifecycle yourself:

tracer.start();

try {
    // do work
} finally {
    tracer.stop();
}

Spring Boot Starter

Tracer comes with a convenient auto configuration for Spring Boot users that sets up aspect, servlet filter and MDC support automatically with sensible defaults:

Configuration Description Default
tracer.stacked Enables stacking of traces false
tracer.aspect.enabled Enables the TracedAspect true
tracer.async.enabled Enables for asynchronous tasks, i.e. @Async true
tracer.filter.enabled Enables the TracerFilter true
tracer.logging.enabled Enables the LoggingTraceListener false
tracer.logging.category Changes the category of the LoggingTraceListener org.zalando.tracer.Tracer
tracer.mdc.enabled Enables the MdcTraceListener true
tracer.scheduling.enabled Enables support for Task Scheduling, i.e. @Scheduled true
tracer.traces Configures actual traces, mapping from name to generator type (uuid, flow-id or phrase)
tracer:
    aspect.enabled: true
    async.enabled: true
    filter.enabled: true
    logging:
        enabled: false
        category: org.zalando.tracer.Tracer
    mdc.enabled: true
    scheduling.enabled: true
    traces:
        X-Trace-ID: uuid
        X-Flow-ID: flow-id

The TracerAutoConfiguration will automatically pick up any TraceListener bound in the application context.

Be aware: The TracerAutoConfiguration will, as long as tracer.async.enabled is set to true, register a AsyncConfigurer and Spring only allows one per Application Context. If this turns out to be a problem please disable the async support and configure it manually. Let us know if you think this needs to be improved.

Getting Help with Tracer

If you have questions, concerns, bug reports, etc., please file an issue in this repository's Issue Tracker.

Getting Involved/Contributing

To contribute, simply make a pull request and add a brief description (1-2 sentences) of your addition or change. For more details, check the contribution guidelines.

Open Issues

tracer's People

Contributors

alexanderyastrebov avatar bocytko avatar lukasniemeier-zalando avatar olliahonen avatar whiskeysierra avatar

Watchers

 avatar  avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.