pkg/tools/tracing/tracing.go (124 lines of code) (raw):
// Licensed to 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. Apache Software Foundation (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 tracing
import (
"encoding/base64"
"fmt"
"strings"
accesslogv3 "skywalking.apache.org/repo/goapi/collect/ebpf/accesslog/v3"
agentv3 "skywalking.apache.org/repo/goapi/collect/language/agent/v3"
)
type Provider int
var (
ProviderSkyWalking Provider = 1
ProviderZipkin = 2
)
type Context interface {
TraceID() string
TraceSegmentID() string
SpanID() string
Provider() *TraceContextProvider
}
type TraceContextProvider struct {
SpanAttachType agentv3.SpanAttachedEvent_SpanReferenceType
AccessLogType accesslogv3.AccessLogTraceInfoProvider
Name string
}
type SkyWalkingTracingContext struct {
TraceID0 string
SegmentID0 string
SpanID0 string
ParentService string
ParentServiceInstance string
ParentEndpoint string
AddressUsedAtClient string
}
type ZipkinTracingContext struct {
TraceID0 string
SpanID0 string
}
func (w *SkyWalkingTracingContext) TraceID() string {
return w.TraceID0
}
func (w *SkyWalkingTracingContext) TraceSegmentID() string {
return w.SegmentID0
}
func (w *SkyWalkingTracingContext) SpanID() string {
return w.SpanID0
}
func (w *SkyWalkingTracingContext) Provider() *TraceContextProvider {
return &TraceContextProvider{
SpanAttachType: agentv3.SpanAttachedEvent_SKYWALKING,
AccessLogType: accesslogv3.AccessLogTraceInfoProvider_SkyWalking,
Name: "skywalking",
}
}
func AnalyzeTracingContext(fetcher func(key string) string) (Context, error) {
// skywalking v3
if sw8Header := fetcher("sw8"); sw8Header != "" {
return analyzeSkyWalking8TracingContext(sw8Header)
}
// zipkin
if zipkinSingleContext := fetcher("b3"); zipkinSingleContext != "" {
if ctx := analyzeZipkinTracingContextWithSingleData(zipkinSingleContext); ctx != nil {
return ctx, nil
}
}
if zipkinTraceID := fetcher("x-b3-traceid"); zipkinTraceID != "" {
if spanID := fetcher("x-b3-spanid"); spanID != "" {
return analyzeZipkinTracingContextWithSpecificData(zipkinTraceID, spanID), nil
}
}
return nil, nil
}
func analyzeSkyWalking8TracingContext(val string) (*SkyWalkingTracingContext, error) {
parts := strings.Split(val, "-")
if len(parts) != 8 {
return nil, fmt.Errorf("sw8 analyze error, value: %s", val)
}
var err error
ctx := &SkyWalkingTracingContext{}
ctx.TraceID0, err = decodeBase64StringValue(err, parts[1])
ctx.SegmentID0, err = decodeBase64StringValue(err, parts[2])
ctx.SpanID0 = parts[3]
ctx.ParentService, err = decodeBase64StringValue(err, parts[4])
ctx.ParentServiceInstance, err = decodeBase64StringValue(err, parts[5])
ctx.ParentEndpoint, err = decodeBase64StringValue(err, parts[6])
ctx.AddressUsedAtClient, err = decodeBase64StringValue(err, parts[7])
if err != nil {
return nil, err
}
return ctx, nil
}
func analyzeZipkinTracingContextWithSpecificData(traceID, spanID string) *ZipkinTracingContext {
return &ZipkinTracingContext{TraceID0: traceID, SpanID0: spanID}
}
func analyzeZipkinTracingContextWithSingleData(singleData string) *ZipkinTracingContext {
info := strings.Split(singleData, "-")
if len(info) < 2 {
return nil
}
return &ZipkinTracingContext{TraceID0: info[0], SpanID0: info[1]}
}
func (w *ZipkinTracingContext) TraceID() string {
return w.TraceID0
}
func (w *ZipkinTracingContext) TraceSegmentID() string {
return ""
}
func (w *ZipkinTracingContext) SpanID() string {
return w.SpanID0
}
func (w *ZipkinTracingContext) Provider() *TraceContextProvider {
return &TraceContextProvider{
SpanAttachType: agentv3.SpanAttachedEvent_ZIPKIN,
AccessLogType: accesslogv3.AccessLogTraceInfoProvider_Zipkin,
Name: "zipkin",
}
}
func decodeBase64StringValue(err error, val string) (string, error) {
if err != nil {
return "", err
}
result, err := base64.StdEncoding.DecodeString(val)
if err != nil {
return "", err
}
return string(result), nil
}