in pkg/instrumentation/podmutator.go [207:362]
func (pm *instPodMutator) Mutate(ctx context.Context, ns corev1.Namespace, pod corev1.Pod) (corev1.Pod, error) {
logger := pm.Logger.WithValues("namespace", pod.Namespace, "name", pod.Name)
// We check if Pod is already instrumented.
if isAutoInstrumentationInjected(pod) {
logger.Info("Skipping pod instrumentation - already instrumented")
return pod, nil
}
var inst *v1alpha1.Instrumentation
var err error
insts := languageInstrumentations{}
// We bail out if any annotation fails to process.
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectJava); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableJavaAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.Java.Instrumentation = inst
} else {
logger.Error(nil, "support for Java auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Java auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectNodeJS); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableNodeJSAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.NodeJS.Instrumentation = inst
} else {
logger.Error(nil, "support for NodeJS auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for NodeJS auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectPython); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnablePythonAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.Python.Instrumentation = inst
} else {
logger.Error(nil, "support for Python auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Python auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectDotNet); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableDotnetAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.DotNet.Instrumentation = inst
insts.DotNet.AdditionalAnnotations = map[string]string{annotationDotNetRuntime: annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationDotNetRuntime)}
} else {
logger.Error(nil, "support for .NET auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for .NET auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectGo); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableGoAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.Go.Instrumentation = inst
} else {
logger.Error(err, "support for Go auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Go auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectApacheHttpd); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableApacheHTTPAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.ApacheHttpd.Instrumentation = inst
} else {
logger.Error(nil, "support for Apache HTTPD auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Apache HTTPD auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectNginx); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
if featuregate.EnableNginxAutoInstrumentationSupport.IsEnabled() || inst == nil {
insts.Nginx.Instrumentation = inst
} else {
logger.Error(nil, "support for Nginx auto instrumentation is not enabled")
pm.Recorder.Event(pod.DeepCopy(), "Warning", "InstrumentationRequestRejected", "support for Nginx auto instrumentation is not enabled")
}
if inst, err = pm.getInstrumentationInstance(ctx, ns, pod, annotationInjectSdk); err != nil {
// we still allow the pod to be created, but we log a message to the operator's logs
logger.Error(err, "failed to select an OpenTelemetry Instrumentation instance for this pod")
return pod, err
}
insts.Sdk.Instrumentation = inst
if insts.Java.Instrumentation == nil && insts.NodeJS.Instrumentation == nil && insts.Python.Instrumentation == nil &&
insts.DotNet.Instrumentation == nil && insts.Go.Instrumentation == nil && insts.ApacheHttpd.Instrumentation == nil &&
insts.Nginx.Instrumentation == nil &&
insts.Sdk.Instrumentation == nil {
logger.V(1).Info("annotation not present in deployment, skipping instrumentation injection")
return pod, nil
}
// We retrieve the annotation for podname
if featuregate.EnableMultiInstrumentationSupport.IsEnabled() {
// We use annotations specific for instrumentation language
insts.Java.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectJavaContainersName)
insts.NodeJS.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectNodeJSContainersName)
insts.Python.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectPythonContainersName)
insts.DotNet.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectDotnetContainersName)
insts.Go.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectGoContainersName)
insts.ApacheHttpd.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectApacheHttpdContainersName)
insts.Nginx.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectNginxContainersName)
insts.Sdk.Containers = annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectSdkContainersName)
// We check if provided annotations and instrumentations are valid
ok, msg := insts.areContainerNamesConfiguredForMultipleInstrumentations()
if !ok {
logger.V(1).Error(msg, "skipping instrumentation injection")
return pod, nil
}
} else {
// We use general annotation for container names
// only when multi instrumentation is disabled
singleInstrEnabled := insts.isSingleInstrumentationEnabled()
if singleInstrEnabled {
generalContainerNames := annotationValue(ns.ObjectMeta, pod.ObjectMeta, annotationInjectContainerName)
insts.setInstrumentationLanguageContainers(generalContainerNames)
} else {
logger.V(1).Error(fmt.Errorf("multiple injection annotations present"), "skipping instrumentation injection")
return pod, nil
}
}
// once it's been determined that instrumentation is desired, none exists yet, and we know which instance it should talk to,
// we should inject the instrumentation.
modifiedPod := pod
modifiedPod = pm.sdkInjector.inject(ctx, insts, ns, modifiedPod)
return modifiedPod, nil
}