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

org.springframework.cloud.sleuth.instrument.web.ExtraSleuthHttpClientParser Maven / Gradle / Ivy

The newest version!
package org.springframework.cloud.sleuth.instrument.web;

import brave.SpanCustomizer;
import brave.http.HttpAdapter;
import brave.http.HttpClientParser;
import cn.patterncat.tracing.ExtraTracingProperties;
import cn.patterncat.tracing.helper.MaskHelper;
import org.springframework.cloud.sleuth.util.SpanNameUtil;

import java.net.URI;
import java.util.function.Supplier;

/**
 * SleuthHttpClientParser
 * Created by cat on 2019-01-23.
 */
public class ExtraSleuthHttpClientParser extends HttpClientParser {

    private static final String HOST_KEY = "http.host";

    private static final String METHOD_KEY = "http.method";

    private static final String PATH_KEY = "http.path";

    private static final String URL_KEY = "http.url";

    private static final String STATUS_CODE_KEY = "http.status";

    private static final String NO_RESPONSE_STATUS = "-1";

    private final TraceKeys traceKeys;

    private final ExtraTracingProperties properties;

    ExtraSleuthHttpClientParser(TraceKeys traceKeys, ExtraTracingProperties properties) {
        this.traceKeys = traceKeys;
        this.properties = properties;
    }

    @Override
    protected  String spanName(HttpAdapter adapter, Req req) {
        return getName(URI.create(adapter.url(req)));
    }

    @Override
    public  void request(HttpAdapter adapter, Req req,
                              SpanCustomizer customizer) {
        super.request(adapter, req, customizer);
        String url = adapter.url(req);
        URI uri = URI.create(url);
        addRequestTags(customizer, url, uri,
                adapter.method(req));
        this.traceKeys.getHttp().getHeaders().forEach(((s) -> {
            String headerValue = adapter.requestHeader(req, s);
            if (headerValue != null) {
                customizer.tag(key(s), headerValue);
            }
        }));
    }

    private String key(String key) {
        return this.traceKeys.getHttp().getPrefix() + key.toLowerCase();
    }

    private String getName(URI uri) {
        // The returned name should comply with RFC 882 - Section 3.1.2.
        // i.e Header values must composed of printable ASCII values.
        return SpanNameUtil.shorten(uriScheme(uri) + ":" + uri.getRawPath());
    }

    private String uriScheme(URI uri) {
        return uri.getScheme() == null ? "http" : uri.getScheme();
    }

    private void addRequestTags(SpanCustomizer customizer,String url, URI uri, String method) {
        String path = uri.getPath();
        //NOTE url可能包含需要mask的queryString,但是url包含了host:port,单纯host缺少port信息
        String maskedUrl = properties.mask(url, new Supplier() {
            @Override
            public String get() {
                return path;
            }
        });
        customizer.tag(URL_KEY, maskedUrl);

        String host = uri.getHost();
        if (host != null) {
            customizer.tag(HOST_KEY, host);
        }
        customizer.tag(PATH_KEY, path);
        customizer.tag(METHOD_KEY, method);
    }

    @Override
    public  void response(HttpAdapter adapter, Resp res, Throwable error, SpanCustomizer customizer) {
        Integer statusCode = null;
        if (res != null) {
            statusCode = adapter.statusCode(res);
            String nameFromRoute = spanNameFromRoute(adapter, res, statusCode);
            if (nameFromRoute != null) customizer.name(nameFromRoute);
            customizer.tag(STATUS_CODE_KEY, statusCode == null ? NO_RESPONSE_STATUS : String.valueOf(statusCode));
        } else {
            customizer.tag(STATUS_CODE_KEY, NO_RESPONSE_STATUS);
        }
        error(statusCode, error, customizer);
    }

    static  String spanNameFromRoute(HttpAdapter adapter, Resp res, int statusCode) {
        String method = adapter.methodFromResponse(res);
        if (method == null) return null; // don't undo a valid name elsewhere
        String route = adapter.route(res);
        if (route == null) return null; // don't undo a valid name elsewhere
        if (!"".equals(route)) return method + " " + route;
        if (statusCode / 100 == 3) return method + " redirected";
        if (statusCode == 404) return method + " not_found";
        return null; // unexpected
    }

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy