@@ -2,14 +2,17 @@ package telemetry
22
33import (
44 "context"
5+ "fmt"
56 "net/url"
67 "os"
78 "strings"
89 "time"
910
1011 "go.opentelemetry.io/otel"
1112 "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploggrpc"
13+ "go.opentelemetry.io/otel/exporters/otlp/otlplog/otlploghttp"
1214 "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
15+ "go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracehttp"
1316 "go.opentelemetry.io/otel/propagation"
1417 sdklog "go.opentelemetry.io/otel/sdk/log"
1518 "go.opentelemetry.io/otel/sdk/resource"
@@ -54,14 +57,14 @@ func Init(ctx context.Context, serviceName string, serviceNamespace string) (shu
5457 loggingEnabled := strings .EqualFold (strings .TrimSpace (os .Getenv ("OTEL_LOGGING_ENABLED" )), "true" )
5558 otelOpts := []adktelemetry.Option {adktelemetry .WithResource (telemetryResource )}
5659 if tracingEnabled {
57- tracerProvider , tpErr := newGRPCTracerProvider (ctx , telemetryResource )
60+ tracerProvider , tpErr := newTracerProvider (ctx , telemetryResource )
5861 if tpErr != nil {
5962 return nil , true , tpErr
6063 }
6164 otelOpts = append (otelOpts , adktelemetry .WithTracerProvider (tracerProvider ))
6265 }
6366 if loggingEnabled {
64- loggerProvider , lpErr := newGRPCLoggerProvider (ctx , telemetryResource )
67+ loggerProvider , lpErr := newLoggerProvider (ctx , telemetryResource )
6568 if lpErr != nil {
6669 return nil , true , lpErr
6770 }
@@ -87,35 +90,66 @@ func isTelemetryEnabled() bool {
8790 strings .EqualFold (strings .TrimSpace (os .Getenv ("OTEL_LOGGING_ENABLED" )), "true" )
8891}
8992
90- func newGRPCTracerProvider (ctx context.Context , res * resource.Resource ) (* sdktrace.TracerProvider , error ) {
91- traceEndpoint := strings .TrimSpace (os .Getenv ("OTEL_EXPORTER_OTLP_TRACES_ENDPOINT" ))
92- if traceEndpoint == "" {
93- traceEndpoint = strings .TrimSpace (os .Getenv ("OTEL_TRACING_EXPORTER_OTLP_ENDPOINT" ))
93+ // resolveOTLPProtocol returns the OTLP protocol for the given signal,
94+ // following OTel spec precedence: signal-specific > general > default (grpc).
95+ func resolveOTLPProtocol (signal string ) string {
96+ if v := strings .TrimSpace (os .Getenv (fmt .Sprintf ("OTEL_EXPORTER_OTLP_%s_PROTOCOL" , signal ))); v != "" {
97+ return strings .ToLower (v )
9498 }
95- if traceEndpoint = = "" {
96- traceEndpoint = strings .TrimSpace ( os . Getenv ( "OTEL_EXPORTER_OTLP_ENDPOINT" ) )
99+ if v := strings . TrimSpace ( os . Getenv ( "OTEL_EXPORTER_OTLP_PROTOCOL" )); v ! = "" {
100+ return strings .ToLower ( v )
97101 }
102+ return "grpc"
103+ }
104+
105+ func resolveEndpoint (signalEnvSuffix string ) string {
106+ endpoint := strings .TrimSpace (os .Getenv (fmt .Sprintf ("OTEL_EXPORTER_OTLP_%s_ENDPOINT" , signalEnvSuffix )))
107+ if endpoint == "" {
108+ endpoint = strings .TrimSpace (os .Getenv (fmt .Sprintf ("OTEL_%s_EXPORTER_OTLP_ENDPOINT" , signalEnvSuffix )))
109+ }
110+ if endpoint == "" {
111+ endpoint = strings .TrimSpace (os .Getenv ("OTEL_EXPORTER_OTLP_ENDPOINT" ))
112+ }
113+ return endpoint
114+ }
98115
99- opts := []otlptracegrpc.Option {
100- // Retry on transient failures
101- otlptracegrpc .WithRetry (otlptracegrpc.RetryConfig {
116+ func newTracerProvider (ctx context.Context , res * resource.Resource ) (* sdktrace.TracerProvider , error ) {
117+ protocol := resolveOTLPProtocol ("TRACES" )
118+ traceEndpoint := resolveEndpoint ("TRACES" )
119+
120+ var exporter sdktrace.SpanExporter
121+ var err error
122+
123+ switch protocol {
124+ case "http/protobuf" :
125+ var opts []otlptracehttp.Option
126+ if traceEndpoint != "" {
127+ opts = append (opts , otlptracehttp .WithEndpointURL (traceEndpoint ))
128+ }
129+ opts = append (opts , otlptracehttp .WithRetry (otlptracehttp.RetryConfig {
102130 Enabled : true ,
103131 InitialInterval : 1 * time .Second ,
104132 MaxInterval : 5 * time .Second ,
105133 MaxElapsedTime : 30 * time .Second ,
106- }),
107- }
108- if traceEndpoint != "" {
109- // If the endpoint has a valid scheme, host, port, path ("scheme://host:port/path"), set endpoint url.
110- if u , err := url .Parse (traceEndpoint ); err == nil && u .Scheme != "" && u .Host != "" {
111- opts = append (opts , otlptracegrpc .WithEndpointURL (u .String ()))
112- } else {
113- // Else, treat it as a regular endpoint ("example.com:4317", no scheme or path)
114- opts = append (opts , otlptracegrpc .WithEndpoint (traceEndpoint ))
134+ }))
135+ exporter , err = otlptracehttp .New (ctx , opts ... )
136+ default :
137+ var opts []otlptracegrpc.Option
138+ opts = append (opts , otlptracegrpc .WithRetry (otlptracegrpc.RetryConfig {
139+ Enabled : true ,
140+ InitialInterval : 1 * time .Second ,
141+ MaxInterval : 5 * time .Second ,
142+ MaxElapsedTime : 30 * time .Second ,
143+ }))
144+ if traceEndpoint != "" {
145+ if u , parseErr := url .Parse (traceEndpoint ); parseErr == nil && u .Scheme != "" && u .Host != "" {
146+ opts = append (opts , otlptracegrpc .WithEndpointURL (u .String ()))
147+ } else {
148+ opts = append (opts , otlptracegrpc .WithEndpoint (traceEndpoint ))
149+ }
115150 }
151+ exporter , err = otlptracegrpc .New (ctx , opts ... )
116152 }
117-
118- exporter , err := otlptracegrpc .New (ctx , opts ... )
119153 if err != nil {
120154 return nil , err
121155 }
@@ -127,25 +161,31 @@ func newGRPCTracerProvider(ctx context.Context, res *resource.Resource) (*sdktra
127161 ), nil
128162}
129163
130- func newGRPCLoggerProvider (ctx context.Context , res * resource.Resource ) (* sdklog.LoggerProvider , error ) {
131- logEndpoint := strings .TrimSpace (os .Getenv ("OTEL_EXPORTER_OTLP_LOGS_ENDPOINT" ))
132- if logEndpoint == "" {
133- logEndpoint = strings .TrimSpace (os .Getenv ("OTEL_LOGGING_EXPORTER_OTLP_ENDPOINT" ))
134- }
135- if logEndpoint == "" {
136- logEndpoint = strings .TrimSpace (os .Getenv ("OTEL_EXPORTER_OTLP_ENDPOINT" ))
137- }
164+ func newLoggerProvider (ctx context.Context , res * resource.Resource ) (* sdklog.LoggerProvider , error ) {
165+ protocol := resolveOTLPProtocol ("LOGS" )
166+ logEndpoint := resolveEndpoint ("LOGS" )
167+
168+ var exporter sdklog.Exporter
169+ var err error
138170
139- var opts []otlploggrpc.Option
140- if logEndpoint != "" {
141- if u , err := url .Parse (logEndpoint ); err == nil && u .Scheme != "" && u .Host != "" {
142- opts = append (opts , otlploggrpc .WithEndpointURL (u .String ()))
143- } else {
144- opts = append (opts , otlploggrpc .WithEndpoint (logEndpoint ))
171+ switch protocol {
172+ case "http/protobuf" :
173+ var opts []otlploghttp.Option
174+ if logEndpoint != "" {
175+ opts = append (opts , otlploghttp .WithEndpointURL (logEndpoint ))
145176 }
177+ exporter , err = otlploghttp .New (ctx , opts ... )
178+ default :
179+ var opts []otlploggrpc.Option
180+ if logEndpoint != "" {
181+ if u , parseErr := url .Parse (logEndpoint ); parseErr == nil && u .Scheme != "" && u .Host != "" {
182+ opts = append (opts , otlploggrpc .WithEndpointURL (u .String ()))
183+ } else {
184+ opts = append (opts , otlploggrpc .WithEndpoint (logEndpoint ))
185+ }
186+ }
187+ exporter , err = otlploggrpc .New (ctx , opts ... )
146188 }
147-
148- exporter , err := otlploggrpc .New (ctx , opts ... )
149189 if err != nil {
150190 return nil , err
151191 }
0 commit comments