77 "os"
88 "sync"
99
10- "github.com/zeromicro/go-zero/core/lang"
1110 "github.com/zeromicro/go-zero/core/logx"
1211 "go.opentelemetry.io/otel"
1312 "go.opentelemetry.io/otel/exporters/jaeger"
@@ -30,42 +29,36 @@ const (
3029)
3130
3231var (
33- agents = make (map [string ]lang.PlaceholderType )
34- lock sync.Mutex
35- tp * sdktrace.TracerProvider
32+ once sync.Once
33+ tp * sdktrace.TracerProvider
34+ shutdownOnceFn = sync .OnceFunc (func () {
35+ if tp != nil {
36+ _ = tp .Shutdown (context .Background ())
37+ }
38+ })
3639)
3740
3841// StartAgent starts an opentelemetry agent.
42+ // It uses sync.Once to ensure the agent is initialized only once,
43+ // similar to prometheus.StartAgent and logx.SetUp.
44+ // This prevents multiple ServiceConf.SetUp() calls from reinitializing
45+ // the global tracer provider when running multiple servers (e.g., REST + RPC)
46+ // in the same process.
3947func StartAgent (c Config ) {
4048 if c .Disabled {
4149 return
4250 }
4351
44- lock .Lock ()
45- defer lock .Unlock ()
46-
47- _ , ok := agents [c .Endpoint ]
48- if ok {
49- return
50- }
51-
52- // if error happens, let later calls run.
53- if err := startAgent (c ); err != nil {
54- return
55- }
56-
57- agents [c .Endpoint ] = lang .Placeholder
52+ once .Do (func () {
53+ if err := startAgent (c ); err != nil {
54+ logx .Error (err )
55+ }
56+ })
5857}
5958
6059// StopAgent shuts down the span processors in the order they were registered.
6160func StopAgent () {
62- lock .Lock ()
63- defer lock .Unlock ()
64-
65- if tp != nil {
66- _ = tp .Shutdown (context .Background ())
67- tp = nil
68- }
61+ shutdownOnceFn ()
6962}
7063
7164func createExporter (c Config ) (sdktrace.SpanExporter , error ) {
0 commit comments