github.com/lingyao2333/mo-zero@v1.4.1/core/trace/agent.go (about)

     1  package trace
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"sync"
     7  
     8  	"github.com/lingyao2333/mo-zero/core/lang"
     9  	"github.com/lingyao2333/mo-zero/core/logx"
    10  	"go.opentelemetry.io/otel"
    11  	"go.opentelemetry.io/otel/exporters/jaeger"
    12  	"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
    13  	"go.opentelemetry.io/otel/exporters/zipkin"
    14  	"go.opentelemetry.io/otel/sdk/resource"
    15  	sdktrace "go.opentelemetry.io/otel/sdk/trace"
    16  	semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
    17  	"google.golang.org/grpc"
    18  )
    19  
    20  const (
    21  	kindJaeger = "jaeger"
    22  	kindZipkin = "zipkin"
    23  	kindGrpc   = "grpc"
    24  )
    25  
    26  var (
    27  	agents = make(map[string]lang.PlaceholderType)
    28  	lock   sync.Mutex
    29  	tp     *sdktrace.TracerProvider
    30  )
    31  
    32  // StartAgent starts an opentelemetry agent.
    33  func StartAgent(c Config) {
    34  	lock.Lock()
    35  	defer lock.Unlock()
    36  
    37  	_, ok := agents[c.Endpoint]
    38  	if ok {
    39  		return
    40  	}
    41  
    42  	// if error happens, let later calls run.
    43  	if err := startAgent(c); err != nil {
    44  		return
    45  	}
    46  
    47  	agents[c.Endpoint] = lang.Placeholder
    48  }
    49  
    50  // StopAgent shuts down the span processors in the order they were registered.
    51  func StopAgent() {
    52  	_ = tp.Shutdown(context.Background())
    53  }
    54  
    55  func createExporter(c Config) (sdktrace.SpanExporter, error) {
    56  	// Just support jaeger and zipkin now, more for later
    57  	switch c.Batcher {
    58  	case kindJaeger:
    59  		return jaeger.New(jaeger.WithCollectorEndpoint(jaeger.WithEndpoint(c.Endpoint)))
    60  	case kindZipkin:
    61  		return zipkin.New(c.Endpoint)
    62  	case kindGrpc:
    63  		return otlptracegrpc.NewUnstarted(
    64  			otlptracegrpc.WithInsecure(),
    65  			otlptracegrpc.WithEndpoint(c.Endpoint),
    66  			otlptracegrpc.WithDialOption(grpc.WithBlock()),
    67  		), nil
    68  	default:
    69  		return nil, fmt.Errorf("unknown exporter: %s", c.Batcher)
    70  	}
    71  }
    72  
    73  func startAgent(c Config) error {
    74  	opts := []sdktrace.TracerProviderOption{
    75  		// Set the sampling rate based on the parent span to 100%
    76  		sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(c.Sampler))),
    77  		// Record information about this application in a Resource.
    78  		sdktrace.WithResource(resource.NewSchemaless(semconv.ServiceNameKey.String(c.Name))),
    79  	}
    80  
    81  	if len(c.Endpoint) > 0 {
    82  		exp, err := createExporter(c)
    83  		if err != nil {
    84  			logx.Error(err)
    85  			return err
    86  		}
    87  
    88  		// Always be sure to batch in production.
    89  		opts = append(opts, sdktrace.WithBatcher(exp))
    90  	}
    91  
    92  	tp = sdktrace.NewTracerProvider(opts...)
    93  	otel.SetTracerProvider(tp)
    94  	otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
    95  		logx.Errorf("[otel] error: %v", err)
    96  	}))
    97  
    98  	return nil
    99  }