All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.opentracing.contrib.zipkin.ZipkinSpan Maven / Gradle / Ivy

package io.opentracing.contrib.zipkin;

import io.opentracing.SpanContext;
import io.opentracing.contrib.zipkin.time.TimeUtil;
import io.opentracing.contrib.zipkin.time.Timer;
import io.opentracing.tag.Tags;
import java.math.BigInteger;
import java.net.Inet6Address;
import java.net.UnknownHostException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicLong;
import zipkin.Annotation;
import zipkin.BinaryAnnotation;
import zipkin.Constants;
import zipkin.Endpoint;
import zipkin.Span;
import zipkin.reporter.Reporter;

public class ZipkinSpan implements io.opentracing.Span {

    private final Span.Builder builder;
    private final Reporter reporter;
    private final Timer timer;
    private final Endpoint.Builder endpointBuilder;
    private final Collection annotations;
    private final Map baggage = new HashMap<>();
    private Boolean isClient;
    private boolean error;
    private boolean isFinished;

    public ZipkinSpan(Span.Builder span, Reporter reporter, Timer timer) {
        this.builder = span;
        this.endpointBuilder = Endpoint.builder();
        this.reporter = reporter;
        this.timer = timer;
        this.annotations = new ArrayList<>();
    }

    public SpanContext context() {
        Span span = builder.build();
        return new ZipkinSpanContext(span.id, span.parentId, span.traceId, baggage.entrySet());
    }

    public void finish() {
        finish(TimeUtil.epochMicros(timer.getEnd()));
    }

    public void finish(long finishMicros) {
        if (!isFinished) {
            isFinished = true;
            Span.Builder builder = this.builder.build().toBuilder();

            long startMicros = TimeUtil.epochMicros(timer.getStart());
            builder.timestamp(startMicros).duration(finishMicros - startMicros);

            Endpoint endpoint = endpointBuilder.build();
            if (isClient != null) {
                builder.addAnnotation(
                    Annotation.builder()
                        .endpoint(endpoint)
                        .timestamp(startMicros)
                        .value(isClient ? Constants.CLIENT_SEND : Constants.SERVER_SEND)
                        .build()
                );
                builder.addAnnotation(
                    Annotation.builder()
                        .endpoint(endpoint)
                        .timestamp(finishMicros)
                        .value(isClient ? Constants.CLIENT_RECV : Constants.SERVER_RECV)
                        .build()
                );
            }

            if (error) {
                builder.addAnnotation(Annotation.builder().endpoint(endpoint).value(Constants.ERROR).build());
            }

            for (Annotation.Builder annotationBuilder : annotations) {
                builder.addAnnotation(annotationBuilder.endpoint(endpoint).build());
            }

            reporter.report(builder.build());
        }
    }

    public void close() {
        finish();
    }

    public io.opentracing.Span setTag(String key, String value) {
        if (key.equals(Tags.SPAN_KIND.getKey())) {
            isClient = value.equals(Tags.SPAN_KIND_CLIENT) ? Boolean.TRUE : value.equals(Tags.SPAN_KIND_SERVER) ? Boolean.FALSE : null;
        } else if (key.equals(Tags.PEER_SERVICE.getKey())) {
            endpointBuilder.serviceName(value);
        } else if (key.equals(Tags.PEER_HOST_IPV6.getKey())) {
            try {
                endpointBuilder.ipv6(Inet6Address.getByName(value).getAddress());
            } catch (UnknownHostException e) {
            }
        } else {
            builder.addBinaryAnnotation(BinaryAnnotation.builder().key(key).type(BinaryAnnotation.Type.STRING).value(value).build());
        }
        return this;
    }

    public io.opentracing.Span setTag(String key, boolean value) {
        if (key.equals(Tags.ERROR.getKey())) {
            error = value;
        } else {
            builder.addBinaryAnnotation(BinaryAnnotation.builder().key(key).type(BinaryAnnotation.Type.BOOL).value(new byte[]{value ? (byte) 1 : (byte) 0}).build());
        }
        return this;
    }

    public io.opentracing.Span setTag(String key, Number value) {
        if (key.equals(Tags.PEER_HOST_IPV4.getKey())) {
            endpointBuilder.ipv4(value.intValue());
        } else if (key.equals(Tags.PEER_PORT.getKey())) {
            endpointBuilder.port(value.shortValue());
        } else {
            BinaryAnnotation.Builder annotationBuilder = BinaryAnnotation.builder().key(key);
            final ByteBuffer bytes;
            if (value instanceof Byte || value instanceof Short) {
                bytes = ByteBuffer.allocate(Short.BYTES).putShort(value.shortValue());
                annotationBuilder.type(BinaryAnnotation.Type.I16);
            } else if (value instanceof Integer || value instanceof AtomicInteger) {
                bytes = ByteBuffer.allocate(Integer.BYTES).putInt(value.intValue());
                annotationBuilder.type(BinaryAnnotation.Type.I32);
            } else if (value instanceof Long || value instanceof AtomicLong || value instanceof BigInteger) {
                bytes = ByteBuffer.allocate(Long.BYTES).putLong(value.longValue());
                annotationBuilder.type(BinaryAnnotation.Type.I64);
            } else {
                bytes = ByteBuffer.allocate(Double.BYTES).putDouble(value.doubleValue());
                annotationBuilder.type(BinaryAnnotation.Type.DOUBLE);
            }
            builder.addBinaryAnnotation(annotationBuilder.value(bytes.array()).build());
        }
        return this;
    }

    public io.opentracing.Span log(Map fields) {
        return log(TimeUtil.epochMicros(timer.getEnd()), fields);
    }

    public io.opentracing.Span log(long timestampMicroseconds, Map fields) {
        for (Map.Entry field : fields.entrySet()) {
            log(timestampMicroseconds, String.format("%s:%s", field.getKey(), field.getValue()));
        }
        return this;
    }

    public io.opentracing.Span log(String event) {
        return log(TimeUtil.epochMicros(timer.getEnd()), event);
    }

    public io.opentracing.Span log(long timestampMicroseconds, String event) {
        annotations.add(Annotation.builder().timestamp(timestampMicroseconds).value(event));
        return this;
    }

    public io.opentracing.Span log(String eventName, Object payload) {
        return this;
    }

    public io.opentracing.Span log(long timestampMicroseconds, String eventName, Object payload) {
        return log(timestampMicroseconds, eventName);
    }

    public io.opentracing.Span setBaggageItem(String key, String value) {
        baggage.put(key, value);
        return this;
    }

    public String getBaggageItem(String key) {
        return baggage.get(key);
    }

    public io.opentracing.Span setOperationName(String operationName) {
        builder.name(operationName);
        return this;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy