• This repository has been archived on 23/May/2023
  • Stars
    star
    1,684
  • Rank 27,715 (Top 0.6 %)
  • Language
    Java
  • License
    Apache License 2.0
  • Created about 9 years ago
  • Updated about 3 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

OpenTracing API for Java. 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163

Build Status Coverage Status Released Version

OpenTracing API for Java

This library is a Java platform API for OpenTracing.

Required Reading

In order to understand the Java platform API, one must first be familiar with the OpenTracing project and terminology more specifically.

Usage

Initialization

Initialization is OpenTracing-implementation-specific. Generally speaking, the pattern is to initialize a Tracer once for the entire process and to use that Tracer for the remainder of the process lifetime. It is a best practice to set the GlobalTracer, even if also making use of cleaner, more modern dependency injection. (See the next section below for rationale)

Accessing the Tracer

Where possible, use some form of dependency injection (of which there are many) to access the Tracer instance. For vanilla application code, this is often reasonable and cleaner for all of the usual DI reasons.

That said, instrumentation for packages that are themselves statically configured (e.g., JDBC drivers) may be unable to make use of said DI mechanisms for Tracer access, and as such they should fall back on GlobalTracer. By and large, OpenTracing instrumentation should always allow the programmer to specify a Tracer instance to use for instrumentation, though the GlobalTracer is a reasonable fallback or default value.

Within-process propagation and the Scope

For any thread, at most one Span may be "active". Of course there may be many other Spans involved with the thread which are (a) started, (b) not finished, and yet (c) not "active": perhaps they are waiting for I/O, blocked on a child Span, or otherwise off of the critical path.

It's inconvenient to pass an active Span from function to function manually, so OpenTracing requires that every Tracer contains a ScopeManager that grants access to the active Span along with a Scope to signal deactivation. Any Span may be transferred to another callback or thread, but not Scope; more on this below.

Accessing the active Span

Access to the active span is straightforward:

io.opentracing.Tracer tracer = ...;
...
Span span = tracer.scopeManager().activeSpan();
if (span != null) {
    span.log("...");
}

Starting a new Span

The common case starts a Span and then sets it as the active instance via ScopeManager:

io.opentracing.Tracer tracer = ...;
...
Span span = tracer.buildSpan("someWork").start();
try (Scope scope = tracer.scopeManager().activate(span)) {
    // Do things.
} catch(Exception ex) {
    Tags.ERROR.set(span, true);
    span.log(Map.of(Fields.EVENT, "error", Fields.ERROR_OBJECT, ex, Fields.MESSAGE, ex.getMessage()));
} finally {
    span.finish();
}

If there is already an active Span, it will act as the parent to any newly started Span unless the programmer invokes ignoreActiveSpan() at buildSpan() time or specified parent context explicitly:

io.opentracing.Tracer tracer = ...;
...
Span span = tracer.buildSpan("someWork").ignoreActiveSpan().start();

Deferring asynchronous work

Consider the case where a Span's lifetime logically starts in one thread and ends in another. For instance, the Span's own internal timing breakdown might look like this:

 [ ServiceHandlerSpan                                 ]
 |路FunctionA路|路路路路路waiting on an RPC路路路路路路|路FunctionB路|
            
---------------------------------------------------------> time

