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

com.alipay.sofa.tracer.plugins.springcloud.instruments.feign.SofaTracerFeignClient Maven / Gradle / Ivy

The newest version!
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.alipay.sofa.tracer.plugins.springcloud.instruments.feign;

import com.alipay.common.tracer.core.SofaTracer;
import com.alipay.common.tracer.core.appender.self.SelfLog;
import com.alipay.common.tracer.core.configuration.SofaTracerConfiguration;
import com.alipay.common.tracer.core.registry.ExtendFormat;
import com.alipay.common.tracer.core.span.CommonSpanTags;
import com.alipay.common.tracer.core.span.SofaTracerSpan;
import com.alipay.common.tracer.core.utils.StringUtils;
import com.alipay.sofa.tracer.plugins.springcloud.carriers.FeignRequestHeadersCarrier;
import com.alipay.sofa.tracer.plugins.springcloud.tracers.FeignClientTracer;
import feign.Client;
import feign.Request;
import feign.Response;
import io.opentracing.tag.Tags;

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;

/**
 * @author: guolei.sgl ([email protected]) 2019/3/13 10:50 AM
 * @since:
 **/
public class SofaTracerFeignClient implements Client {

    private Client            delegate;

    private FeignClientTracer feignClientTracer;

    public SofaTracerFeignClient(Client delegate) {
        this.delegate = delegate;
    }

    @Override
    public Response execute(Request request, Request.Options options) {
        if (feignClientTracer == null) {
            feignClientTracer = FeignClientTracer.getFeignClientTracerSingleton();
        }
        SofaTracerSpan sofaTracerSpan = null;
        int resultCode = -1;
        try {
            sofaTracerSpan = feignClientTracer.clientSend(request.httpMethod().name());
            // new a headers map
            LinkedHashMap> headers = new LinkedHashMap<>(
                request.headers());
            appendRequestSpanTagsAndInject(request, sofaTracerSpan, headers);
            // renew request with the headers that have been injected into the carrier
            request = Request.create(request.httpMethod(), request.url(), headers, request.body(),
                request.charset());
            Response response = delegate.execute(request, options);
            // set result tags
            appendResponseSpanTags(response, sofaTracerSpan);
            resultCode = response.status();
            return response;
        } catch (Exception ex) {
            appendExceptionSpanTags(request, sofaTracerSpan, ex);
            throw new RuntimeException(ex);
        } finally {
            if (sofaTracerSpan != null) {
                // do clear tl
                feignClientTracer.clientReceive(String.valueOf(resultCode));
            }
        }
    }

    /**
     * append exception tags for current span
     * @param request
     * @param sofaTracerSpan
     */
    private void appendExceptionSpanTags(Request request, SofaTracerSpan sofaTracerSpan,
                                         Exception ex) {
        appendRequestSpanTags(request, sofaTracerSpan);
        sofaTracerSpan.setTag(CommonSpanTags.RESULT_CODE, -1);
        sofaTracerSpan.setTag(Tags.ERROR.getKey(), ex.getMessage());
    }

    private String[] parseRemoteHostAndPort(Request request) {
        String[] hostWithPort = new String[2];
        URL requestUrl = null;
        try {
            requestUrl = new URL(request.url());
        } catch (MalformedURLException e) {
            SelfLog.error("cannot parse remote host and port. request:" + request.url(), e);
        }
        hostWithPort[0] = requestUrl != null ? requestUrl.getHost() : "";
        hostWithPort[1] = String.valueOf(requestUrl != null ? requestUrl.getPort() : -1);
        return hostWithPort;
    }

    /**
     * append response tags for current span
     * @param response
     * @param sofaTracerSpan
     */
    private void appendResponseSpanTags(Response response, SofaTracerSpan sofaTracerSpan) {
        if (sofaTracerSpan == null) {
            return;
        }
        Integer responseSize = null;
        if (response.body() != null) {
            responseSize = response.body().length();
        }
        sofaTracerSpan.setTag(CommonSpanTags.RESP_SIZE, responseSize);
        sofaTracerSpan.setTag(CommonSpanTags.CURRENT_THREAD_NAME, Thread.currentThread().getName());
        sofaTracerSpan.setTag(CommonSpanTags.RESULT_CODE, response.status());
    }

    /**
     * append request tags for current span
     * @param request
     * @param sofaTracerSpan
     * @param headers
     */
    private void appendRequestSpanTagsAndInject(Request request, SofaTracerSpan sofaTracerSpan,
                                                LinkedHashMap> headers) {
        // set tags
        appendRequestSpanTags(request, sofaTracerSpan);
        // inject carrier into headers
        this.injectCarrier(headers, sofaTracerSpan);
    }

    private void appendRequestSpanTags(Request request, SofaTracerSpan sofaTracerSpan) {
        if (sofaTracerSpan == null) {
            return;
        }
        // appName
        String appName = SofaTracerConfiguration.getProperty(
            SofaTracerConfiguration.TRACER_APPNAME_KEY, StringUtils.EMPTY_STRING);
        //methodName
        String methodName = request.httpMethod().name();
        //appName
        sofaTracerSpan.setTag(CommonSpanTags.LOCAL_APP, appName == null ? StringUtils.EMPTY_STRING
            : appName);
        sofaTracerSpan.setTag(Tags.SPAN_KIND.getKey(), Tags.SPAN_KIND_CLIENT);
        sofaTracerSpan.setTag(CommonSpanTags.REMOTE_APP, StringUtils.EMPTY_STRING);
        sofaTracerSpan.setTag(CommonSpanTags.REQUEST_URL, request.url());
        sofaTracerSpan.setTag(CommonSpanTags.METHOD, methodName);
        String[] hostWithPort = parseRemoteHostAndPort(request);
        sofaTracerSpan.setTag(CommonSpanTags.REMOTE_HOST, hostWithPort[0]);
        sofaTracerSpan.setTag(CommonSpanTags.REMOTE_PORT, hostWithPort[1]);

        if (request.body() != null) {
            sofaTracerSpan.setTag(CommonSpanTags.REQ_SIZE, request.body().length);
        } else {
            sofaTracerSpan.setTag(CommonSpanTags.REQ_SIZE, 0);
        }
    }

    private void injectCarrier(Map> headers, SofaTracerSpan currentSpan) {
        SofaTracer sofaTracer = this.feignClientTracer.getSofaTracer();
        sofaTracer.inject(currentSpan.getSofaTracerSpanContext(),
            ExtendFormat.Builtin.B3_HTTP_HEADERS, new FeignRequestHeadersCarrier(headers));
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy