Repository: open-telemetry/opentelemetry-operator
Pull request #3948 (2025-04-29 14:00:09)

[Chore] Update Dotnet instrumentation tests to assert telemetry data
**Description:** <Describe what has changed.>
The PR updates the Dotnet instrumentation tests to assert the telemetry data. To be retested and merged after PR https://github.com/open-telemetry/opentelemetry-operator/pull/3946 is merged. 



Patch:
diff --git a/.chloggen/fix_ta-cmdline-values.yaml b/.chloggen/fix_ta-cmdline-values.yaml
new file mode 100755
index 00000000..9734ece9
--- /dev/null
+++ b/.chloggen/fix_ta-cmdline-values.yaml
@@ -0,0 +1,16 @@
+# One of 'breaking', 'deprecation', 'new_component', 'enhancement', 'bug_fix'
+change_type: bug_fix
+
+# The name of the component, or a single word describing the area of concern, (e.g. collector, target allocator, auto-instrumentation, opamp, github action)
+component: target allocator
+
+# A brief description of the change. Surround your text with quotes ("") if it needs to start with a backtick (`).
+note: Fix config loading priority
+
+# One or more tracking issues related to the change
+issues: [3928]
+
+# (Optional) One or more lines of additional information to render under the primary note.
+# These lines will be padded with 2 spaces and then inserted directly into the document.
+# Use pipe (|) for multiline entries.
+subtext:
\ No newline at end of file
diff --git a/cmd/otel-allocator/internal/config/config.go b/cmd/otel-allocator/internal/config/config.go
index f118fc33..bc51a1d6 100644
--- a/cmd/otel-allocator/internal/config/config.go
+++ b/cmd/otel-allocator/internal/config/config.go
@@ -12,6 +12,7 @@ import (
 	"log/slog"
 	"math"
 	"os"
+	"path/filepath"
 	"reflect"
 	"time"
 
@@ -26,12 +27,15 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 	"k8s.io/client-go/rest"
 	"k8s.io/client-go/tools/clientcmd"
+	"k8s.io/client-go/util/homedir"
 	"k8s.io/klog/v2"
 	ctrl "sigs.k8s.io/controller-runtime"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 )
 
 const (
+	DefaultListenAddr                                  = ":8080"
+	DefaultHttpsListenAddr                             = ":8443"
 	DefaultResyncTime                                  = 5 * time.Minute
 	DefaultConfigFilePath               string         = "/conf/targetallocator.yaml"
 	DefaultCRScrapeInterval             model.Duration = model.Duration(time.Second * 30)
@@ -40,6 +44,10 @@ const (
 	DefaultCollectorNotReadyGracePeriod                = 0 * time.Second
 )
 
+var (
+	DefaultKubeConfigFilePath string = filepath.Join(homedir.HomeDir(), ".kube", "config")
+)
+
 // By default, scrape protocols include PrometheusText1_0_0, which only Prometheus >=3.0 supports.
 // Manually exclude this protocol until several versions of the Otel Collector support it.
 var DefaultScrapeProtocols = []promconfig.ScrapeProtocol{
@@ -227,9 +235,10 @@ func LoadFromCLI(target *Config, flagSet *pflag.FlagSet) error {
 	klog.SetLogger(target.RootLogger)
 	ctrl.SetLogger(target.RootLogger)
 
-	target.KubeConfigFilePath, err = getKubeConfigFilePath(flagSet)
-	if err != nil {
-		return err
+	if kubeConfigFilePath, changed, flagErr := getKubeConfigFilePath(flagSet); flagErr != nil {
+		return flagErr
+	} else if changed {
+		target.KubeConfigFilePath = kubeConfigFilePath
 	}
 	clusterConfig, err := clientcmd.BuildConfigFromFlags("", target.KubeConfigFilePath)
 	if err != nil {
@@ -245,9 +254,10 @@ func LoadFromCLI(target *Config, flagSet *pflag.FlagSet) error {
 	}
 	target.ClusterConfig = clusterConfig
 
-	target.ListenAddr, err = getListenAddr(flagSet)
-	if err != nil {
-		return err
+	if listenAddr, changed, flagErr := getListenAddr(flagSet); flagErr != nil {
+		return flagErr
+	} else if changed {
+		target.ListenAddr = listenAddr
 	}
 
 	if prometheusCREnabled, changed, flagErr := getPrometheusCREnabled(flagSet); flagErr != nil {
@@ -335,6 +345,11 @@ func unmarshal(cfg *Config, configFile string) error {
 
 func CreateDefaultConfig() Config {
 	return Config{
+		ListenAddr:         DefaultListenAddr,
+		KubeConfigFilePath: DefaultKubeConfigFilePath,
+		HTTPS: HTTPSServerConfig{
+			ListenAddr: DefaultHttpsListenAddr,
+		},
 		AllocationStrategy:         DefaultAllocationStrategy,
 		AllocationFallbackStrategy: "",
 		FilterStrategy:             DefaultFilterStrategy,
@@ -349,11 +364,11 @@ func CreateDefaultConfig() Config {
 	}
 }
 
-func Load() (*Config, error) {
+func Load(args []string) (*Config, error) {
 	var err error
 
 	flagSet := getFlagSet(pflag.ExitOnError)
-	err = flagSet.Parse(os.Args)
+	err = flagSet.Parse(args)
 	if err != nil {
 		return nil, err
 	}
diff --git a/cmd/otel-allocator/internal/config/flags.go b/cmd/otel-allocator/internal/config/flags.go
index 5c812e8f..ae156ff8 100644
--- a/cmd/otel-allocator/internal/config/flags.go
+++ b/cmd/otel-allocator/internal/config/flags.go
@@ -5,10 +5,8 @@ package config
 
 import (
 	"flag"
-	"path/filepath"
 
 	"github.com/spf13/pflag"
-	"k8s.io/client-go/util/homedir"
 	"sigs.k8s.io/controller-runtime/pkg/log/zap"
 )
 
@@ -32,11 +30,11 @@ var zapCmdLineOpts zap.Options
 func getFlagSet(errorHandling pflag.ErrorHandling) *pflag.FlagSet {
 	flagSet := pflag.NewFlagSet(targetAllocatorName, errorHandling)
 	flagSet.String(configFilePathFlagName, DefaultConfigFilePath, "The path to the config file.")
-	flagSet.String(listenAddrFlagName, ":8080", "The address where this service serves.")
+	flagSet.String(listenAddrFlagName, DefaultListenAddr, "The address where this service serves.")
 	flagSet.Bool(prometheusCREnabledFlagName, false, "Enable Prometheus CRs as target sources")
-	flagSet.String(kubeConfigPathFlagName, filepath.Join(homedir.HomeDir(), ".kube", "config"), "absolute path to the KubeconfigPath file")
+	flagSet.String(kubeConfigPathFlagName, DefaultKubeConfigFilePath, "absolute path to the KubeconfigPath file")
 	flagSet.Bool(httpsEnabledFlagName, false, "Enable HTTPS additional server")
-	flagSet.String(listenAddrHttpsFlagName, ":8443", "The address where this service serves over HTTPS.")
+	flagSet.String(listenAddrHttpsFlagName, DefaultHttpsListenAddr, "The address where this service serves over HTTPS.")
 	flagSet.String(httpsCAFilePathFlagName, "", "The path to the HTTPS server TLS CA file.")
 	flagSet.String(httpsTLSCertFilePathFlagName, "", "The path to the HTTPS server TLS certificate file.")
 	flagSet.String(httpsTLSKeyFilePathFlagName, "", "The path to the HTTPS server TLS key file.")
@@ -50,64 +48,54 @@ func getConfigFilePath(flagSet *pflag.FlagSet) (string, error) {
 	return flagSet.GetString(configFilePathFlagName)
 }
 
-func getKubeConfigFilePath(flagSet *pflag.FlagSet) (string, error) {
-	return flagSet.GetString(kubeConfigPathFlagName)
+func getKubeConfigFilePath(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
+	return getFlagValueAndChangedString(flagSet, kubeConfigPathFlagName)
 }
 
-func getListenAddr(flagSet *pflag.FlagSet) (string, error) {
-	return flagSet.GetString(listenAddrFlagName)
+func getListenAddr(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
+	return getFlagValueAndChangedString(flagSet, listenAddrFlagName)
 }
 
 func getPrometheusCREnabled(flagSet *pflag.FlagSet) (value bool, changed bool, err error) {
-	if changed = flagSet.Changed(prometheusCREnabledFlagName); !changed {
-		value, err = false, nil
-		return
-	}
-	value, err = flagSet.GetBool(prometheusCREnabledFlagName)
-	return
+	return getFlagValueAndChangedBool(flagSet, prometheusCREnabledFlagName)
 }
 
 func getHttpsListenAddr(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
-	if changed = flagSet.Changed(listenAddrHttpsFlagName); !changed {
-		value, err = ":8443", nil
-		return
-	}
-	value, err = flagSet.GetString(listenAddrHttpsFlagName)
-	return
+	return getFlagValueAndChangedString(flagSet, listenAddrHttpsFlagName)
 }
 
 func getHttpsEnabled(flagSet *pflag.FlagSet) (value bool, changed bool, err error) {
-	if changed = flagSet.Changed(httpsEnabledFlagName); !changed {
-		value, err = false, nil
-		return
-	}
-	value, err = flagSet.GetBool(httpsEnabledFlagName)
-	return
+	return getFlagValueAndChangedBool(flagSet, httpsEnabledFlagName)
 }
 
 func getHttpsCAFilePath(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
-	if changed = flagSet.Changed(httpsCAFilePathFlagName); !changed {
-		value, err = "", nil
-		return
-	}
-	value, err = flagSet.GetString(httpsCAFilePathFlagName)
-	return
+	return getFlagValueAndChangedString(flagSet, httpsCAFilePathFlagName)
 }
 
 func getHttpsTLSCertFilePath(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
-	if changed = flagSet.Changed(httpsTLSCertFilePathFlagName); !changed {
+	return getFlagValueAndChangedString(flagSet, httpsTLSCertFilePathFlagName)
+}
+
+func getHttpsTLSKeyFilePath(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
+	return getFlagValueAndChangedString(flagSet, httpsTLSKeyFilePathFlagName)
+}
+
+// getFlagValueAndChanged returns the given flag's string value and whether it was changed.
+func getFlagValueAndChangedString(flagSet *pflag.FlagSet, flagName string) (value string, changed bool, err error) {
+	if changed = flagSet.Changed(flagName); !changed {
 		value, err = "", nil
 		return
 	}
-	value, err = flagSet.GetString(httpsTLSCertFilePathFlagName)
+	value, err = flagSet.GetString(flagName)
 	return
 }
 
-func getHttpsTLSKeyFilePath(flagSet *pflag.FlagSet) (value string, changed bool, err error) {
-	if changed = flagSet.Changed(httpsTLSKeyFilePathFlagName); !changed {
-		value, err = "", nil
+// getFlagValueAndChanged returns the given flag's string value and whether it was changed.
+func getFlagValueAndChangedBool(flagSet *pflag.FlagSet, flagName string) (value bool, changed bool, err error) {
+	if changed = flagSet.Changed(flagName); !changed {
+		value, err = false, nil
 		return
 	}
-	value, err = flagSet.GetString(httpsTLSKeyFilePathFlagName)
+	value, err = flagSet.GetBool(flagName)
 	return
 }
diff --git a/cmd/otel-allocator/main.go b/cmd/otel-allocator/main.go
index 1b387585..6035080f 100644
--- a/cmd/otel-allocator/main.go
+++ b/cmd/otel-allocator/main.go
@@ -52,7 +52,7 @@ func main() {
 		interrupts      = make(chan os.Signal, 1)
 		errChan         = make(chan error)
 	)
-	cfg, err := config.Load()
+	cfg, err := config.Load(os.Args)
 	if err != nil {
 		fmt.Printf("Failed to load config: %v", err)
 		os.Exit(1)


Test patch:
diff --git a/cmd/otel-allocator/internal/config/config_test.go b/cmd/otel-allocator/internal/config/config_test.go
index 9df390f4..7593681e 100644
--- a/cmd/otel-allocator/internal/config/config_test.go
+++ b/cmd/otel-allocator/internal/config/config_test.go
@@ -6,6 +6,7 @@ package config
 import (
 	"fmt"
 	"os"
+	"path/filepath"
 	"testing"
 	"time"
 
@@ -20,7 +21,7 @@ import (
 	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
 )
 
-func TestLoad(t *testing.T) {
+func TestLoadFromFile(t *testing.T) {
 	type args struct {
 		file string
 	}
@@ -36,6 +37,8 @@ func TestLoad(t *testing.T) {
 				file: "./testdata/config_test.yaml",
 			},
 			want: Config{
+				ListenAddr:         DefaultListenAddr,
+				KubeConfigFilePath: DefaultKubeConfigFilePath,
 				AllocationStrategy: DefaultAllocationStrategy,
 				CollectorNamespace: "default",
 				CollectorSelector: &metav1.LabelSelector{
@@ -122,6 +125,8 @@ func TestLoad(t *testing.T) {
 				file: "./testdata/pod_service_selector_test.yaml",
 			},
 			want: Config{
+				ListenAddr:         DefaultListenAddr,
+				KubeConfigFilePath: DefaultKubeConfigFilePath,
 				AllocationStrategy: DefaultAllocationStrategy,
 				CollectorNamespace: "default",
 				CollectorSelector: &metav1.LabelSelector{
@@ -148,6 +153,9 @@ func TestLoad(t *testing.T) {
 					ProbeNamespaceSelector:          &metav1.LabelSelector{},
 					ScrapeInterval:                  DefaultCRScrapeInterval,
 				},
+				HTTPS: HTTPSServerConfig{
+					ListenAddr: ":8443",
+				},
 				PromConfig: &promconfig.Config{
 					GlobalConfig: promconfig.GlobalConfig{
 						ScrapeInterval:     model.Duration(60 * time.Second),
@@ -197,6 +205,8 @@ func TestLoad(t *testing.T) {
 				file: "./testdata/pod_service_selector_camelcase_test.yaml",
 			},
 			want: Config{
+				ListenAddr:         DefaultListenAddr,
+				KubeConfigFilePath: DefaultKubeConfigFilePath,
 				AllocationStrategy: DefaultAllocationStrategy,
 				CollectorNamespace: "default",
 				CollectorSelector: &metav1.LabelSelector{
@@ -223,6 +233,9 @@ func TestLoad(t *testing.T) {
 					ProbeNamespaceSelector:          &metav1.LabelSelector{},
 					ScrapeInterval:                  DefaultCRScrapeInterval,
 				},
+				HTTPS: HTTPSServerConfig{
+					ListenAddr: ":8443",
+				},
 				PromConfig: &promconfig.Config{
 					GlobalConfig: promconfig.GlobalConfig{
 						ScrapeInterval:     model.Duration(60 * time.Second),
@@ -272,6 +285,8 @@ func TestLoad(t *testing.T) {
 				file: "./testdata/pod_service_selector_expressions_test.yaml",
 			},
 			want: Config{
+				ListenAddr:         DefaultListenAddr,
+				KubeConfigFilePath: DefaultKubeConfigFilePath,
 				AllocationStrategy: DefaultAllocationStrategy,
 				CollectorNamespace: "default",
 				CollectorSelector: &metav1.LabelSelector{
@@ -322,6 +337,9 @@ func TestLoad(t *testing.T) {
 					ProbeNamespaceSelector:          &metav1.LabelSelector{},
 					ScrapeInterval:                  DefaultCRScrapeInterval,
 				},
+				HTTPS: HTTPSServerConfig{
+					ListenAddr: ":8443",
+				},
 				PromConfig: &promconfig.Config{
 					GlobalConfig: promconfig.GlobalConfig{
 						ScrapeInterval:     model.Duration(60 * time.Second),
@@ -371,6 +389,8 @@ func TestLoad(t *testing.T) {
 				file: "./testdata/pod_service_selector_camelcase_expressions_test.yaml",
 			},
 			want: Config{
+				ListenAddr:         DefaultListenAddr,
+				KubeConfigFilePath: DefaultKubeConfigFilePath,
 				AllocationStrategy: DefaultAllocationStrategy,
 				CollectorNamespace: "default",
 				CollectorSelector: &metav1.LabelSelector{
@@ -421,6 +441,9 @@ func TestLoad(t *testing.T) {
 					ProbeNamespaceSelector:          &metav1.LabelSelector{},
 					ScrapeInterval:                  DefaultCRScrapeInterval,
 				},
+				HTTPS: HTTPSServerConfig{
+					ListenAddr: ":8443",
+				},
 				PromConfig: &promconfig.Config{
 					GlobalConfig: promconfig.GlobalConfig{
 						ScrapeInterval:     model.Duration(60 * time.Second),
@@ -599,3 +622,259 @@ func TestGetAllowDenyLists(t *testing.T) {
 		})
 	}
 }
+
+func TestConfigLoadPriority(t *testing.T) {
+	// Helper function to create a dummy kube config for tests
+	createDummyKubeConfig := func(t *testing.T, dir string) string {
+		kubeConfigPath := filepath.Join(dir, "kube.config")
+		kubeConfigContent := `
+apiVersion: v1
+kind: Config
+clusters:
+- cluster:
+    server: https://example.com
+  name: test-cluster
+contexts:
+- context:
+    cluster: test-cluster
+    user: test-user
+  name: test-context
+current-context: test-context
+users:
+- name: test-user
+  user:
+    token: dummy-token
+`
+		err := os.WriteFile(kubeConfigPath, []byte(kubeConfigContent), 0600)
+		require.NoError(t, err)
+		return kubeConfigPath
+	}
+
+	t.Run("default values when nothing is set", func(t *testing.T) {
+		// Setup: create empty config file and dummy kube config
+		tempDir := t.TempDir()
+		emptyConfigPath := filepath.Join(tempDir, "empty.yaml")
+		err := os.WriteFile(emptyConfigPath, []byte("{}"), 0600)
+		require.NoError(t, err)
+
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		// Prepare args for Load function
+		args := []string{
+			"--" + configFilePathFlagName + "=" + emptyConfigPath,
+			"--" + kubeConfigPathFlagName + "=" + kubeConfigPath,
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert defaults are used
+		assert.Equal(t, DefaultListenAddr, config.ListenAddr)
+		assert.Equal(t, kubeConfigPath, config.KubeConfigFilePath)
+		assert.Equal(t, DefaultHttpsListenAddr, config.HTTPS.ListenAddr)
+		assert.Equal(t, DefaultAllocationStrategy, config.AllocationStrategy)
+		assert.Equal(t, DefaultFilterStrategy, config.FilterStrategy)
+		assert.False(t, config.PrometheusCR.Enabled)
+		assert.False(t, config.HTTPS.Enabled)
+	})
+
+	t.Run("command-line has priority over config file for boolean values", func(t *testing.T) {
+		// Setup: create config file with values and dummy kube config
+		tempDir := t.TempDir()
+		configContent := `
+prometheus_cr:
+  enabled: false
+https:
+  enabled: false
+`
+		configPath := filepath.Join(tempDir, "config.yaml")
+		err := os.WriteFile(configPath, []byte(configContent), 0600)
+		require.NoError(t, err)
+
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		// Prepare args for Load function that override config file
+		args := []string{
+			"--" + configFilePathFlagName + "=" + configPath,
+			"--" + prometheusCREnabledFlagName + "=true",
+			"--" + httpsEnabledFlagName + "=true",
+			"--" + kubeConfigPathFlagName + "=" + kubeConfigPath,
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert CLI values override config file
+		assert.True(t, config.PrometheusCR.Enabled, "CLI should override config file for prometheus CR enabled")
+		assert.True(t, config.HTTPS.Enabled, "CLI should override config file for HTTPS enabled")
+	})
+
+	t.Run("command-line has priority over config file for string values", func(t *testing.T) {
+		// Setup: create config file with values and dummy kube config
+		tempDir := t.TempDir()
+		configContent := `
+listen_addr: ":9090"
+https:
+  listen_addr: ":9443"
+  ca_file_path: "/config/ca.pem"
+  tls_cert_file_path: "/config/cert.pem"
+  tls_key_file_path: "/config/key.pem"
+kube_config_file_path: "/config/kube.config"
+`
+		configPath := filepath.Join(tempDir, "config.yaml")
+		err := os.WriteFile(configPath, []byte(configContent), 0600)
+		require.NoError(t, err)
+
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		// CLI values different from config file
+		cliListenAddr := ":8888"
+		cliHttpsListenAddr := ":8443"
+		cliCAPath := "/cli/ca.pem"
+		cliCertPath := "/cli/cert.pem"
+		cliKeyPath := "/cli/key.pem"
+
+		// Prepare args for Load function that override config file
+		args := []string{
+			"--" + configFilePathFlagName + "=" + configPath,
+			"--" + listenAddrFlagName + "=" + cliListenAddr,
+			"--" + listenAddrHttpsFlagName + "=" + cliHttpsListenAddr,
+			"--" + httpsCAFilePathFlagName + "=" + cliCAPath,
+			"--" + httpsTLSCertFilePathFlagName + "=" + cliCertPath,
+			"--" + httpsTLSKeyFilePathFlagName + "=" + cliKeyPath,
+			"--" + kubeConfigPathFlagName + "=" + kubeConfigPath,
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert CLI values override config file
+		assert.Equal(t, cliListenAddr, config.ListenAddr, "CLI should override config file for listen address")
+		assert.Equal(t, cliHttpsListenAddr, config.HTTPS.ListenAddr, "CLI should override config file for HTTPS listen address")
+		assert.Equal(t, cliCAPath, config.HTTPS.CAFilePath, "CLI should override config file for CA file path")
+		assert.Equal(t, cliCertPath, config.HTTPS.TLSCertFilePath, "CLI should override config file for TLS cert file path")
+		assert.Equal(t, cliKeyPath, config.HTTPS.TLSKeyFilePath, "CLI should override config file for TLS key file path")
+		assert.Equal(t, kubeConfigPath, config.KubeConfigFilePath, "CLI should override config file for kube config path")
+	})
+
+	t.Run("config file overrides defaults when CLI not specified", func(t *testing.T) {
+		// Setup: create config file with values and dummy kube config
+		tempDir := t.TempDir()
+		configListenAddr := ":7070"
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		configContent := `
+listen_addr: "` + configListenAddr + `"
+prometheus_cr:
+  enabled: true
+https:
+  enabled: true
+  listen_addr: ":7443"
+kube_config_file_path: "` + kubeConfigPath + `"
+`
+		configPath := filepath.Join(tempDir, "config.yaml")
+		err := os.WriteFile(configPath, []byte(configContent), 0600)
+		require.NoError(t, err)
+
+		// Prepare args for Load function with only config file path
+		args := []string{
+			"--" + configFilePathFlagName + "=" + configPath,
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert config file values override defaults
+		assert.Equal(t, configListenAddr, config.ListenAddr, "Config file should override defaults for listen address")
+		assert.True(t, config.PrometheusCR.Enabled, "Config file should override defaults for prometheus CR enabled")
+		assert.True(t, config.HTTPS.Enabled, "Config file should override defaults for HTTPS enabled")
+		assert.Equal(t, ":7443", config.HTTPS.ListenAddr, "Config file should override defaults for HTTPS listen address")
+		assert.Equal(t, kubeConfigPath, config.KubeConfigFilePath, "Config file should set kube config path")
+	})
+
+	t.Run("environment variables are applied", func(t *testing.T) {
+		// Setup: create empty config file and dummy kube config
+		tempDir := t.TempDir()
+		emptyConfigPath := filepath.Join(tempDir, "empty.yaml")
+		err := os.WriteFile(emptyConfigPath, []byte("{}"), 0600)
+		require.NoError(t, err)
+
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		// Save original env var value and restore after test
+		originalNamespace := os.Getenv("OTELCOL_NAMESPACE")
+		defer func() {
+			envErr := os.Setenv("OTELCOL_NAMESPACE", originalNamespace)
+			assert.NoError(t, envErr)
+		}()
+
+		// Set environment variable
+		testNamespace := "test-namespace"
+		err = os.Setenv("OTELCOL_NAMESPACE", testNamespace)
+		require.NoError(t, err)
+
+		// Prepare args for Load function
+		args := []string{
+			"--" + configFilePathFlagName + "=" + emptyConfigPath,
+			"--" + kubeConfigPathFlagName + "=" + kubeConfigPath,
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert environment variable is applied
+		assert.Equal(t, testNamespace, config.CollectorNamespace, "Environment variable should be applied")
+	})
+
+	t.Run("loading priority order: defaults <- config file <- env vars <- CLI", func(t *testing.T) {
+		// Setup: create config file with values and dummy kube config
+		tempDir := t.TempDir()
+		kubeConfigPath := createDummyKubeConfig(t, tempDir)
+
+		// Config file sets values
+		configContent := `
+collector_namespace: "config-file-namespace"
+listen_addr: ":9090"
+prometheus_cr:
+  enabled: false
+kube_config_file_path: "` + kubeConfigPath + `"
+`
+		configPath := filepath.Join(tempDir, "config.yaml")
+		err := os.WriteFile(configPath, []byte(configContent), 0600)
+		require.NoError(t, err)
+
+		// Save original env var value and restore after test
+		originalNamespace := os.Getenv("OTELCOL_NAMESPACE")
+		defer func() {
+			envErr := os.Setenv("OTELCOL_NAMESPACE", originalNamespace)
+			assert.NoError(t, envErr)
+		}()
+
+		// Environment variable sets value
+		testNamespace := "env-var-namespace"
+		err = os.Setenv("OTELCOL_NAMESPACE", testNamespace)
+		require.NoError(t, err)
+
+		// Prepare args for Load function with CLI values
+		cliListenAddr := ":8888"
+		args := []string{
+			"--" + configFilePathFlagName + "=" + configPath,
+			"--" + listenAddrFlagName + "=" + cliListenAddr,
+			"--" + prometheusCREnabledFlagName + "=true",
+		}
+
+		// Load config using the full Load function
+		config, err := Load(args)
+		require.NoError(t, err)
+
+		// Assert correct priority: CLI over env vars over config file over defaults
+		assert.Equal(t, testNamespace, config.CollectorNamespace, "Env var should override config file for namespace")
+		assert.Equal(t, cliListenAddr, config.ListenAddr, "CLI should override config file for listen address")
+		assert.True(t, config.PrometheusCR.Enabled, "CLI should override config file for prometheus CR enabled")
+	})
+}
diff --git a/cmd/otel-allocator/internal/config/flags_test.go b/cmd/otel-allocator/internal/config/flags_test.go
index f1ea0de2..5c76da9a 100644
--- a/cmd/otel-allocator/internal/config/flags_test.go
+++ b/cmd/otel-allocator/internal/config/flags_test.go
@@ -39,20 +39,26 @@ func TestFlagGetters(t *testing.T) {
 			name:          "GetKubeConfigFilePath",
 			flagArgs:      []string{"--" + kubeConfigPathFlagName, filepath.Join("~", ".kube", "config")},
 			expectedValue: filepath.Join("~", ".kube", "config"),
-			getterFunc:    func(fs *pflag.FlagSet) (interface{}, error) { return getKubeConfigFilePath(fs) },
+			getterFunc: func(fs *pflag.FlagSet) (interface{}, error) {
+				value, _, err := getKubeConfigFilePath(fs)
+				return value, err
+			},
 		},
 		{
 			name:          "GetListenAddr",
 			flagArgs:      []string{"--" + listenAddrFlagName, ":8081"},
 			expectedValue: ":8081",
-			getterFunc:    func(fs *pflag.FlagSet) (interface{}, error) { return getListenAddr(fs) },
+			getterFunc: func(fs *pflag.FlagSet) (interface{}, error) {
+				value, _, err := getListenAddr(fs)
+				return value, err
+			},
 		},
 		{
 			name:          "GetPrometheusCREnabled",
 			flagArgs:      []string{"--" + prometheusCREnabledFlagName, "true"},
 			expectedValue: true,
 			getterFunc: func(fs *pflag.FlagSet) (interface{}, error) {
-				_, value, err := getPrometheusCREnabled(fs)
+				value, _, err := getPrometheusCREnabled(fs)
 				return value, err
 			},
 		},
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-collector.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-collector.yaml
index 5db3bc0a..35568d28 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-collector.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-collector.yaml
@@ -1,22 +1,27 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: sidecar
 spec:
   mode: sidecar
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+
+    processors: {}
 
     exporters:
       debug:
+        verbosity: detailed
 
     service:
       pipelines:
         traces:
           receivers: [otlp]
           exporters: [debug]
+        metrics:
+          receivers: [otlp]
+          exporters: [debug]
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-instrumentation.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-instrumentation.yaml
index 71351ee4..312606fe 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-instrumentation.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/00-install-instrumentation.yaml
@@ -7,24 +7,15 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
   exporter:
-    endpoint: http://localhost:4317
+    endpoint: http://localhost:4318
   propagators:
     - jaeger
     - b3multi
-  sampler:
-    type: parentbased_traceidratio
-    argument: "0.25"
-  dotnet:
-    env:
-      - name: OTEL_LOG_LEVEL
-        value: "debug"
\ No newline at end of file
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-assert.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-assert.yaml
index 91ecb811..5ea35016 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-assert.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-assert.yaml
@@ -13,15 +13,15 @@ spec:
     - name: OTEL_NODE_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.hostIP
     - name: OTEL_POD_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.podIP
     - name: ASPNETCORE_URLS
       value: http://+:8080
-    - name: OTEL_LOG_LEVEL
-      value: debug
     - name: CORECLR_ENABLE_PROFILING
       value: "1"
     - name: CORECLR_PROFILER
@@ -39,13 +39,11 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
     - name: OTEL_SERVICE_NAME
@@ -64,6 +62,9 @@ spec:
       value: jaeger,b3multi
     - name: OTEL_RESOURCE_ATTRIBUTES
     name: myapp
+    ports:
+    - containerPort: 8080
+      protocol: TCP
     volumeMounts:
     - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
       readOnly: true
@@ -73,13 +74,13 @@ spec:
     - name: OTEL_NODE_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.hostIP
     - name: OTEL_POD_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.podIP
-    - name: OTEL_LOG_LEVEL
-      value: debug
     - name: CORECLR_ENABLE_PROFILING
       value: "1"
     - name: CORECLR_PROFILER
@@ -97,13 +98,11 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
     - name: OTEL_SERVICE_NAME
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-install-app.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-install-app.yaml
index 65681d5b..86407fcd 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-install-app.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/01-install-app.yaml
@@ -22,6 +22,8 @@ spec:
         fsGroup: 3000
       containers:
       - name: myapp
+        ports:
+        - containerPort: 8080
         image: ghcr.io/open-telemetry/opentelemetry-operator/e2e-test-app-dotnet:main
         securityContext:
           allowPrivilegeEscalation: false
@@ -30,6 +32,15 @@ spec:
         env:
         - name: ASPNETCORE_URLS
           value: "http://+:8080"
+        readinessProbe:
+          httpGet:
+            path: /rolldice
+            port: 8080
+            scheme: HTTP
+          initialDelaySeconds: 5
+          periodSeconds: 15
+          timeoutSeconds: 2
+          failureThreshold: 3
       - name: myrabbit
         image: rabbitmq:3
         securityContext:
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-assert.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-assert.yaml
index dfda2367..339fdb6a 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-assert.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-assert.yaml
@@ -24,15 +24,15 @@ spec:
     - name: OTEL_NODE_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.hostIP
     - name: OTEL_POD_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.podIP
     - name: ASPNETCORE_URLS
       value: http://+:8080
-    - name: OTEL_LOG_LEVEL
-      value: debug
     - name: CORECLR_ENABLE_PROFILING
       value: "1"
     - name: CORECLR_PROFILER
@@ -50,13 +50,11 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
     - name: OTEL_SERVICE_NAME
@@ -74,6 +72,10 @@ spec:
     - name: OTEL_PROPAGATORS
       value: jaeger,b3multi
     - name: OTEL_RESOURCE_ATTRIBUTES
+    name: myapp
+    ports:
+    - containerPort: 8080
+      protocol: TCP
     volumeMounts:
     - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
       readOnly: true
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-install-app.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-install-app.yaml
index d6bea125..fdef18c0 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-install-app.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/02-install-app.yaml
@@ -22,6 +22,8 @@ spec:
         fsGroup: 3000
       containers:
       - name: myapp
+        ports:
+        - containerPort: 8080
         image: ghcr.io/open-telemetry/opentelemetry-operator/e2e-test-app-dotnet:main
         securityContext:
           allowPrivilegeEscalation: false
@@ -30,6 +32,15 @@ spec:
         env:
         - name: ASPNETCORE_URLS
           value: "http://+:8080"
+        readinessProbe:
+          httpGet:
+            path: /rolldice
+            port: 8080
+            scheme: HTTP
+          initialDelaySeconds: 5
+          periodSeconds: 15
+          timeoutSeconds: 2
+          failureThreshold: 3
       - name: myrabbit
         image: rabbitmq:3
         securityContext:
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/chainsaw-test.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/chainsaw-test.yaml
index 13ff6abb..1c8e9250 100755
--- a/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/chainsaw-test.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-multicontainer/chainsaw-test.yaml
@@ -40,12 +40,197 @@ spec:
     catch:
       - podLogs:
           selector: app=my-dotnet-multi
+  - name: Make a request to the app
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet-multi
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - proxy:
+          apiVersion: v1
+          kind: Pod
+          name: ($podName)
+          namespace: ${NAMESPACE}
+          port: "8080"
+          path: /rolldice
+  - name: Wait for telemetry data
+    try:
+    - script:
+        env:
+          - name: LABEL_SELECTOR
+            value: "app=my-dotnet-multi"
+          - name: CONTAINER_NAME
+            value: "otc-container" 
+          - name: RETRY_TIMEOUT
+            value: "120"
+          - name: RETRY_SLEEP
+            value: "5"
+          - name: SEARCH_STRINGS_ENV
+            value: |
+              Name: process.runtime.dotnet.gc.collections.count
+              Description: Number of garbage collections that have occurred since process start
+        timeout: 2m
+        content: ../../test-e2e-apps/scripts/check_pod_logs.sh
+  - name: Check the instrumented app has sent the telemetry data successfully
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet-multi
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - script:
+          env:
+          - name: podName
+            value: ($podName)
+          content: |
+            #!/bin/bash
+            # set -ex
+            kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/${podName}:8888/proxy/metrics
+          outputs:
+          - name: metrics
+            value: (x_metrics_decode($stdout))
+          check:
+            ($error == null): true
+      - assert:
+          resource:
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_metric_points_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_metric_points_total'].value | [0] > `1`): true
+    catch:
+      - podLogs:
+          selector: app=my-dotnet-multi
+          container: otc-container
   - name: step-03
     try:
+    - command:
+        env:
+        - name: appnamespace
+          value: ($namespace)
+        entrypoint: kubectl
+        args:
+          - get
+          - pod
+          - -n
+          - $appnamespace
+          - -l
+          - app=my-dotnet-multi
+          - -o
+          - jsonpath={.items[0].metadata.name}
+        outputs:
+        - name: podName
+          value: ($stdout)
     - apply:
         file: 02-install-app.yaml
     - assert:
         file: 02-assert.yaml
+    - wait:
+        apiVersion: v1
+        kind: Pod
+        name: ($podName)
+        namespace: ($namespace)
+        timeout: 1m
+        for:
+          deletion: {}
+    catch:
+      - podLogs:
+          selector: app=my-dotnet-multi
+  - name: Make a request to the app
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet-multi
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - proxy:
+          apiVersion: v1
+          kind: Pod
+          name: ($podName)
+          namespace: ${NAMESPACE}
+          port: "8080"
+          path: /rolldice
+  - name: Wait for telemetry data
+    try:
+    - script:
+        env:
+          - name: LABEL_SELECTOR
+            value: "app=my-dotnet-multi"
+          - name: CONTAINER_NAME
+            value: "otc-container" 
+          - name: RETRY_TIMEOUT
+            value: "120"
+          - name: RETRY_SLEEP
+            value: "5"
+          - name: SEARCH_STRINGS_ENV
+            value: |
+              Name: process.runtime.dotnet.gc.collections.count
+              Description: Number of garbage collections that have occurred since process start
+        timeout: 2m
+        content: ../../test-e2e-apps/scripts/check_pod_logs.sh
+  - name: Check the instrumented app has sent the telemetry data successfully
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet-multi
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - script:
+          env:
+          - name: podName
+            value: ($podName)
+          content: |
+            #!/bin/bash
+            # set -ex
+            kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/${podName}:8888/proxy/metrics
+          outputs:
+          - name: metrics
+            value: (x_metrics_decode($stdout))
+          check:
+            ($error == null): true
+      - assert:
+          resource:
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_metric_points_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_metric_points_total'].value | [0] > `1`): true
     catch:
       - podLogs:
           selector: app=my-dotnet-multi
+          container: otc-container
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-collector.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-collector.yaml
index 34a26ebb..e32ff2b4 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-collector.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-collector.yaml
@@ -1,22 +1,27 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: sidecar
 spec:
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+
+    processors: {}
 
     exporters:
       debug:
+        verbosity: detailed
 
     service:
       pipelines:
         traces:
           receivers: [otlp]
           exporters: [debug]
+        metrics:
+          receivers: [otlp]
+          exporters: [debug]
   mode: sidecar
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-instrumentation.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-instrumentation.yaml
index 80ca25ca..312606fe 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-instrumentation.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-musl/00-install-instrumentation.yaml
@@ -7,20 +7,15 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
   exporter:
-    endpoint: http://localhost:4317
+    endpoint: http://localhost:4318
   propagators:
     - jaeger
     - b3multi
-  sampler:
-    type: parentbased_traceidratio
-    argument: "0.25"
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-assert.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-assert.yaml
index 08afb751..b564520e 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-assert.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-assert.yaml
@@ -3,7 +3,7 @@ kind: Pod
 metadata:
   annotations:
     instrumentation.opentelemetry.io/inject-dotnet: "true"
-    sidecar.opentelemetry.io/inject: "true"
+    instrumentation.opentelemetry.io/otel-dotnet-auto-runtime: linux-musl-x64
   labels:
     app: my-dotnet-musl
 spec:
@@ -12,10 +12,12 @@ spec:
     - name: OTEL_NODE_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.hostIP
     - name: OTEL_POD_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.podIP
     - name: ASPNETCORE_URLS
       value: http://+:8080
@@ -36,13 +38,11 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
     - name: OTEL_SERVICE_NAME
@@ -61,6 +61,9 @@ spec:
       value: jaeger,b3multi
     - name: OTEL_RESOURCE_ATTRIBUTES
     name: myapp
+    ports:
+    - containerPort: 8080
+      protocol: TCP
     volumeMounts:
     - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
       readOnly: true
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-install-app.yaml b/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-install-app.yaml
index b69d2fb3..589346e7 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-install-app.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet-musl/01-install-app.yaml
@@ -22,6 +22,8 @@ spec:
         fsGroup: 3000
       containers:
       - name: myapp
+        ports:
+        - containerPort: 8080
         image: ghcr.io/open-telemetry/opentelemetry-operator/e2e-test-app-dotnet:main
         securityContext:
           allowPrivilegeEscalation: false
@@ -30,3 +32,12 @@ spec:
         env:
         - name: ASPNETCORE_URLS
           value: "http://+:8080"
+        readinessProbe:
+          httpGet:
+            path: /rolldice
+            port: 8080
+            scheme: HTTP
+          initialDelaySeconds: 5
+          periodSeconds: 15
+          timeoutSeconds: 2
+          failureThreshold: 3
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet/00-install-collector.yaml b/tests/e2e-instrumentation/instrumentation-dotnet/00-install-collector.yaml
index 34a26ebb..e32ff2b4 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet/00-install-collector.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet/00-install-collector.yaml
@@ -1,22 +1,27 @@
-apiVersion: opentelemetry.io/v1alpha1
+apiVersion: opentelemetry.io/v1beta1
 kind: OpenTelemetryCollector
 metadata:
   name: sidecar
 spec:
-  config: |
+  config:
     receivers:
       otlp:
         protocols:
-          grpc:
-          http:
-    processors:
+          grpc: {}
+          http: {}
+
+    processors: {}
 
     exporters:
       debug:
+        verbosity: detailed
 
     service:
       pipelines:
         traces:
           receivers: [otlp]
           exporters: [debug]
+        metrics:
+          receivers: [otlp]
+          exporters: [debug]
   mode: sidecar
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet/00-install-instrumentation.yaml b/tests/e2e-instrumentation/instrumentation-dotnet/00-install-instrumentation.yaml
index 80ca25ca..312606fe 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet/00-install-instrumentation.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet/00-install-instrumentation.yaml
@@ -7,20 +7,15 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
   exporter:
-    endpoint: http://localhost:4317
+    endpoint: http://localhost:4318
   propagators:
     - jaeger
     - b3multi
-  sampler:
-    type: parentbased_traceidratio
-    argument: "0.25"
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet/01-assert.yaml b/tests/e2e-instrumentation/instrumentation-dotnet/01-assert.yaml
index 1318ded2..c0e3b79f 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet/01-assert.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet/01-assert.yaml
@@ -12,10 +12,12 @@ spec:
     - name: OTEL_NODE_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.hostIP
     - name: OTEL_POD_IP
       valueFrom:
         fieldRef:
+          apiVersion: v1
           fieldPath: status.podIP
     - name: ASPNETCORE_URLS
       value: http://+:8080
@@ -36,13 +38,11 @@ spec:
     - name: OTEL_TRACES_EXPORTER
       value: otlp
     - name: OTEL_EXPORTER_OTLP_ENDPOINT
-      value: http://localhost:4317
+      value: http://localhost:4318
     - name: OTEL_EXPORTER_OTLP_TIMEOUT
-      value: "20"
+      value: "20000"
     - name: OTEL_TRACES_SAMPLER
-      value: parentbased_traceidratio
-    - name: OTEL_TRACES_SAMPLER_ARG
-      value: "0.85"
+      value: always_on
     - name: SPLUNK_TRACE_RESPONSE_HEADER_ENABLED
       value: "true"
     - name: OTEL_SERVICE_NAME
@@ -61,6 +61,9 @@ spec:
       value: jaeger,b3multi
     - name: OTEL_RESOURCE_ATTRIBUTES
     name: myapp
+    ports:
+    - containerPort: 8080
+      protocol: TCP
     volumeMounts:
     - mountPath: /var/run/secrets/kubernetes.io/serviceaccount
       readOnly: true
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet/01-install-app.yaml b/tests/e2e-instrumentation/instrumentation-dotnet/01-install-app.yaml
index 4a80480f..33fead0a 100644
--- a/tests/e2e-instrumentation/instrumentation-dotnet/01-install-app.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet/01-install-app.yaml
@@ -21,6 +21,8 @@ spec:
         fsGroup: 3000
       containers:
       - name: myapp
+        ports:
+        - containerPort: 8080
         image: ghcr.io/open-telemetry/opentelemetry-operator/e2e-test-app-dotnet:main
         securityContext:
           allowPrivilegeEscalation: false
@@ -29,3 +31,12 @@ spec:
         env:
         - name: ASPNETCORE_URLS
           value: "http://+:8080"
+        readinessProbe:
+          httpGet:
+            path: /rolldice
+            port: 8080
+            scheme: HTTP
+          initialDelaySeconds: 5
+          periodSeconds: 15
+          timeoutSeconds: 2
+          failureThreshold: 3
diff --git a/tests/e2e-instrumentation/instrumentation-dotnet/chainsaw-test.yaml b/tests/e2e-instrumentation/instrumentation-dotnet/chainsaw-test.yaml
index bdd2fd9a..84c02ae8 100755
--- a/tests/e2e-instrumentation/instrumentation-dotnet/chainsaw-test.yaml
+++ b/tests/e2e-instrumentation/instrumentation-dotnet/chainsaw-test.yaml
@@ -38,3 +38,83 @@ spec:
     catch:
       - podLogs:
           selector: app=my-dotnet
+  - name: Make a request to the app
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - proxy:
+          apiVersion: v1
+          kind: Pod
+          name: ($podName)
+          namespace: ${NAMESPACE}
+          port: "8080"
+          path: /rolldice
+  - name: Wait for telemetry data
+    try:
+    - script:
+        env:
+          - name: LABEL_SELECTOR
+            value: "app=my-dotnet"
+          - name: CONTAINER_NAME
+            value: "otc-container" 
+          - name: RETRY_TIMEOUT
+            value: "120"
+          - name: RETRY_SLEEP
+            value: "5"
+          - name: SEARCH_STRINGS_ENV
+            value: |
+              Name: process.runtime.dotnet.gc.collections.count
+              Description: Number of garbage collections that have occurred since process start
+        timeout: 2m
+        content: ../../test-e2e-apps/scripts/check_pod_logs.sh
+  - name: Check the instrumented app has sent the telemetry data successfully
+    try:
+      - command:
+          entrypoint: kubectl
+          args:
+            - get
+            - pod
+            - -n
+            - ${NAMESPACE}
+            - -l
+            - app=my-dotnet
+            - -o
+            - jsonpath={.items[0].metadata.name}
+          outputs:
+          - name: podName
+            value: ($stdout)
+      - script:
+          env:
+          - name: podName
+            value: ($podName)
+          content: |
+            #!/bin/bash
+            # set -ex
+            kubectl get --raw /api/v1/namespaces/$NAMESPACE/pods/${podName}:8888/proxy/metrics
+          outputs:
+          - name: metrics
+            value: (x_metrics_decode($stdout))
+          check:
+            ($error == null): true
+      - assert:
+          resource:
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_spans_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_exporter_sent_metric_points_total'].value | [0] > `1`): true
+            ($metrics[?as_string(metric."__name__") == 'otelcol_receiver_accepted_metric_points_total'].value | [0] > `1`): true
+    catch:
+      - podLogs:
+          selector: app=my-dotnet
+          container: otc-container