The "ServiceHandlerSpan" is active while it's running FunctionA and FunctionB, and inactive while it's waiting on an RPC (presumably modelled as its own Span, though that's not the concern here).

The ScopeManager API makes it possible to fetch the span in FunctionA and re-activate it in FunctionB. Note that every Tracer contains a ScopeManager. These are the steps:

  1. Start a Span via start.
  2. At the beginning of the closure/Runnable/Future/etc itself, invoke tracer.scopeManager().activate(span) to re-activate the Span and get a new Scope, then close() it when the Span is no longer active (or use try-with-resources for less typing).
  3. Invoke span.finish() when the work is done.

Here is an example using CompletableFuture:

io.opentracing.Tracer tracer = ...;
...
// STEP 1 ABOVE: start the Span.
final Span span = tracer.buildSpan("ServiceHandlerSpan").start();
try (Scope scope = tracer.scopeManager().activate(span)) {
    // Do work.
    ...

    future = CompletableFuture.supplyAsync(() -> {

        // STEP 2 ABOVE: reactivate the Span in the callback.
        try (Scope scope = tracer.scopeManager().activate(span)) {
            ...
        }
    }).thenRun(() -> {
        // STEP 3 ABOVE: finish the Span when the work is done.
        span.finish();
    });
}

Observe that passing Scope to another thread or callback is not supported. Only Span can be used under this scenario.

In practice, all of this is most fluently accomplished through the use of an OpenTracing-aware ExecutorService and/or Runnable/Callable adapter; they factor out most of the typing.

Deprecated members since 0.31

ScopeManager.active(Span, boolean) and SpanBuilder.startActive() have been deprecated as part of removing automatic Span finish upon Scope close, as doing it through try-with statements would make it hard to properly handle errors (Span objects would get finished before a catch block would be reached). This improves API safety, and makes it more difficult to do the wrong thing and end up with unexpected errors.

Scope.span() and ScopeManager.scope() have been deprecated in order to prevent the anti-pattern of passing Scope objects between threads (Scope objects are not guaranteed to be thread-safe). Now Scope will be responsible for Span deactivation only, instead of being a Span container.

Instrumentation Tests

This project has a working design of interfaces for the OpenTracing API. There is a MockTracer to facilitate unit-testing of OpenTracing Java instrumentation.

Packages are deployed to Maven Central under the io.opentracing group.

Development

This is a maven project, and provides a wrapper, ./mvnw to pin a consistent version. Run ./mvnw clean install to build, run tests, and create jars.

This wrapper was generated by mvn -N io.takari:maven:wrapper -Dmaven=3.5.0

License

Apache 2.0 License.

Contributing

See Contributing for matters such as license headers.

More Repositories

1

opentracing-go

OpenTracing API for Go. 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Go
3,493
star
2

specification

A place to document (and discuss) the OpenTracing specification. 馃洃 This project is DEPRECATED! https://github.com/opentracing/specification/issues/163
1,173
star
3

opentracing-javascript

OpenTracing API for Javascript (both Node and browser). 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
TypeScript
1,091
star
4

opentracing-python

OpenTracing API for Python. 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Python
755
star
5

opentracing-csharp

OpenTracing API for C# (.NET). 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
C#
517
star
6

opentracing-php

OpenTracing API for PHP
PHP
507
star
7

opentracing-cpp

OpenTracing API for C++. 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
C++
320
star
8

opentracing-ruby

OpenTracing API for Ruby
Ruby
173
star
9

opentracing.io

OpenTracing website
SCSS
116
star
10

basictracer-go

Basic implementation of the OpenTracing API for Go. 馃洃 This library is DEPRECATED!
Go
81
star
11

opentracing-rust

OpenTracing API for Rust
Rust
76
star
12

opentracing-c

ANSI C API for OpenTracing
C
33
star
13

opentracing-lua

OpenTracing API for Lua
Lua
29
star
14

opentracing-objc

OpenTracing API for Objective-C. 馃洃 This library is DEPRECATED! https://github.com/opentracing/specification/issues/163
Objective-C
28
star
15

basictracer-python

The Python implementation of the "BasicTracer" reference implementation. 馃洃 This library is DEPRECATED!
Python
26
star
16

opentracing-swift

This is a prototype OpenTracing API for the Swift language. This is intended to explore and validate decisions about implementing the OpenTracing API in Swift.
Swift
17
star
17

lua-bridge-tracer

Provides an implementation of the Lua OpenTracing API on top of the C++ API
C++
14
star
18

basictracer-csharp

Reference implementation of OpenTracing API in C#
12
star
19

documentation

Please see opentracing.io repo instead
7
star
20

basictracer-javascript

JavaScript
7
star
21

contrib

A place (or, really, a pointer) for community contributions to OpenTracing
5
star
22

opentracing-java-v030

Backwards compatibility layer for Java v0.30
Java
3
star
23

c-bridge-tracer

Experimental C binding for C++ tracers
1
star