Open tracing not showing the relation between spans

1.9k views Asked by At

I am trying to use open tracing to show a trace and relation between 2 spans.

From the following implementation, I am expecting the following structure for the trace.

spanOne (parent)
    spanTwo (child)

Instead I end up with no relation between the 2, each having its own block.

spanOne

spanTwo

Implementation

Just an interface

@FunctionalInterface
public interface AddData {
    Single<Response> add(Request request);
}

class one implementating above interface

import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import rx.Single;

public class AddDataClassOne implements AddData {

    private final String name;
    private final Tracer tracer;

    public AddDataClassOne(String name, Tracer tracer) {
        this.name = name;
        this.tracer = tracer;
    }

    @Override
    public Single<Response> add(Request request) {

        final Span span = this.tracer.buildSpan(this.name).start();
        try(Scope ignored = this.tracer.scopeManager().activate(span)) {
            // some other logic
            return Single.just(new Response());
        } finally {
            span.finish();
        }
    }
}

class two implementing above interface (identical to class 1, removed other logic to keep it simple)

import io.opentracing.Scope;
import io.opentracing.Span;
import io.opentracing.Tracer;
import rx.Single;

public class AddDataClassTwo implements AddData {

    private final String name;
    private final Tracer tracer;

    public AddDataClassTwo(String name, Tracer tracer) {
        this.name = name;
        this.tracer = tracer;
    }

    @Override
    public Single<Response> add(Request request) {

        final Span span = this.tracer.buildSpan(this.name).start();
        try(Scope ignored = this.tracer.scopeManager().activate(span)) {
            // some other logic
            return Single.just(new Response());
        } finally {
            span.finish();
        }
    }
}

Main class where I am wrapping the parent class over the child class and calling the add method.

import io.jaegertracing.internal.JaegerTracer;
import io.jaegertracing.internal.samplers.ConstSampler;
import io.opentracing.Tracer;

import java.util.function.UnaryOperator;

public class MainClass {

    private static final Tracer tracer = new JaegerTracer.Builder("sample-test")
            .withSampler(new ConstSampler(true))
            .build();

    public static void main(String[] args) {

        UnaryOperator<AddData> operator = addData -> new AddDataClassOne("spanOne", tracer);
        AddDataClassTwo addDataClassTwo = new AddDataClassTwo("spanTwo", tracer);

        AddData apply = operator.apply(addDataClassTwo);
        apply.add(new Request()).subscribe();
    }
}

From the docs:

If there is already an active span, it will act as the parent to the span created by buildSpan().

Based on the examples given, each logic has its own span name captured within a try block which is the same as what am doing here.

Referring to this page: The last part under: Propagate the in-process context on this page https://github.com/yurishkuro/opentracing-tutorial/tree/master/java/src/main/java/lesson02

Could I get some advice on what am missing? Thanks.

1

There are 1 answers

0
Vova Tymtsiv On

From what I see the reason is that after executing AddDataClassOne.add() span already finished, so it can't have any child spans.

So when in AddDataClassTwo.add you call start(), it can't find active span, and can't become a child of it.

In order to achieve desired structure, you have to call AddDataClassTwo.add before you call span.finish().

Note: The most deeply nested span should always be closed first, and next closing to the initially opened span - parent.