diff --git a/operator/controllers/lifecycle/interfaces/fake/tracer_mock.go b/operator/controllers/common/fake/tracer_mock.go similarity index 91% rename from operator/controllers/lifecycle/interfaces/fake/tracer_mock.go rename to operator/controllers/common/fake/tracer_mock.go index 5934e8ba0b..cecca3b3de 100644 --- a/operator/controllers/lifecycle/interfaces/fake/tracer_mock.go +++ b/operator/controllers/common/fake/tracer_mock.go @@ -9,18 +9,18 @@ import ( "sync" ) -// ITracerMock is a mock implementation of common.ITracer. +// ITracerMock is a mock implementation of interfaces.ITracer. // // func TestSomethingThatUsesITracer(t *testing.T) { // -// // make and configure a mocked common.ITracer +// // make and configure a mocked interfaces.ITracer // mockedITracer := &ITracerMock{ // StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { // panic("mock out the Start method") // }, // } // -// // use mockedITracer in code that requires common.ITracer +// // use mockedITracer in code that requires interfaces.ITracer // // and then make assertions. // // } diff --git a/operator/controllers/common/fake/tracerfactory_mock.go b/operator/controllers/common/fake/tracerfactory_mock.go new file mode 100644 index 0000000000..c84c5982ef --- /dev/null +++ b/operator/controllers/common/fake/tracerfactory_mock.go @@ -0,0 +1,71 @@ +// Code generated by moq; DO NOT EDIT. +// github.com/matryer/moq + +package fake + +import ( + "go.opentelemetry.io/otel/trace" + "sync" +) + +// TracerFactoryMock is a mock implementation of interfaces.TracerFactory. +// +// func TestSomethingThatUsesTracerFactory(t *testing.T) { +// +// // make and configure a mocked interfaces.TracerFactory +// mockedTracerFactory := &TracerFactoryMock{ +// GetTracerFunc: func(name string) trace.Tracer { +// panic("mock out the GetTracer method") +// }, +// } +// +// // use mockedTracerFactory in code that requires interfaces.TracerFactory +// // and then make assertions. +// +// } +type TracerFactoryMock struct { + // GetTracerFunc mocks the GetTracer method. + GetTracerFunc func(name string) trace.Tracer + + // calls tracks calls to the methods. + calls struct { + // GetTracer holds details about calls to the GetTracer method. + GetTracer []struct { + // Name is the name argument value. + Name string + } + } + lockGetTracer sync.RWMutex +} + +// GetTracer calls GetTracerFunc. +func (mock *TracerFactoryMock) GetTracer(name string) trace.Tracer { + if mock.GetTracerFunc == nil { + panic("TracerFactoryMock.GetTracerFunc: method is nil but TracerFactory.GetTracer was just called") + } + callInfo := struct { + Name string + }{ + Name: name, + } + mock.lockGetTracer.Lock() + mock.calls.GetTracer = append(mock.calls.GetTracer, callInfo) + mock.lockGetTracer.Unlock() + return mock.GetTracerFunc(name) +} + +// GetTracerCalls gets all the calls that were made to GetTracer. +// Check the length with: +// +// len(mockedTracerFactory.GetTracerCalls()) +func (mock *TracerFactoryMock) GetTracerCalls() []struct { + Name string +} { + var calls []struct { + Name string + } + mock.lockGetTracer.RLock() + calls = mock.calls.GetTracer + mock.lockGetTracer.RUnlock() + return calls +} diff --git a/operator/controllers/common/otel_utils.go b/operator/controllers/common/otel_utils.go index 5ea69eadcb..8585a11f29 100644 --- a/operator/controllers/common/otel_utils.go +++ b/operator/controllers/common/otel_utils.go @@ -38,6 +38,9 @@ var ( type otelConfig struct { TracerProvider *trace.TracerProvider OtelExporter *trace.SpanExporter + + mtx sync.RWMutex + tracers map[string]ITracer } // do not export this type to make it accessible only via the GetInstance method (i.e Singleton) @@ -46,7 +49,9 @@ var otelInstance *otelConfig func GetOtelInstance() *otelConfig { // initialize once otelInitOnce.Do(func() { - otelInstance = &otelConfig{} + otelInstance = &otelConfig{ + tracers: map[string]ITracer{}, + } }) return otelInstance @@ -62,6 +67,7 @@ func (o *otelConfig) InitOtelCollector(otelCollectorUrl string) error { otel.SetTracerProvider(o.TracerProvider) otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) o.OtelExporter = &otelExporter + o.cleanTracers() logger.Info("Successfully initialized OTel collector") return nil } @@ -72,6 +78,21 @@ func (o *otelConfig) ShutDown() { } } +func (o *otelConfig) GetTracer(name string) ITracer { + o.mtx.Lock() + defer o.mtx.Unlock() + if o.tracers[name] == nil { + o.tracers[name] = otel.Tracer(name) + } + return o.tracers[name] +} + +func (o *otelConfig) cleanTracers() { + o.mtx.Lock() + defer o.mtx.Unlock() + o.tracers = map[string]ITracer{} +} + func GetOTelTracerProviderOptions(oTelCollectorUrl string) ([]trace.TracerProviderOption, trace.SpanExporter, error) { var tracerProviderOptions []trace.TracerProviderOption var otelExporter trace.SpanExporter diff --git a/operator/controllers/common/otel_utils_test.go b/operator/controllers/common/otel_utils_test.go index 2e953bccbd..e6e99362b8 100644 --- a/operator/controllers/common/otel_utils_test.go +++ b/operator/controllers/common/otel_utils_test.go @@ -229,3 +229,14 @@ func TestSetUpKeptnTaskMeters_ErrorCase(t *testing.T) { require.Nil(t, got.EvaluationCount) require.Nil(t, got.EvaluationDuration) } + +func Test_otelConfig_GetTracer(t *testing.T) { + otelConfig := GetOtelInstance() + + tracer := otelConfig.GetTracer("new-tracer") + require.NotNil(t, tracer) + + otelConfig.cleanTracers() + + require.Empty(t, otelConfig.tracers) +} diff --git a/operator/controllers/common/tracer.go b/operator/controllers/common/tracer.go new file mode 100644 index 0000000000..4fda3a5a96 --- /dev/null +++ b/operator/controllers/common/tracer.go @@ -0,0 +1,11 @@ +package common + +import "go.opentelemetry.io/otel/trace" + +//go:generate moq -pkg fake -skip-ensure -out ./fake/tracer_mock.go . ITracer +type ITracer = trace.Tracer + +//go:generate moq -pkg fake -skip-ensure -out ./fake/tracerfactory_mock.go . TracerFactory +type TracerFactory interface { + GetTracer(name string) ITracer +} diff --git a/operator/controllers/lifecycle/interfaces/tracer.go b/operator/controllers/lifecycle/interfaces/tracer.go deleted file mode 100644 index bd88b808ff..0000000000 --- a/operator/controllers/lifecycle/interfaces/tracer.go +++ /dev/null @@ -1,6 +0,0 @@ -package interfaces - -import "go.opentelemetry.io/otel/trace" - -//go:generate moq -pkg fake -skip-ensure -out ./fake/tracer_mock.go . ITracer -type ITracer = trace.Tracer diff --git a/operator/controllers/lifecycle/keptnapp/controller.go b/operator/controllers/lifecycle/keptnapp/controller.go index b058a4d3ab..4141953f58 100644 --- a/operator/controllers/lifecycle/keptnapp/controller.go +++ b/operator/controllers/lifecycle/keptnapp/controller.go @@ -26,7 +26,6 @@ import ( "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" controllererrors "github.com/keptn/lifecycle-toolkit/operator/controllers/errors" - "github.com/keptn/lifecycle-toolkit/operator/controllers/lifecycle/interfaces" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" @@ -43,14 +42,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) -// KeptnAppReconciler reconciles a KeptnApp object +const traceComponentName = "keptn/operator/app" +// KeptnAppReconciler reconciles a KeptnApp object type KeptnAppReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Log logr.Logger - Tracer interfaces.ITracer + Scheme *runtime.Scheme + Recorder record.EventRecorder + Log logr.Logger + TracerFactory controllercommon.TracerFactory } //+kubebuilder:rbac:groups=lifecycle.keptn.sh,resources=keptnapps,verbs=get;list;watch;create;update;patch;delete @@ -84,7 +84,7 @@ func (r *KeptnAppReconciler) Reconcile(ctx context.Context, req ctrl.Request) (c traceContextCarrier := propagation.MapCarrier(app.Annotations) ctx = otel.GetTextMapPropagator().Extract(ctx, traceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_app", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_app", trace.WithSpanKind(trace.SpanKindConsumer)) defer span.End() app.SetSpanAttributes(span) @@ -138,10 +138,10 @@ func (r *KeptnAppReconciler) SetupWithManager(mgr ctrl.Manager) error { } func (r *KeptnAppReconciler) createAppVersion(ctx context.Context, app *klcv1alpha2.KeptnApp) (*klcv1alpha2.KeptnAppVersion, error) { - ctx, span := r.Tracer.Start(ctx, "create_app_version", trace.WithSpanKind(trace.SpanKindProducer)) + ctx, span := r.getTracer().Start(ctx, "create_app_version", trace.WithSpanKind(trace.SpanKindProducer)) defer span.End() - ctxAppTrace, spanAppTrace := r.Tracer.Start(ctx, app.GetAppVersionName(), trace.WithNewRoot(), trace.WithSpanKind(trace.SpanKindServer)) + ctxAppTrace, spanAppTrace := r.getTracer().Start(ctx, app.GetAppVersionName(), trace.WithNewRoot(), trace.WithSpanKind(trace.SpanKindServer)) defer spanAppTrace.End() app.SetSpanAttributes(span) @@ -201,3 +201,7 @@ func (r *KeptnAppReconciler) deprecateAppVersions(ctx context.Context, app *klcv } return lastResultErr } + +func (r *KeptnAppReconciler) getTracer() controllercommon.ITracer { + return r.TracerFactory.GetTracer(traceComponentName) +} diff --git a/operator/controllers/lifecycle/keptnapp/controller_test.go b/operator/controllers/lifecycle/keptnapp/controller_test.go index 54c67c03cb..cd14e9ab97 100644 --- a/operator/controllers/lifecycle/keptnapp/controller_test.go +++ b/operator/controllers/lifecycle/keptnapp/controller_test.go @@ -10,7 +10,6 @@ import ( apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" "github.com/keptn/lifecycle-toolkit/operator/controllers/common/fake" - interfacesfake "github.com/keptn/lifecycle-toolkit/operator/controllers/lifecycle/interfaces/fake" "github.com/magiconair/properties/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace" @@ -165,7 +164,7 @@ func TestKeptnAppReconciler_deprecateAppVersions(t *testing.T) { assert.Matches(t, event, `Normal CreateAppVersionAppVersionDeprecated Create AppVersion: deprecated KeptnAppVersions for KeptnAppVersion: myapp-1.0.0-2 / Namespace: default, Name: myapp, Version: 1.0.0`) } -func setupReconciler() (*KeptnAppReconciler, chan string, *interfacesfake.ITracerMock) { +func setupReconciler() (*KeptnAppReconciler, chan string, *fake.ITracerMock) { //setup logger opts := zap.Options{ Development: true, @@ -173,19 +172,23 @@ func setupReconciler() (*KeptnAppReconciler, chan string, *interfacesfake.ITrace ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) //fake a tracer - tr := &interfacesfake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + tr := &fake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return ctx, trace.SpanFromContext(ctx) }} + tf := &fake.TracerFactoryMock{GetTracerFunc: func(name string) trace.Tracer { + return tr + }} + fakeClient := fake.NewClient() recorder := record.NewFakeRecorder(100) r := &KeptnAppReconciler{ - Client: fakeClient, - Scheme: scheme.Scheme, - Recorder: recorder, - Log: ctrl.Log.WithName("test-appController"), - Tracer: tr, + Client: fakeClient, + Scheme: scheme.Scheme, + Recorder: recorder, + Log: ctrl.Log.WithName("test-appController"), + TracerFactory: tf, } return r, recorder.Events, tr } diff --git a/operator/controllers/lifecycle/keptnappversion/controller.go b/operator/controllers/lifecycle/keptnappversion/controller.go index f2b689b924..d2097e9416 100644 --- a/operator/controllers/lifecycle/keptnappversion/controller.go +++ b/operator/controllers/lifecycle/keptnappversion/controller.go @@ -26,7 +26,6 @@ import ( apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" controllererrors "github.com/keptn/lifecycle-toolkit/operator/controllers/errors" - "github.com/keptn/lifecycle-toolkit/operator/controllers/lifecycle/interfaces" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" "go.opentelemetry.io/otel/propagation" @@ -41,15 +40,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) +const traceComponentName = "keptn/operator/appversion" + // KeptnAppVersionReconciler reconciles a KeptnAppVersion object type KeptnAppVersionReconciler struct { Scheme *runtime.Scheme client.Client - Log logr.Logger - Recorder record.EventRecorder - Tracer interfaces.ITracer - Meters apicommon.KeptnMeters - SpanHandler controllercommon.ISpanHandler + Log logr.Logger + Recorder record.EventRecorder + TracerFactory controllercommon.TracerFactory + Meters apicommon.KeptnMeters + SpanHandler controllercommon.ISpanHandler } //+kubebuilder:rbac:groups=lifecycle.keptn.sh,resources=keptnappversions,verbs=get;list;watch;create;update;patch;delete @@ -94,7 +95,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ SpanHandler: r.SpanHandler, } - ctxAppTrace, spanAppTrace, err := r.SpanHandler.GetSpan(ctxAppTrace, r.Tracer, appVersion, "") + ctxAppTrace, spanAppTrace, err := r.SpanHandler.GetSpan(ctxAppTrace, r.getTracer(), appVersion, "") if err != nil { r.Log.Error(err, "could not get span") } @@ -109,7 +110,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ reconcilePreDep := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostDeployment(ctx, phaseCtx, appVersion, apicommon.PreDeploymentCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.Tracer, appVersion, phase, span, reconcilePreDep) + result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.getTracer(), appVersion, phase, span, reconcilePreDep) if !result.Continue { return result.Result, err } @@ -120,7 +121,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ reconcilePreEval := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostEvaluation(ctx, phaseCtx, appVersion, apicommon.PreDeploymentEvaluationCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.Tracer, appVersion, phase, span, reconcilePreEval) + result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.getTracer(), appVersion, phase, span, reconcilePreEval) if !result.Continue { return result.Result, err } @@ -131,7 +132,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ reconcileAppDep := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcileWorkloads(ctx, appVersion) } - result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.Tracer, appVersion, phase, span, reconcileAppDep) + result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.getTracer(), appVersion, phase, span, reconcileAppDep) if !result.Continue { return result.Result, err } @@ -142,7 +143,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ reconcilePostDep := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostDeployment(ctx, phaseCtx, appVersion, apicommon.PostDeploymentCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.Tracer, appVersion, phase, span, reconcilePostDep) + result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.getTracer(), appVersion, phase, span, reconcilePostDep) if !result.Continue { return result.Result, err } @@ -153,7 +154,7 @@ func (r *KeptnAppVersionReconciler) Reconcile(ctx context.Context, req ctrl.Requ reconcilePostEval := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostEvaluation(ctx, phaseCtx, appVersion, apicommon.PostDeploymentEvaluationCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.Tracer, appVersion, phase, span, reconcilePostEval) + result, err := phaseHandler.HandlePhase(ctx, ctxAppTrace, r.getTracer(), appVersion, phase, span, reconcilePostEval) if !result.Continue { return result.Result, err } @@ -208,7 +209,7 @@ func (r *KeptnAppVersionReconciler) setupSpansContexts(ctx context.Context, appV appTraceContextCarrier := propagation.MapCarrier(appVersion.Spec.TraceId) ctxAppTrace := otel.GetTextMapPropagator().Extract(context.TODO(), appTraceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_app_version", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_app_version", trace.WithSpanKind(trace.SpanKindConsumer)) endFunc := func() { if appVersion.IsEndTimeSet() { @@ -229,3 +230,7 @@ func (r *KeptnAppVersionReconciler) SetupWithManager(mgr ctrl.Manager) error { For(&klcv1alpha2.KeptnAppVersion{}, builder.WithPredicates(predicate.GenerationChangedPredicate{})). Complete(r) } + +func (r *KeptnAppVersionReconciler) getTracer() trace.Tracer { + return r.TracerFactory.GetTracer(traceComponentName) +} diff --git a/operator/controllers/lifecycle/keptnappversion/controller_test.go b/operator/controllers/lifecycle/keptnappversion/controller_test.go index 4782e2ffbc..444570d9dc 100644 --- a/operator/controllers/lifecycle/keptnappversion/controller_test.go +++ b/operator/controllers/lifecycle/keptnappversion/controller_test.go @@ -11,7 +11,6 @@ import ( apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" "github.com/keptn/lifecycle-toolkit/operator/controllers/common/fake" - interfacesfake "github.com/keptn/lifecycle-toolkit/operator/controllers/lifecycle/interfaces/fake" "github.com/magiconair/properties/assert" "github.com/stretchr/testify/require" "go.opentelemetry.io/otel/trace" @@ -145,19 +144,23 @@ func setupReconcilerWithMeters() *KeptnAppVersionReconciler { ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) //fake a tracer - tr := &interfacesfake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + tr := &fake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return ctx, trace.SpanFromContext(ctx) }} + tf := &fake.TracerFactoryMock{GetTracerFunc: func(name string) trace.Tracer { + return tr + }} + r := &KeptnAppVersionReconciler{ - Log: ctrl.Log.WithName("test-appVersionController"), - Tracer: tr, - Meters: controllercommon.InitAppMeters(), + Log: ctrl.Log.WithName("test-appVersionController"), + TracerFactory: tf, + Meters: controllercommon.InitAppMeters(), } return r } -func setupReconciler() (*KeptnAppVersionReconciler, chan string, *interfacesfake.ITracerMock, *fake.ISpanHandlerMock) { +func setupReconciler() (*KeptnAppVersionReconciler, chan string, *fake.ITracerMock, *fake.ISpanHandlerMock) { //setup logger opts := zap.Options{ Development: true, @@ -165,10 +168,14 @@ func setupReconciler() (*KeptnAppVersionReconciler, chan string, *interfacesfake ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) //fake a tracer - tr := &interfacesfake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + tr := &fake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return ctx, trace.SpanFromContext(ctx) }} + tf := &fake.TracerFactoryMock{GetTracerFunc: func(name string) trace.Tracer { + return tr + }} + //fake span handler spanRecorder := &fake.ISpanHandlerMock{ @@ -182,13 +189,13 @@ func setupReconciler() (*KeptnAppVersionReconciler, chan string, *interfacesfake recorder := record.NewFakeRecorder(100) r := &KeptnAppVersionReconciler{ - Client: fakeClient, - Scheme: scheme.Scheme, - Recorder: recorder, - Log: ctrl.Log.WithName("test-appVersionController"), - Tracer: tr, - SpanHandler: spanRecorder, - Meters: controllercommon.InitAppMeters(), + Client: fakeClient, + Scheme: scheme.Scheme, + Recorder: recorder, + Log: ctrl.Log.WithName("test-appVersionController"), + TracerFactory: tf, + SpanHandler: spanRecorder, + Meters: controllercommon.InitAppMeters(), } return r, recorder.Events, tr, spanRecorder } diff --git a/operator/controllers/lifecycle/keptnappversion/reconcile_prepostdeployment.go b/operator/controllers/lifecycle/keptnappversion/reconcile_prepostdeployment.go index 8cfd945542..1f969cf9f5 100644 --- a/operator/controllers/lifecycle/keptnappversion/reconcile_prepostdeployment.go +++ b/operator/controllers/lifecycle/keptnappversion/reconcile_prepostdeployment.go @@ -15,7 +15,7 @@ func (r *KeptnAppVersionReconciler) reconcilePrePostDeployment(ctx context.Conte Client: r.Client, Recorder: r.Recorder, Log: r.Log, - Tracer: r.Tracer, + Tracer: r.getTracer(), Scheme: r.Scheme, SpanHandler: r.SpanHandler, } diff --git a/operator/controllers/lifecycle/keptnappversion/reconcile_prepostevaluation.go b/operator/controllers/lifecycle/keptnappversion/reconcile_prepostevaluation.go index af53487491..f021db2a28 100644 --- a/operator/controllers/lifecycle/keptnappversion/reconcile_prepostevaluation.go +++ b/operator/controllers/lifecycle/keptnappversion/reconcile_prepostevaluation.go @@ -15,7 +15,7 @@ func (r *KeptnAppVersionReconciler) reconcilePrePostEvaluation(ctx context.Conte Client: r.Client, Recorder: r.Recorder, Log: r.Log, - Tracer: r.Tracer, + Tracer: r.getTracer(), Scheme: r.Scheme, SpanHandler: r.SpanHandler, } diff --git a/operator/controllers/lifecycle/keptnevaluation/controller.go b/operator/controllers/lifecycle/keptnevaluation/controller.go index 33aa73067d..f6da2adbc7 100644 --- a/operator/controllers/lifecycle/keptnevaluation/controller.go +++ b/operator/controllers/lifecycle/keptnevaluation/controller.go @@ -40,15 +40,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const traceComponentName = "keptn/operator/evaluation" + // KeptnEvaluationReconciler reconciles a KeptnEvaluation object type KeptnEvaluationReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Log logr.Logger - Meters apicommon.KeptnMeters - Tracer trace.Tracer - Namespace string + Scheme *runtime.Scheme + Recorder record.EventRecorder + Log logr.Logger + Meters apicommon.KeptnMeters + TracerFactory controllercommon.TracerFactory + Namespace string } //clusterrole @@ -140,7 +142,7 @@ func (r *KeptnEvaluationReconciler) Reconcile(ctx context.Context, req ctrl.Requ func (r *KeptnEvaluationReconciler) setupEvaluationSpans(ctx context.Context, evaluation *klcv1alpha2.KeptnEvaluation) (context.Context, trace.Span) { traceContextCarrier := propagation.MapCarrier(evaluation.Annotations) ctx = otel.GetTextMapPropagator().Extract(ctx, traceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_evaluation", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_evaluation", trace.WithSpanKind(trace.SpanKindConsumer)) evaluation.SetSpanAttributes(span) evaluation.SetStartTime() @@ -281,3 +283,7 @@ func (r *KeptnEvaluationReconciler) fetchDefinitionAndProvider(ctx context.Conte } return evaluationDefinition, evaluationProvider, nil } + +func (r *KeptnEvaluationReconciler) getTracer() controllercommon.ITracer { + return r.TracerFactory.GetTracer(traceComponentName) +} diff --git a/operator/controllers/lifecycle/keptntask/controller.go b/operator/controllers/lifecycle/keptntask/controller.go index f870744e7f..f369d1cd6f 100644 --- a/operator/controllers/lifecycle/keptntask/controller.go +++ b/operator/controllers/lifecycle/keptntask/controller.go @@ -24,6 +24,7 @@ import ( "github.com/go-logr/logr" klcv1alpha2 "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2" apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" + controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" controllererrors "github.com/keptn/lifecycle-toolkit/operator/controllers/errors" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/codes" @@ -39,14 +40,16 @@ import ( "sigs.k8s.io/controller-runtime/pkg/predicate" ) +const traceComponentName = "keptn/operator/task" + // KeptnTaskReconciler reconciles a KeptnTask object type KeptnTaskReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Log logr.Logger - Meters apicommon.KeptnMeters - Tracer trace.Tracer + Scheme *runtime.Scheme + Recorder record.EventRecorder + Log logr.Logger + Meters apicommon.KeptnMeters + TracerFactory controllercommon.TracerFactory } //+kubebuilder:rbac:groups=lifecycle.keptn.sh,resources=keptntasks,verbs=get;list;watch;create;update;patch;delete @@ -73,7 +76,7 @@ func (r *KeptnTaskReconciler) Reconcile(ctx context.Context, req ctrl.Request) ( traceContextCarrier := propagation.MapCarrier(task.Annotations) ctx = otel.GetTextMapPropagator().Extract(ctx, traceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_task", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_task", trace.WithSpanKind(trace.SpanKindConsumer)) defer span.End() task.SetSpanAttributes(span) @@ -164,3 +167,7 @@ func (r *KeptnTaskReconciler) JobExists(ctx context.Context, task klcv1alpha2.Ke return false, nil } + +func (r *KeptnTaskReconciler) getTracer() controllercommon.ITracer { + return r.TracerFactory.GetTracer(traceComponentName) +} diff --git a/operator/controllers/lifecycle/keptnworkload/controller.go b/operator/controllers/lifecycle/keptnworkload/controller.go index ef343fa580..f25a938bf1 100644 --- a/operator/controllers/lifecycle/keptnworkload/controller.go +++ b/operator/controllers/lifecycle/keptnworkload/controller.go @@ -41,13 +41,15 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) +const traceComponentName = "keptn/operator/workload" + // KeptnWorkloadReconciler reconciles a KeptnWorkload object type KeptnWorkloadReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Log logr.Logger - Tracer trace.Tracer + Scheme *runtime.Scheme + Recorder record.EventRecorder + Log logr.Logger + TracerFactory controllercommon.TracerFactory } //+kubebuilder:rbac:groups=lifecycle.keptn.sh,resources=keptnworkloads,verbs=get;list;watch;create;update;patch;delete @@ -81,7 +83,7 @@ func (r *KeptnWorkloadReconciler) Reconcile(ctx context.Context, req ctrl.Reques traceContextCarrier := propagation.MapCarrier(workload.Annotations) ctx = otel.GetTextMapPropagator().Extract(ctx, traceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_workload", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_workload", trace.WithSpanKind(trace.SpanKindConsumer)) defer span.End() workload.SetSpanAttributes(span) @@ -131,7 +133,7 @@ func (r *KeptnWorkloadReconciler) SetupWithManager(mgr ctrl.Manager) error { } func (r *KeptnWorkloadReconciler) createWorkloadInstance(ctx context.Context, workload *klcv1alpha2.KeptnWorkload) (*klcv1alpha2.KeptnWorkloadInstance, error) { - ctx, span := r.Tracer.Start(ctx, "create_workload_instance", trace.WithSpanKind(trace.SpanKindProducer)) + ctx, span := r.getTracer().Start(ctx, "create_workload_instance", trace.WithSpanKind(trace.SpanKindProducer)) defer span.End() workload.SetSpanAttributes(span) @@ -154,3 +156,7 @@ func (r *KeptnWorkloadReconciler) createWorkloadInstance(ctx context.Context, wo return &workloadInstance, err } + +func (r *KeptnWorkloadReconciler) getTracer() controllercommon.ITracer { + return r.TracerFactory.GetTracer(traceComponentName) +} diff --git a/operator/controllers/lifecycle/keptnworkloadinstance/controller.go b/operator/controllers/lifecycle/keptnworkloadinstance/controller.go index 817fa644dd..0e709bf35a 100644 --- a/operator/controllers/lifecycle/keptnworkloadinstance/controller.go +++ b/operator/controllers/lifecycle/keptnworkloadinstance/controller.go @@ -41,15 +41,17 @@ import ( "sigs.k8s.io/controller-runtime/pkg/reconcile" ) +const traceComponentName = "keptn/operator/workloadinstance" + // KeptnWorkloadInstanceReconciler reconciles a KeptnWorkloadInstance object type KeptnWorkloadInstanceReconciler struct { client.Client - Scheme *runtime.Scheme - Recorder record.EventRecorder - Log logr.Logger - Meters apicommon.KeptnMeters - Tracer trace.Tracer - SpanHandler *controllercommon.SpanHandler + Scheme *runtime.Scheme + Recorder record.EventRecorder + Log logr.Logger + Meters apicommon.KeptnMeters + SpanHandler *controllercommon.SpanHandler + TracerFactory controllercommon.TracerFactory } //+kubebuilder:rbac:groups=lifecycle.keptn.sh,resources=keptnworkloadinstances,verbs=get;list;watch;create;update;patch;delete @@ -104,7 +106,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr } // this will be the parent span for all phases of the WorkloadInstance - ctxWorkloadTrace, spanWorkloadTrace, err := r.SpanHandler.GetSpan(ctxAppTrace, r.Tracer, workloadInstance, "") + ctxWorkloadTrace, spanWorkloadTrace, err := r.SpanHandler.GetSpan(ctxAppTrace, r.getTracer(), workloadInstance, "") if err != nil { r.Log.Error(err, "could not get span") } @@ -118,7 +120,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr reconcilePre := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostDeployment(ctx, phaseCtx, workloadInstance, apicommon.PreDeploymentCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.Tracer, workloadInstance, phase, span, reconcilePre) + result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.getTracer(), workloadInstance, phase, span, reconcilePre) if !result.Continue { return result.Result, err } @@ -130,7 +132,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr reconcilePreEval := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostEvaluation(ctx, phaseCtx, workloadInstance, apicommon.PreDeploymentEvaluationCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.Tracer, workloadInstance, phase, span, reconcilePreEval) + result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.getTracer(), workloadInstance, phase, span, reconcilePreEval) if !result.Continue { return result.Result, err } @@ -142,7 +144,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr reconcileWorkloadInstance := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcileDeployment(ctx, workloadInstance) } - result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.Tracer, workloadInstance, phase, span, reconcileWorkloadInstance) + result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.getTracer(), workloadInstance, phase, span, reconcileWorkloadInstance) if !result.Continue { return result.Result, err } @@ -154,7 +156,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr reconcilePostDeployment := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostDeployment(ctx, phaseCtx, workloadInstance, apicommon.PostDeploymentCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.Tracer, workloadInstance, phase, span, reconcilePostDeployment) + result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.getTracer(), workloadInstance, phase, span, reconcilePostDeployment) if !result.Continue { return result.Result, err } @@ -166,7 +168,7 @@ func (r *KeptnWorkloadInstanceReconciler) Reconcile(ctx context.Context, req ctr reconcilePostEval := func(phaseCtx context.Context) (apicommon.KeptnState, error) { return r.reconcilePrePostEvaluation(ctx, phaseCtx, workloadInstance, apicommon.PostDeploymentEvaluationCheckType) } - result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.Tracer, workloadInstance, phase, span, reconcilePostEval) + result, err := phaseHandler.HandlePhase(ctx, ctxWorkloadTrace, r.getTracer(), workloadInstance, phase, span, reconcilePostEval) if !result.Continue { return result.Result, err } @@ -228,7 +230,7 @@ func (r *KeptnWorkloadInstanceReconciler) setupSpansContexts(ctx context.Context traceContextCarrier := propagation.MapCarrier(workloadInstance.Annotations) ctx = otel.GetTextMapPropagator().Extract(ctx, traceContextCarrier) - ctx, span := r.Tracer.Start(ctx, "reconcile_workload_instance", trace.WithSpanKind(trace.SpanKindConsumer)) + ctx, span := r.getTracer().Start(ctx, "reconcile_workload_instance", trace.WithSpanKind(trace.SpanKindConsumer)) endFunc := func(span trace.Span, workloadInstance *klcv1alpha2.KeptnWorkloadInstance) { if workloadInstance.IsEndTimeSet() { @@ -309,6 +311,10 @@ func (r *KeptnWorkloadInstanceReconciler) getAppVersionForWorkloadInstance(ctx c return true, latestVersion, nil } +func (r *KeptnWorkloadInstanceReconciler) getTracer() controllercommon.ITracer { + return r.TracerFactory.GetTracer(traceComponentName) +} + func getLatestAppVersion(apps *klcv1alpha2.KeptnAppVersionList, wli *klcv1alpha2.KeptnWorkloadInstance) (bool, klcv1alpha2.KeptnAppVersion, error) { latestVersion := klcv1alpha2.KeptnAppVersion{} // ignore the potential error since this can not return an error with 0.0.0 diff --git a/operator/controllers/lifecycle/keptnworkloadinstance/controller_test.go b/operator/controllers/lifecycle/keptnworkloadinstance/controller_test.go index 10f5c77259..edd1f02fb7 100644 --- a/operator/controllers/lifecycle/keptnworkloadinstance/controller_test.go +++ b/operator/controllers/lifecycle/keptnworkloadinstance/controller_test.go @@ -11,7 +11,6 @@ import ( controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" "github.com/keptn/lifecycle-toolkit/operator/controllers/common/fake" controllererrors "github.com/keptn/lifecycle-toolkit/operator/controllers/errors" - interfacesfake "github.com/keptn/lifecycle-toolkit/operator/controllers/lifecycle/interfaces/fake" "github.com/magiconair/properties/assert" "github.com/stretchr/testify/require" testrequire "github.com/stretchr/testify/require" @@ -1048,7 +1047,7 @@ func TestKeptnWorkloadInstanceReconciler_ReconcileDoNotRetryAfterFailedPhase(t * } -func setupReconciler() (*KeptnWorkloadInstanceReconciler, chan string, *interfacesfake.ITracerMock) { +func setupReconciler() (*KeptnWorkloadInstanceReconciler, chan string, *fake.ITracerMock) { //setup logger opts := zap.Options{ Development: true, @@ -1056,20 +1055,24 @@ func setupReconciler() (*KeptnWorkloadInstanceReconciler, chan string, *interfac ctrl.SetLogger(zap.New(zap.UseFlagOptions(&opts))) //fake a tracer - tr := &interfacesfake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { + tr := &fake.ITracerMock{StartFunc: func(ctx context.Context, spanName string, opts ...trace.SpanStartOption) (context.Context, trace.Span) { return ctx, trace.SpanFromContext(ctx) }} + tf := &fake.TracerFactoryMock{GetTracerFunc: func(name string) trace.Tracer { + return tr + }} + fakeClient := fake.NewClient() recorder := record.NewFakeRecorder(100) r := &KeptnWorkloadInstanceReconciler{ - Client: fakeClient, - Scheme: scheme.Scheme, - Recorder: recorder, - Log: ctrl.Log.WithName("test-appController"), - Tracer: tr, - Meters: controllercommon.InitAppMeters(), - SpanHandler: &controllercommon.SpanHandler{}, + Client: fakeClient, + Scheme: scheme.Scheme, + Recorder: recorder, + Log: ctrl.Log.WithName("test-appController"), + TracerFactory: tf, + Meters: controllercommon.InitAppMeters(), + SpanHandler: &controllercommon.SpanHandler{}, } return r, recorder.Events, tr } diff --git a/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostdeployment.go b/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostdeployment.go index ffa8b77710..23983a11b1 100644 --- a/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostdeployment.go +++ b/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostdeployment.go @@ -15,7 +15,7 @@ func (r *KeptnWorkloadInstanceReconciler) reconcilePrePostDeployment(ctx context Client: r.Client, Recorder: r.Recorder, Log: r.Log, - Tracer: r.Tracer, + Tracer: r.getTracer(), Scheme: r.Scheme, SpanHandler: r.SpanHandler, } diff --git a/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostevaluation.go b/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostevaluation.go index 3ffdac7b69..5953ef2f16 100644 --- a/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostevaluation.go +++ b/operator/controllers/lifecycle/keptnworkloadinstance/reconcile_prepostevaluation.go @@ -15,7 +15,7 @@ func (r *KeptnWorkloadInstanceReconciler) reconcilePrePostEvaluation(ctx context Client: r.Client, Recorder: r.Recorder, Log: r.Log, - Tracer: r.Tracer, + Tracer: r.getTracer(), Scheme: r.Scheme, SpanHandler: r.SpanHandler, } diff --git a/operator/main.go b/operator/main.go index 842902adfd..67e94abc14 100644 --- a/operator/main.go +++ b/operator/main.go @@ -48,11 +48,8 @@ import ( keptnserver "github.com/keptn/lifecycle-toolkit/operator/pkg/metrics" "github.com/open-feature/go-sdk/pkg/openfeature" "github.com/prometheus/client_golang/prometheus/promhttp" - "go.opentelemetry.io/otel" otelprom "go.opentelemetry.io/otel/exporters/prometheus" - "go.opentelemetry.io/otel/propagation" "go.opentelemetry.io/otel/sdk/metric" - "go.opentelemetry.io/otel/sdk/trace" corev1 "k8s.io/api/core/v1" "k8s.io/apimachinery/pkg/runtime" utilruntime "k8s.io/apimachinery/pkg/util/runtime" @@ -163,31 +160,20 @@ func main() { keptnserver.StartServerManager(ctx, mgr.GetClient(), openfeature.NewClient("klt"), env.ExposeKeptnMetrics, metricServerTickerInterval) // Enabling OTel - tpOptions, _, err := controllercommon.GetOTelTracerProviderOptions("") + err = controllercommon.GetOtelInstance().InitOtelCollector("") if err != nil { setupLog.Error(err, "unable to initialize OTel tracer options") } - tp := trace.NewTracerProvider(tpOptions...) - - defer func() { - if err := tp.Shutdown(context.Background()); err != nil { - setupLog.Error(err, "unable to shutdown OTel exporter") - os.Exit(1) - } - }() - otel.SetTracerProvider(tp) - otel.SetTextMapPropagator(propagation.NewCompositeTextMapPropagator(propagation.TraceContext{}, propagation.Baggage{})) - spanHandler := &controllercommon.SpanHandler{} taskReconciler := &keptntask.KeptnTaskReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnTask Controller"), - Recorder: mgr.GetEventRecorderFor("keptntask-controller"), - Meters: keptnMeters, - Tracer: otel.Tracer("keptn/operator/task"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnTask Controller"), + Recorder: mgr.GetEventRecorderFor("keptntask-controller"), + Meters: keptnMeters, + TracerFactory: controllercommon.GetOtelInstance(), } if err = (taskReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnTask") @@ -206,11 +192,11 @@ func main() { } appReconciler := &keptnapp.KeptnAppReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnApp Controller"), - Recorder: mgr.GetEventRecorderFor("keptnapp-controller"), - Tracer: otel.Tracer("keptn/operator/app"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnApp Controller"), + Recorder: mgr.GetEventRecorderFor("keptnapp-controller"), + TracerFactory: controllercommon.GetOtelInstance(), } if err = (appReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnApp") @@ -218,11 +204,11 @@ func main() { } workloadReconciler := &keptnworkload.KeptnWorkloadReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnWorkload Controller"), - Recorder: mgr.GetEventRecorderFor("keptnworkload-controller"), - Tracer: otel.Tracer("keptn/operator/workload"), + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnWorkload Controller"), + Recorder: mgr.GetEventRecorderFor("keptnworkload-controller"), + TracerFactory: controllercommon.GetOtelInstance(), } if err = (workloadReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnWorkload") @@ -230,13 +216,13 @@ func main() { } workloadInstanceReconciler := &keptnworkloadinstance.KeptnWorkloadInstanceReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnWorkloadInstance Controller"), - Recorder: mgr.GetEventRecorderFor("keptnworkloadinstance-controller"), - Meters: keptnMeters, - Tracer: otel.Tracer("keptn/operator/workloadinstance"), - SpanHandler: spanHandler, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnWorkloadInstance Controller"), + Recorder: mgr.GetEventRecorderFor("keptnworkloadinstance-controller"), + Meters: keptnMeters, + TracerFactory: controllercommon.GetOtelInstance(), + SpanHandler: spanHandler, } if err = (workloadInstanceReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnWorkloadInstance") @@ -244,13 +230,13 @@ func main() { } appVersionReconciler := &keptnappversion.KeptnAppVersionReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnAppVersion Controller"), - Recorder: mgr.GetEventRecorderFor("keptnappversion-controller"), - Tracer: otel.Tracer("keptn/operator/appversion"), - Meters: keptnMeters, - SpanHandler: spanHandler, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnAppVersion Controller"), + Recorder: mgr.GetEventRecorderFor("keptnappversion-controller"), + TracerFactory: controllercommon.GetOtelInstance(), + Meters: keptnMeters, + SpanHandler: spanHandler, } if err = (appVersionReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnAppVersion") @@ -258,13 +244,13 @@ func main() { } evaluationReconciler := &keptnevaluation.KeptnEvaluationReconciler{ - Client: mgr.GetClient(), - Scheme: mgr.GetScheme(), - Log: ctrl.Log.WithName("KeptnEvaluation Controller"), - Recorder: mgr.GetEventRecorderFor("keptnevaluation-controller"), - Tracer: otel.Tracer("keptn/operator/evaluation"), - Meters: keptnMeters, - Namespace: env.PodNamespace, + Client: mgr.GetClient(), + Scheme: mgr.GetScheme(), + Log: ctrl.Log.WithName("KeptnEvaluation Controller"), + Recorder: mgr.GetEventRecorderFor("keptnevaluation-controller"), + TracerFactory: controllercommon.GetOtelInstance(), + Meters: keptnMeters, + Namespace: env.PodNamespace, } if err = (evaluationReconciler).SetupWithManager(mgr); err != nil { setupLog.Error(err, "unable to create controller", "controller", "KeptnEvaluation") diff --git a/operator/test/component/appcontroller_test.go b/operator/test/component/appcontroller_test.go index d10cc22594..81db12799e 100644 --- a/operator/test/component/appcontroller_test.go +++ b/operator/test/component/appcontroller_test.go @@ -45,11 +45,11 @@ var _ = Describe("KeptnAppController", Ordered, func() { ////setup controllers here controllers := []interfaces.Controller{&keptnapp.KeptnAppReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("test-app-controller"), - Log: GinkgoLogr, - Tracer: tracer.Tracer("test-app-tracer"), + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("test-app-controller"), + Log: GinkgoLogr, + TracerFactory: &tracerFactory{tracer: tracer}, }} setupManager(controllers) // we can register multiple time the same controller // so that they have a different span/trace diff --git a/operator/test/component/common.go b/operator/test/component/common.go index f9d8fe4395..65fd962426 100644 --- a/operator/test/component/common.go +++ b/operator/test/component/common.go @@ -2,9 +2,11 @@ package component import ( apicommon "github.com/keptn/lifecycle-toolkit/operator/apis/lifecycle/v1alpha2/common" + controllercommon "github.com/keptn/lifecycle-toolkit/operator/controllers/common" "go.opentelemetry.io/otel/metric/instrument" "go.opentelemetry.io/otel/metric/unit" "go.opentelemetry.io/otel/sdk/metric" + "go.opentelemetry.io/otel/trace" ) func initKeptnMeters() apicommon.KeptnMeters { @@ -31,3 +33,11 @@ func initKeptnMeters() apicommon.KeptnMeters { } return meters } + +type tracerFactory struct { + tracer trace.TracerProvider +} + +func (f *tracerFactory) GetTracer(name string) controllercommon.ITracer { + return f.tracer.Tracer(name) +} diff --git a/operator/test/component/evaluationcontroller_test.go b/operator/test/component/evaluationcontroller_test.go index d79588467c..a6cc837b8f 100644 --- a/operator/test/component/evaluationcontroller_test.go +++ b/operator/test/component/evaluationcontroller_test.go @@ -48,13 +48,13 @@ var _ = Describe("KeptnEvaluationController", Ordered, func() { ////setup controllers here controllers := []interfaces.Controller{&keptnevaluation.KeptnEvaluationReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("test-evaluation-controller"), - Log: GinkgoLogr, - Meters: initKeptnMeters(), - Tracer: tracer.Tracer("test-evaluation-tracer"), - Namespace: KLTnamespace, + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("test-evaluation-controller"), + Log: GinkgoLogr, + Meters: initKeptnMeters(), + TracerFactory: &tracerFactory{tracer: tracer}, + Namespace: KLTnamespace, }} setupManager(controllers) // we can register multiple time the same controller ns = makeKLTDefaultNamespace(KLTnamespace) diff --git a/operator/test/component/load_test.go b/operator/test/component/load_test.go index 0b7e10d58a..cda0180f63 100644 --- a/operator/test/component/load_test.go +++ b/operator/test/component/load_test.go @@ -43,11 +43,11 @@ var _ = Describe("[Feature:Performance] Load KeptnAppController", Ordered, func( tracer = otelsdk.NewTracerProvider(otelsdk.WithSpanProcessor(spanRecorder)) controllers := []interfaces.Controller{&keptnapp.KeptnAppReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("load-app-controller"), - Log: GinkgoLogr, - Tracer: tracer.Tracer("load-app-tracer"), + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("load-app-controller"), + Log: GinkgoLogr, + TracerFactory: &tracerFactory{tracer: tracer}, }} setupManager(controllers) }) diff --git a/operator/test/component/taskcontroller_test.go b/operator/test/component/taskcontroller_test.go index 45889f6898..309d2ece02 100644 --- a/operator/test/component/taskcontroller_test.go +++ b/operator/test/component/taskcontroller_test.go @@ -42,12 +42,12 @@ var _ = Describe("KeptnTaskController", Ordered, func() { ////setup controllers here controllers := []interfaces.Controller{&keptntask.KeptnTaskReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("test-task-controller"), - Log: GinkgoLogr, - Meters: initKeptnMeters(), - Tracer: tracer.Tracer("test-task-tracer"), + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("test-task-controller"), + Log: GinkgoLogr, + Meters: initKeptnMeters(), + TracerFactory: &tracerFactory{tracer: tracer}, }} setupManager(controllers) // we can register multiple time the same controller }) diff --git a/operator/test/component/workloadinstancecontroller_test.go b/operator/test/component/workloadinstancecontroller_test.go index 881173f0ee..4daea0d680 100644 --- a/operator/test/component/workloadinstancecontroller_test.go +++ b/operator/test/component/workloadinstancecontroller_test.go @@ -68,13 +68,13 @@ var _ = Describe("KeptnWorkloadInstanceController", Ordered, func() { ////setup controllers here controllers := []interfaces.Controller{&keptnworkloadinstance.KeptnWorkloadInstanceReconciler{ - Client: k8sManager.GetClient(), - Scheme: k8sManager.GetScheme(), - Recorder: k8sManager.GetEventRecorderFor("test-app-controller"), - Log: GinkgoLogr, - Meters: initKeptnMeters(), - SpanHandler: &controllercommon.SpanHandler{}, - Tracer: tracer.Tracer("test-app-tracer"), + Client: k8sManager.GetClient(), + Scheme: k8sManager.GetScheme(), + Recorder: k8sManager.GetEventRecorderFor("test-app-controller"), + Log: GinkgoLogr, + Meters: initKeptnMeters(), + SpanHandler: &controllercommon.SpanHandler{}, + TracerFactory: &tracerFactory{tracer: tracer}, }} setupManager(controllers) // we can register multiple time the same controller // so that they have a different span/trace