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

com.alipay.sofa.tracer.plugins.zipkin.adapter.ZipkinV2SpanAdapter Maven / Gradle / Ivy

There is a newer version: 4.0.1
Show 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.zipkin.adapter;

import com.alipay.common.tracer.core.context.span.SofaTracerSpanContext;
import com.alipay.common.tracer.core.span.CommonSpanTags;
import com.alipay.common.tracer.core.span.LogData;
import com.alipay.common.tracer.core.span.SofaTracerSpan;
import com.alipay.common.tracer.core.utils.StringUtils;
import io.opentracing.tag.Tags;
import zipkin2.Endpoint;
import zipkin2.Span;

import java.net.InetAddress;
import java.util.Map;

/***
 * ZipkinV2SpanAdapter : convent sofaTracer span model to zipkin span model
 * @author guolei.sgl 05/09/2018
 * @since v.2.3.0
 */
public class ZipkinV2SpanAdapter {

    /**
     * cache and performance improve
     */
    private InetAddress localIpAddress = null;

    /**
     * convent sofaTracerSpan model to zipKinSpan model
     *
     * @param sofaTracerSpan original span
     * @return zipkinSpan model
     */
    public Span convertToZipkinSpan(SofaTracerSpan sofaTracerSpan) {
        if (sofaTracerSpan == null) {
            return null;
        }
        // spanId、parentId、tracerId
        Span.Builder zipkinSpanBuilder = Span.newBuilder();
        SofaTracerSpanContext context = sofaTracerSpan.getSofaTracerSpanContext();
        zipkinSpanBuilder.traceId(getValidTraceId(context));
        zipkinSpanBuilder.id(spanIdToLong(context.getSpanId()));
        if (StringUtils.isNotBlank(context.getParentId())) {
            zipkinSpanBuilder.parentId(spanIdToLong(context.getParentId()));
        }

        // timestamp & duration
        long start = sofaTracerSpan.getStartTime() * 1000;
        long finish = sofaTracerSpan.getEndTime() * 1000;
        zipkinSpanBuilder.timestamp(start);
        zipkinSpanBuilder.duration(finish - start);

        // kind
        Map tagsWithStr = sofaTracerSpan.getTagsWithStr();
        String kindStr = tagsWithStr.get(Tags.SPAN_KIND.getKey());
        if (StringUtils.isNotBlank(kindStr) && kindStr.equals(Tags.SPAN_KIND_SERVER)) {
            zipkinSpanBuilder.kind(Span.Kind.SERVER);
        } else {
            zipkinSpanBuilder.kind(Span.Kind.CLIENT);
        }

        // Endpoint
        Endpoint endpoint = getZipkinEndpoint(sofaTracerSpan);
        zipkinSpanBuilder.localEndpoint(endpoint);

        // Tags
        this.addZipkinTags(zipkinSpanBuilder, sofaTracerSpan);

        // span name
        String operationName = sofaTracerSpan.getOperationName();
        if (StringUtils.isNotBlank(operationName)) {
            zipkinSpanBuilder.name(operationName);
        } else {
            zipkinSpanBuilder.name(StringUtils.EMPTY_STRING);

            if (StringUtils.isNotBlank(sofaTracerSpan.getTagsWithStr().get("message.event.code"))) {
                // set messageTopic:messageEventCode as name
                String name = sofaTracerSpan.getTagsWithStr().get("message.topic") + ":"
                              + sofaTracerSpan.getTagsWithStr().get("message.event.code");
                zipkinSpanBuilder.name(name);
            } else if (StringUtils.isNotBlank(sofaTracerSpan.getTagsWithStr().get("table.name"))) {
                // set tableName as name
                zipkinSpanBuilder.name(sofaTracerSpan.getTagsWithStr().get("table.name"));
            } else if (StringUtils.isNotBlank(sofaTracerSpan.getTagsWithStr()
                .get("datasource.name"))) {
                // set datasourceName as name
                zipkinSpanBuilder.name(sofaTracerSpan.getTagsWithStr().get("datasource.name"));
            }
        }

        // Annotations
        this.addZipkinAnnotations(zipkinSpanBuilder, sofaTracerSpan);

        return zipkinSpanBuilder.build();
    }

