fix: Use standard env variables for opentelemtry (#2194)
Opentelemetry defines standard variables which are supported by multiple observability platforms. [1] https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/sdk-environment-variables.md [2] https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/protocol/exporter.md By defining support for standard env vars, Fission open telemetry support can be leveraged with different platforms such as NewRelic, SigNoz, DataDog etc. Signed-off-by: Sanket Sudake <sanketsudake@gmail.com>
This commit is contained in:
+73
-19
@@ -3,8 +3,11 @@ package otel
|
||||
import (
|
||||
"context"
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"go.opentelemetry.io/otel"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
|
||||
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
|
||||
"go.opentelemetry.io/otel/propagation"
|
||||
"go.opentelemetry.io/otel/sdk/resource"
|
||||
@@ -12,31 +15,58 @@ import (
|
||||
semconv "go.opentelemetry.io/otel/semconv/v1.4.0"
|
||||
"go.uber.org/zap"
|
||||
"google.golang.org/grpc"
|
||||
"google.golang.org/grpc/credentials"
|
||||
apiv1 "k8s.io/api/core/v1"
|
||||
)
|
||||
|
||||
func getSpanProcessor(ctx context.Context, logger *zap.Logger) (*sdktrace.SpanProcessor, error) {
|
||||
collectorEndpoint := os.Getenv("OTEL_COLLECTOR_ENDPOINT")
|
||||
if collectorEndpoint == "" {
|
||||
logger.Info("skipping trace exporter registration")
|
||||
const (
|
||||
OtelEnvPrefix = "OTEL_"
|
||||
OtelEndpointEnvVar = "OTEL_EXPORTER_OTLP_ENDPOINT"
|
||||
OtelInsecureEnvVar = "OTEL_EXPORTER_OTLP_INSECURE"
|
||||
)
|
||||
|
||||
type OtelConfig struct {
|
||||
endpoint string
|
||||
insecure bool
|
||||
}
|
||||
|
||||
func parseOtelConfig() OtelConfig {
|
||||
config := OtelConfig{}
|
||||
config.endpoint = os.Getenv(OtelEndpointEnvVar)
|
||||
insecure, err := strconv.ParseBool(os.Getenv(OtelInsecureEnvVar))
|
||||
if err != nil {
|
||||
insecure = false
|
||||
}
|
||||
config.insecure = insecure
|
||||
return config
|
||||
}
|
||||
|
||||
func getTraceExporter(ctx context.Context, logger *zap.Logger) (*otlptrace.Exporter, error) {
|
||||
otelConfig := parseOtelConfig()
|
||||
if otelConfig.endpoint == "" {
|
||||
logger.Info("OTEL_EXPORTER_OTLP_ENDPOINT not set, skipping Opentelemtry tracing")
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
traceExporter, err := otlptracegrpc.New(ctx,
|
||||
otlptracegrpc.WithInsecure(),
|
||||
otlptracegrpc.WithEndpoint(collectorEndpoint),
|
||||
grpcOpts := []otlptracegrpc.Option{
|
||||
otlptracegrpc.WithEndpoint(otelConfig.endpoint),
|
||||
otlptracegrpc.WithDialOption(grpc.WithBlock()),
|
||||
)
|
||||
}
|
||||
if otelConfig.insecure {
|
||||
grpcOpts = append(grpcOpts, otlptracegrpc.WithInsecure())
|
||||
} else {
|
||||
grpcOpts = append(grpcOpts, otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(nil, "")))
|
||||
}
|
||||
|
||||
exporter, err := otlptracegrpc.New(ctx, grpcOpts...)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
|
||||
return &bsp, nil
|
||||
return exporter, nil
|
||||
}
|
||||
|
||||
// Initializes an OTLP exporter, and configures the corresponding trace and metric providers.
|
||||
func InitProvider(logger *zap.Logger, serviceName string) (func(), error) {
|
||||
ctx := context.Background()
|
||||
func InitProvider(ctx context.Context, logger *zap.Logger, serviceName string) (func(context.Context), error) {
|
||||
res, err := resource.New(ctx,
|
||||
resource.WithAttributes(
|
||||
semconv.ServiceNameKey.String(serviceName),
|
||||
@@ -46,26 +76,50 @@ func InitProvider(logger *zap.Logger, serviceName string) (func(), error) {
|
||||
return nil, err
|
||||
}
|
||||
tracerProvider := sdktrace.NewTracerProvider(
|
||||
sdktrace.WithSampler(sdktrace.AlwaysSample()),
|
||||
sdktrace.WithResource(res),
|
||||
)
|
||||
|
||||
bsp, err := getSpanProcessor(ctx, logger)
|
||||
traceExporter, err := getTraceExporter(ctx, logger)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if bsp != nil {
|
||||
tracerProvider.RegisterSpanProcessor(*bsp)
|
||||
|
||||
if traceExporter != nil {
|
||||
bsp := sdktrace.NewBatchSpanProcessor(traceExporter)
|
||||
tracerProvider.RegisterSpanProcessor(bsp)
|
||||
}
|
||||
|
||||
otel.SetTracerProvider(tracerProvider)
|
||||
otel.SetTextMapPropagator(propagation.TraceContext{})
|
||||
otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(
|
||||
propagation.TraceContext{}, propagation.Baggage{}))
|
||||
|
||||
// Shutdown will flush any remaining spans and shut down the exporter.
|
||||
return func() {
|
||||
return func(ctx context.Context) {
|
||||
err := tracerProvider.Shutdown(ctx)
|
||||
if err != nil {
|
||||
logger.Fatal("error shutting down trace provider", zap.Error(err))
|
||||
}
|
||||
if traceExporter != nil {
|
||||
if err = traceExporter.Shutdown(ctx); err != nil {
|
||||
logger.Fatal("error shutting down trace exporter", zap.Error(err))
|
||||
}
|
||||
}
|
||||
}, nil
|
||||
}
|
||||
|
||||
// OtelEnvForContainer returns a list of environment variables
|
||||
// for the container, which start with prefix OTEL_
|
||||
func OtelEnvForContainer() []apiv1.EnvVar {
|
||||
otelEnvs := []apiv1.EnvVar{}
|
||||
for _, e := range os.Environ() {
|
||||
if strings.HasPrefix(e, OtelEnvPrefix) {
|
||||
pair := strings.SplitN(e, "=", 2)
|
||||
otelEnvs = append(otelEnvs, apiv1.EnvVar{
|
||||
Name: pair[0],
|
||||
Value: pair[1],
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
return otelEnvs
|
||||
}
|
||||
|
||||
@@ -11,7 +11,11 @@ import (
|
||||
)
|
||||
|
||||
func TracingEnabled(logger *zap.Logger) bool {
|
||||
openTracingEnabled, err := strconv.ParseBool(os.Getenv("OPENTRACING_ENABLED"))
|
||||
tracingEnabled := os.Getenv("TRACING_ENABLED")
|
||||
if len(tracingEnabled) == 0 {
|
||||
return false
|
||||
}
|
||||
openTracingEnabled, err := strconv.ParseBool(tracingEnabled)
|
||||
if err != nil {
|
||||
if logger != nil {
|
||||
logger.Error("Error parsing OpenTracing enabled flag", zap.Error(err))
|
||||
|
||||
Reference in New Issue
Block a user