1
0
mirror of https://github.com/kubernetes-sigs/descheduler.git synced 2026-01-26 13:29:11 +01:00
Files
descheduler/pkg/tracing/tracing.go
Harsha Narayana add9d6e897 enable Open telemetry support for descheduler
1. Enable OTEL configuration and base framework
2. update generated conversion spec
3. enable docker based conversion and deep copy generate
4. fix broken unit tests
2023-07-18 11:14:21 +05:30

157 lines
4.9 KiB
Go

/*
Copyright 2023 The Kubernetes Authors.
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package tracing
import (
"context"
"crypto/x509"
"os"
"go.opentelemetry.io/otel"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace"
"go.opentelemetry.io/otel/exporters/otlp/otlptrace/otlptracegrpc"
"go.opentelemetry.io/otel/propagation"
sdkresource "go.opentelemetry.io/otel/sdk/resource"
sdktrace "go.opentelemetry.io/otel/sdk/trace"
semconv "go.opentelemetry.io/otel/semconv/v1.12.0"
"go.opentelemetry.io/otel/trace"
"google.golang.org/grpc/credentials"
"k8s.io/klog/v2"
)
const (
// DefaultServiceName is the default service name used for tracing.
DefaultServiceName = "descheduler"
// DescheduleOperation is the operation name used for Deschedule() functions.
DescheduleOperation = "deschedule"
// BalanceOperation is the operation name used for Balance() functions.
BalanceOperation = "balance"
// EvictOperation is the operation name used for Evict() functions.
EvictOperation = "evict"
// TracerName is used to setup the named tracer
TracerName = "sigs.k8s.io/descheduler"
)
var (
tracer trace.Tracer
provider trace.TracerProvider
)
func init() {
provider = trace.NewNoopTracerProvider()
tracer = provider.Tracer(TracerName)
}
func Tracer() trace.Tracer {
return tracer
}
// NewTracerProvider creates a new trace provider with the given options.
func NewTracerProvider(ctx context.Context, endpoint, caCert, name, namespace string, sampleRate float64, fallbackToNoOpTracer bool) (err error) {
defer func(p trace.TracerProvider) {
if err != nil && !fallbackToNoOpTracer {
return
}
if err != nil && fallbackToNoOpTracer {
klog.ErrorS(err, "ran into an error trying to setup a trace provider. Falling back to NoOp provider")
err = nil
provider = trace.NewNoopTracerProvider()
}
otel.SetTextMapPropagator(propagation.TraceContext{})
otel.SetTracerProvider(provider)
otel.SetErrorHandler(otel.ErrorHandlerFunc(func(err error) {
klog.ErrorS(err, "got error from opentelemetry")
}))
tracer = otel.GetTracerProvider().Tracer(TracerName)
}(provider)
if endpoint == "" {
klog.V(2).Info("Did not find a trace collector endpoint defined. Switching to NoopTraceProvider")
provider = trace.NewNoopTracerProvider()
return
}
var opts []otlptracegrpc.Option
opts = append(opts, otlptracegrpc.WithEndpoint(endpoint))
var data []byte
if caCert != "" {
data, err = os.ReadFile(caCert)
if err != nil {
klog.ErrorS(err, "failed to extract ca certificate required to generate the transport credentials")
return err
}
pool := x509.NewCertPool()
if !pool.AppendCertsFromPEM(data) {
klog.Error("failed to create cert pool using the ca certificate provided for generating the transport credentials")
return err
}
klog.Info("Enabling trace GRPC client in secure TLS mode")
opts = append(opts, otlptracegrpc.WithTLSCredentials(credentials.NewClientTLSFromCert(pool, "")))
} else {
klog.Info("Enabling trace GRPC client in insecure mode")
opts = append(opts, otlptracegrpc.WithInsecure())
}
client := otlptracegrpc.NewClient(opts...)
exporter, err := otlptrace.New(ctx, client)
if err != nil {
klog.ErrorS(err, "failed to create an instance of the trace exporter")
return err
}
if name == "" {
klog.V(5).InfoS("no name provided, using default service name for tracing", "name", DefaultServiceName)
name = DefaultServiceName
}
resourceOpts := []sdkresource.Option{sdkresource.WithAttributes(semconv.ServiceNameKey.String(name)), sdkresource.WithSchemaURL(semconv.SchemaURL), sdkresource.WithProcess()}
if namespace != "" {
resourceOpts = append(resourceOpts, sdkresource.WithAttributes(semconv.ServiceNamespaceKey.String(namespace)))
}
resource, err := sdkresource.New(ctx, resourceOpts...)
if err != nil {
klog.ErrorS(err, "failed to create traceable resource")
return err
}
spanProcessor := sdktrace.NewBatchSpanProcessor(exporter)
provider = sdktrace.NewTracerProvider(
sdktrace.WithSampler(sdktrace.ParentBased(sdktrace.TraceIDRatioBased(sampleRate))),
sdktrace.WithSpanProcessor(spanProcessor),
sdktrace.WithResource(resource),
)
klog.V(2).Info("Successfully setup trace provider")
return
}
// Shutdown shuts down the global trace exporter.
func Shutdown(ctx context.Context) error {
tp, ok := provider.(*sdktrace.TracerProvider)
if !ok {
return nil
}
if err := tp.Shutdown(ctx); err != nil {
otel.Handle(err)
klog.ErrorS(err, "failed to shutdown the trace exporter")
return err
}
return nil
}