    private String getValidTraceId(SofaTracerSpanContext context) {
        String traceId = context.getTraceId();
        if (traceId.endsWith("T")) {
            traceId = traceId.substring(0, traceId.length() - 1);
        }
        return traceId;
    }

    public static long spanIdToLong(String spanId) {
        return FNV64HashCode(spanId);
    }

    /**
     * from http://en.wikipedia.org/wiki/Fowler_Noll_Vo_hash
     *
     * @param data String data
     * @return fnv hash code
     */
    public static long FNV64HashCode(String data) {
        //hash FNVHash64 : http://www.isthe.com/chongo/tech/comp/fnv/index.html#FNV-param
        long hash = 0xcbf29ce484222325L;
        for (int i = 0; i < data.length(); ++i) {
            char c = data.charAt(i);
            hash ^= c;
            hash *= 0x100000001b3L;
        }
        return hash;
    }

    private Endpoint getZipkinEndpoint(SofaTracerSpan span) {
        if (localIpAddress == null) {
            localIpAddress = NetUtils.getLocalAddress();
        }
        String appName = span.getTagsWithStr().get(CommonSpanTags.LOCAL_APP);
        return Endpoint.newBuilder().serviceName(appName).ip(localIpAddress).build();
    }

    /**
     * Put the baggage data into the tags
     *
     * @param zipkinSpan
     * @param span
     */
    private void addZipkinTagsWithBaggage(Span.Builder zipkinSpan, SofaTracerSpan span) {
        SofaTracerSpanContext sofaTracerSpanContext = span.getSofaTracerSpanContext();
        if (sofaTracerSpanContext != null) {
            Map sysBaggage = sofaTracerSpanContext.getSysBaggage();
            for (Map.Entry e : sysBaggage.entrySet()) {
                zipkinSpan.putTag(e.getKey(), e.getValue());
            }
            Map bizBaggage = sofaTracerSpanContext.getBizBaggage();
            for (Map.Entry e : bizBaggage.entrySet()) {
                zipkinSpan.putTag(e.getKey(), e.getValue());
            }
        }
    }

    /**
     * convent Annotations
     *
     * @param zipkinSpan
     * @param span
     */
    private void addZipkinAnnotations(Span.Builder zipkinSpan, SofaTracerSpan span) {
        for (LogData logData : span.getLogs()) {
            Map fields = logData.getFields();
            if (fields == null || fields.size() <= 0) {
                continue;
            }
            for (Map.Entry entry : fields.entrySet()) {
                // zipkin has been support default log event depend on span kind & serviceName
                if (!(entry.getValue().toString().equals(LogData.CLIENT_RECV_EVENT_VALUE)
                      || entry.getValue().toString().equals(LogData.CLIENT_SEND_EVENT_VALUE)
                      || entry.getValue().toString().equals(LogData.SERVER_RECV_EVENT_VALUE) || entry
                    .getValue().toString().equals(LogData.SERVER_SEND_EVENT_VALUE))) {
                    zipkinSpan.addAnnotation(logData.getTime() * 1000, entry.getValue().toString());
                }
            }
        }
    }

    /**
     * convent tags
     *
     * @param zipkinSpan
     * @param span
     */
    private void addZipkinTags(Span.Builder zipkinSpan, SofaTracerSpan span) {

        for (Map.Entry e : span.getTagsWithStr().entrySet()) {
            zipkinSpan.putTag(e.getKey(), e.getValue());
        }
        for (Map.Entry e : span.getTagsWithNumber().entrySet()) {
            zipkinSpan.putTag(e.getKey(), e.getValue().toString());
        }
        for (Map.Entry e : span.getTagsWithBool().entrySet()) {
            zipkinSpan.putTag(e.getKey(), e.getValue().toString());
        }

        SofaTracerSpanContext context = span.getSofaTracerSpanContext();
        zipkinSpan.putTag("origin.span.id", context.getSpanId());
        zipkinSpan.putTag("origin.parent.span.id", context.getParentId());

        addZipkinTagsWithBaggage(zipkinSpan, span);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy