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 }