blob: 5705182f2072b8213dae45dc1494ba2738d2e0d7 [file] [log] [blame]
/*
* 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 tracing
import (
"context"
"errors"
"fmt"
)
import (
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/propagation"
"go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.7.0"
"go.opentelemetry.io/otel/trace"
)
import (
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/logger"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/model"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/tracing/jaeger"
"github.com/apache/dubbo-go-pixiu/pixiu/pkg/tracing/otlp"
)
// Different Listeners listen to different protocol requests, and create the corresponding tracer
type ProtocolName string
const HTTPProtocol ProtocolName = "HTTP"
const ServiceName = "dubbo-go-pixiu"
// Sampling Strategy
const (
ALWAYS = "always"
NEVER = "never"
RATIO = "ratio"
)
// Exporter end
const (
JAEGER = "jaeger"
OTLP = "otlp"
)
// Holder Unique Name by making Id self-incrementing。
type Holder struct {
Tracers map[string]Trace
}
// Tracers corresponding to the listening protocol are maintained by the holder
type TraceDriver struct {
trace.TracerProvider
}
// InitDriver loading BootStrap configuration about trace
func InitDriver(bs *model.Bootstrap) *TraceDriver {
config := bs.Trace
if config == nil {
logger.Info("[dubbo-go-pixiu] no trace configuration in conf.yaml")
return nil
}
ctx := context.Background()
exp, err := newExporter(ctx, config)
if err != nil {
logger.Warnf("[dubbo-go-pixiu] create trace exporter failed: %v", err)
return nil
}
provider := newTraceProvider(exp, config)
otel.SetTracerProvider(provider)
return &TraceDriver{TracerProvider: provider}
}
func newExporter(ctx context.Context, cfg *model.TracerConfig) (sdktrace.SpanExporter, error) {
// You must specify exporter to collect traces, otherwise return nil.
switch cfg.Name {
case OTLP:
return otlp.NewOTLPExporter(ctx, cfg)
case JAEGER:
return jaeger.NewJaegerExporter(cfg)
default:
return nil, errors.New("no exporter error\n")
}
}
func newTraceProvider(exp sdktrace.SpanExporter, cfg *model.TracerConfig) *sdktrace.TracerProvider {
// The service.name attribute is required.
if cfg.ServiceName == "" {
cfg.ServiceName = ServiceName
}
resource := resource.NewWithAttributes(
semconv.SchemaURL,
semconv.ServiceNameKey.String(cfg.ServiceName),
)
//otel.SetTextMapPropagator(propagation.TraceContext{})
otel.SetTextMapPropagator(customJaegerInject{})
return sdktrace.NewTracerProvider(
sdktrace.WithBatcher(exp),
sdktrace.WithResource(resource),
sdktrace.WithSampler(newSampler(cfg.Sampler)),
)
}
type customJaegerInject struct {
propagation.TraceContext
}
func (c customJaegerInject) Inject(ctx context.Context, carrier propagation.TextMapCarrier) {
sc := trace.SpanContextFromContext(ctx)
if !sc.IsValid() {
return
}
// Clear all flags other than the trace-context supported sampling bit.
flags := sc.TraceFlags() & trace.FlagsSampled
h := fmt.Sprintf("%s:%s:%s:%s",
sc.TraceID(),
sc.SpanID(),
sc.SpanID(),
flags)
carrier.Set("uber-trace-id", h)
}
func newSampler(sample model.Sampler) sdktrace.Sampler {
// default sampling: always.
switch sample.Type {
case ALWAYS:
return sdktrace.AlwaysSample()
case NEVER:
return sdktrace.NeverSample()
case RATIO:
return sdktrace.TraceIDRatioBased(sample.Param)
default:
return sdktrace.AlwaysSample()
}
}