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

feign.opentracing.TracingClient Maven / Gradle / Ivy

There is a newer version: 0.4.1
Show newest version
package feign.opentracing;

import io.opentracing.Scope;
import io.opentracing.Span;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;

import feign.Client;
import feign.Request;
import feign.Response;
import io.opentracing.SpanContext;
import io.opentracing.Tracer;
import io.opentracing.propagation.Format;
import io.opentracing.tag.Tags;

/**
 * OpenTracing Feign integration. This client wraps actual client implementation and creates tracing data for
 * outgoing requests.
 *
 * @author Pavol Loffay
 */
public class TracingClient implements Client {
    private static final Logger log = Logger.getLogger(TracingClient.class.getName());

    private Tracer tracer;
    private List spanDecorators;

    private Client delegate;

    /**
     * @param delegate delegating client
     * @param tracer tracer
     */
    public TracingClient(Client delegate, Tracer tracer) {
        this(delegate, tracer, Collections.singletonList(new FeignSpanDecorator.StandardTags()));
    }

    /**
     * @param delegate delegating client
     * @param tracer tracer
     * @param spanDecorators span decorators
     */
    public TracingClient(Client delegate, Tracer tracer, List spanDecorators) {
        this.delegate = delegate;
        this.tracer = tracer;
        this.spanDecorators = new ArrayList<>(spanDecorators);
    }

    @Override
    public Response execute(Request request, Request.Options options) throws IOException {
        Span span = tracer.buildSpan(request.method())
            .withTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT)
            .start();

        for (FeignSpanDecorator spanDecorator: spanDecorators) {
            try {
                spanDecorator.onRequest(request, options, span);
            } catch (Exception ex) {
                log.log(Level.SEVERE, "Exception during decorating span", ex);
            }
        }

        request = inject(span.context(), request);

        try (Scope scope = tracer.activateSpan(span)) {
            Response response = delegate.execute(request, options);
            for (FeignSpanDecorator spanDecorator : spanDecorators) {
                try {
                    spanDecorator.onResponse(response, options, span);
                } catch (Exception ex) {
                    log.log(Level.SEVERE, "Exception during decorating span", ex);
                }
            }
            return response;
        } catch (Exception ex) {
            for (FeignSpanDecorator spanDecorator: spanDecorators) {
                try {
                    spanDecorator.onError(ex, request, span);
                } catch (Exception exDecorator) {
                    log.log(Level.SEVERE, "Exception during decorating span", exDecorator);
                }
            }

            throw ex;
        } finally {
            span.finish();
        }
    }

    private Request inject(SpanContext spanContext, Request request) {
        Map> headersWithTracingContext = new HashMap<>(request.headers());
        tracer.inject(spanContext, Format.Builtin.HTTP_HEADERS, new HttpHeadersInjectAdapter(headersWithTracingContext));
        return request.create(request.method(), request.url(), headersWithTracingContext,request.body(),
                request.charset());
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy