Skip to content

Commit

Permalink
feat(injector): add k8s.namespace.name and k8s.pod.name
Browse files Browse the repository at this point in the history
  • Loading branch information
mmanciop committed Dec 3, 2024
1 parent 52a3bdf commit 793b6fe
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 41 deletions.
11 changes: 6 additions & 5 deletions helm-chart/dash0-operator/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -620,11 +620,12 @@ For example, it sets (or appends to) `NODE_OPTIONS` to activate the
[Dash0 OpenTelemetry distribution for Node.js](https://github.com/dash0hq/opentelemetry-js-distribution) to collect
tracing data from all Node.js workloads.

Additionally, the Dash0 injector will use the values of the `DASH0_POD_UID` and `DASH0_CONTAINER_NAME` environment
variables, added to the instrumented containers by the operator, to populate the resource attributes
`k8s.pod.uid` and `k8s.container.name` via the `OTEL_RESOURCE_ATTRIBUTES` environment variable.
These attributes are appended to the existing attributes specified by the original value of the
`OTEL_RESOURCE_ATTRIBUTES` environment variable, if the latter is set in the environment of the injected process.
Additionally, the Dash0 injector will use the values of the `DASH0_NAMESPACE_NAME`, `DASH0_POD_NAME`, `DASH0_POD_UID`
and `DASH0_CONTAINER_NAME` environment variables, added to the instrumented containers by the operator, to populate
the resource attributes `k8s.namespace.name`, `k8s.pod.name`, `k8s.pod.uid` and `k8s.container.name` via the
`OTEL_RESOURCE_ATTRIBUTES` environment variable. These attributes are appended to the existing attributes specified by
the original value of the `OTEL_RESOURCE_ATTRIBUTES` environment variable, if the latter is set in the environment of
the injected process.

If you are curious, the source code for the injector is open source and can be found
[here](https://github.com/dash0hq/dash0-operator/blob/main/images/instrumentation/injector/src/dash0_injector.c).
Expand Down
29 changes: 27 additions & 2 deletions images/instrumentation/injector/src/dash0_injector.c
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,9 @@
"--require " \
"/__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry"
#define OTEL_RESOURCE_ATTRIBUTES_ENV_VAR_NAME "OTEL_RESOURCE_ATTRIBUTES"
#define DASH0_NAMESPACE_NAME_ENV_VAR_NAME "DASH0_NAMESPACE_NAME"
#define DASH0_POD_UID_ENV_VAR_NAME "DASH0_POD_UID"
#define DASH0_POD_NAME_ENV_VAR_NAME "DASH0_POD_NAME"
#define DASH0_POD_CONTAINER_NAME_VAR_NAME "DASH0_CONTAINER_NAME"

extern char **__environ;
Expand Down Expand Up @@ -94,18 +96,41 @@ char val2[1012];

char *getenv(const char *name) {
char *origValue = __getenv(name);
char *podUid = __getenv(DASH0_POD_UID_ENV_VAR_NAME);
char *containerName = __getenv(DASH0_POD_CONTAINER_NAME_VAR_NAME);
int l = __strlen(name);

char *otelResourceAttributesVarName = OTEL_RESOURCE_ATTRIBUTES_ENV_VAR_NAME;
char *nodeOptionsVarName = NODE_OPTIONS_ENV_VAR_NAME;
if (__strcmp(name, otelResourceAttributesVarName) == 0) {
// If we have not calculated this env var yet
if (__strlen(val1) == 0) {
char *namespaceName = __getenv(DASH0_NAMESPACE_NAME_ENV_VAR_NAME);
char *podUid = __getenv(DASH0_POD_UID_ENV_VAR_NAME);
char *podName = __getenv(DASH0_POD_NAME_ENV_VAR_NAME);
char *containerName = __getenv(DASH0_POD_CONTAINER_NAME_VAR_NAME);

int catCount = 0;

if (namespaceName != NULL && __strlen(namespaceName) > 0) {
__strcat(val1, "k8s.namespace.name=");
__strcat(val1, namespaceName);
catCount += 1;
}

if (podName != NULL && __strlen(podName) > 0) {
if (catCount > 0) {
__strcat(val1, ",");
}

__strcat(val1, "k8s.pod.name=");
__strcat(val1, podName);
catCount += 1;
}

if (podUid != NULL && __strlen(podUid) > 0) {
if (catCount > 0) {
__strcat(val1, ",");
}

__strcat(val1, "k8s.pod.uid=");
__strcat(val1, podUid);
catCount += 1;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,9 +45,9 @@ run_test_case() {
existing_otel_resource_attributes=${5:-}
set +e
if [ "$existing_node_options_value" != "" ]; then
test_output=$(LD_PRELOAD="$injector_binary" TEST_VAR=value DASH0_POD_UID=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff DASH0_CONTAINER_NAME=test-app NODE_OPTIONS="$existing_node_options_value" OTEL_RESOURCE_ATTRIBUTES="${existing_otel_resource_attributes}" node index.js "$command")
test_output=$(LD_PRELOAD="$injector_binary" TEST_VAR=value DASH0_NAMESPACE_NAME=my-namespace DASH0_POD_NAME=my-pod DASH0_POD_UID=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff DASH0_CONTAINER_NAME=test-app NODE_OPTIONS="$existing_node_options_value" OTEL_RESOURCE_ATTRIBUTES="${existing_otel_resource_attributes}" node index.js "$command")
else
test_output=$(LD_PRELOAD="$injector_binary" TEST_VAR=value DASH0_POD_UID=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff DASH0_CONTAINER_NAME=test-app OTEL_RESOURCE_ATTRIBUTES="${existing_otel_resource_attributes}" node index.js "$command")
test_output=$(LD_PRELOAD="$injector_binary" TEST_VAR=value DASH0_NAMESPACE_NAME=my-namespace DASH0_POD_NAME=my-pod DASH0_POD_UID=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff DASH0_CONTAINER_NAME=test-app OTEL_RESOURCE_ATTRIBUTES="${existing_otel_resource_attributes}" node index.js "$command")
fi
test_exit_code=$?
set -e
Expand Down Expand Up @@ -76,8 +76,8 @@ run_test_case "getenv: overrides NODE_OPTIONS if it is not present" node_options
run_test_case "getenv: ask for NODE_OPTIONS (unset) twice" node_options_twice "NODE_OPTIONS: --require /__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry; NODE_OPTIONS: --require /__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry"
run_test_case "getenv: prepends to NODE_OPTIONS if it is present" node_options "NODE_OPTIONS: --require /__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry --no-deprecation" "--no-deprecation"
run_test_case "getenv: ask for NODE_OPTIONS (set) twice" node_options_twice "NODE_OPTIONS: --require /__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry --no-deprecation; NODE_OPTIONS: --require /__dash0__/instrumentation/node.js/node_modules/@dash0hq/opentelemetry --no-deprecation" "--no-deprecation"
run_test_case "getenv: sets k8s.pod.uid and k8s.container.name via OTEL_RESOURCE_ATTRIBUTES" otel_resource_attributes "OTEL_RESOURCE_ATTRIBUTES: k8s.pod.uid=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff,k8s.container.name=test-app" ""
run_test_case "getenv: sets k8s.pod.uid and k8s.container.name via OTEL_RESOURCE_ATTRIBUTES with pre-existing value" otel_resource_attributes "OTEL_RESOURCE_ATTRIBUTES: k8s.pod.uid=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff,k8s.container.name=test-app,foo=bar" "" "foo=bar"
run_test_case "getenv: sets k8s.pod.uid and k8s.container.name via OTEL_RESOURCE_ATTRIBUTES" otel_resource_attributes "OTEL_RESOURCE_ATTRIBUTES: k8s.namespace.name=my-namespace,k8s.pod.name=my-pod,k8s.pod.uid=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff,k8s.container.name=test-app" ""
run_test_case "getenv: sets k8s.pod.uid and k8s.container.name via OTEL_RESOURCE_ATTRIBUTES with pre-existing value" otel_resource_attributes "OTEL_RESOURCE_ATTRIBUTES: k8s.namespace.name=my-namespace,k8s.pod.name=my-pod,k8s.pod.uid=275ecb36-5aa8-4c2a-9c47-d8bb681b9aff,k8s.container.name=test-app,foo=bar" "" "foo=bar"

exit $exit_code

32 changes: 20 additions & 12 deletions internal/webhooks/instrumentation_webhook_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -196,25 +196,29 @@ var _ = Describe("The Dash0 instrumentation webhook", func() {
{
VolumeMounts: 2,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 3,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-0",
},
{
VolumeMounts: 3,
Dash0VolumeMountIdx: 2,
EnvVars: 7,
EnvVars: 9,
LdPreloadEnvVarIdx: 2,
NodeIpIdx: 3,
Dash0CollectorBaseUrlEnvVarIdx: 4,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 5,
Dash0ContainerNameEnvVarIdx: 6,
Dash0NamespaceNameEnvVarIdx: 5,
Dash0PodNameEnvVarIdx: 6,
Dash0PodUidEnvVarIdx: 7,
Dash0ContainerNameEnvVarIdx: 8,
Dash0ContainerNameEnvVarExpectedValue: "test-container-1",
},
},
Expand Down Expand Up @@ -242,27 +246,31 @@ var _ = Describe("The Dash0 instrumentation webhook", func() {
{
VolumeMounts: 2,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
LdPreloadUsesValueFrom: true,
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 3,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-0",
},
{
VolumeMounts: 3,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
LdPreloadValue: "/__dash0__/dash0_injector.so third_party_preload.so another_third_party_preload.so",
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 0,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-1",
},
},
Expand Down
34 changes: 31 additions & 3 deletions internal/workloads/workload_modifier.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ const (
envVarLdPreloadValue = "/__dash0__/dash0_injector.so"
envVarDash0CollectorBaseUrlName = "DASH0_OTEL_COLLECTOR_BASE_URL"
envVarDash0NodeIp = "DASH0_NODE_IP"
envVarDash0PodUidName = "DASH0_POD_UID"
envVarDash0NamespaceName = "DASH0_NAMESPACE_NAME"
envVarDash0PodName = "DASH0_POD_NAME"
envVarDash0PodUid = "DASH0_POD_UID"
envVarDash0ContainerName = "DASH0_CONTAINER_NAME"
)

Expand Down Expand Up @@ -282,7 +284,31 @@ func (m *ResourceModifier) addEnvironmentVariables(container *corev1.Container,
m.addOrReplaceEnvironmentVariable(
container,
corev1.EnvVar{
Name: envVarDash0PodUidName,
Name: envVarDash0NamespaceName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
)

m.addOrReplaceEnvironmentVariable(
container,
corev1.EnvVar{
Name: envVarDash0PodName,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
)

m.addOrReplaceEnvironmentVariable(
container,
corev1.EnvVar{
Name: envVarDash0PodUid,
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.uid",
Expand Down Expand Up @@ -450,7 +476,9 @@ func (m *ResourceModifier) removeEnvironmentVariables(container *corev1.Containe
m.removeLdPreload(container)
m.removeEnvironmentVariable(container, envVarDash0NodeIp)
m.removeEnvironmentVariable(container, envVarDash0CollectorBaseUrlName)
m.removeEnvironmentVariable(container, envVarDash0PodUidName)
m.removeEnvironmentVariable(container, envVarDash0NamespaceName)
m.removeEnvironmentVariable(container, envVarDash0PodName)
m.removeEnvironmentVariable(container, envVarDash0PodUid)
m.removeEnvironmentVariable(container, envVarDash0ContainerName)
}

Expand Down
36 changes: 24 additions & 12 deletions internal/workloads/workload_modifier_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -74,25 +74,29 @@ var _ = Describe("Dash0 Workload Modification", func() {
{
VolumeMounts: 2,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 3,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-0",
},
{
VolumeMounts: 3,
Dash0VolumeMountIdx: 2,
EnvVars: 7,
EnvVars: 9,
LdPreloadEnvVarIdx: 2,
NodeIpIdx: 3,
Dash0CollectorBaseUrlEnvVarIdx: 4,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 5,
Dash0ContainerNameEnvVarIdx: 6,
Dash0NamespaceNameEnvVarIdx: 5,
Dash0PodNameEnvVarIdx: 6,
Dash0PodUidEnvVarIdx: 7,
Dash0ContainerNameEnvVarIdx: 8,
Dash0ContainerNameEnvVarExpectedValue: "test-container-1",
},
},
Expand All @@ -115,27 +119,31 @@ var _ = Describe("Dash0 Workload Modification", func() {
{
VolumeMounts: 2,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
LdPreloadUsesValueFrom: true,
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 3,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-0",
},
{
VolumeMounts: 3,
Dash0VolumeMountIdx: 1,
EnvVars: 6,
EnvVars: 8,
LdPreloadEnvVarIdx: 1,
LdPreloadValue: "/__dash0__/dash0_injector.so third_party_preload.so another_third_party_preload.so",
NodeIpIdx: 2,
Dash0CollectorBaseUrlEnvVarIdx: 0,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 4,
Dash0ContainerNameEnvVarIdx: 5,
Dash0NamespaceNameEnvVarIdx: 4,
Dash0PodNameEnvVarIdx: 5,
Dash0PodUidEnvVarIdx: 6,
Dash0ContainerNameEnvVarIdx: 7,
Dash0ContainerNameEnvVarExpectedValue: "test-container-1",
},
},
Expand Down Expand Up @@ -315,6 +323,8 @@ var _ = Describe("Dash0 Workload Modification", func() {
LdPreloadEnvVarIdx: -1,
NodeIpIdx: -1,
Dash0CollectorBaseUrlEnvVarIdx: -1,
Dash0NamespaceNameEnvVarIdx: -1,
Dash0PodNameEnvVarIdx: -1,
Dash0PodUidEnvVarIdx: -1,
Dash0ContainerNameEnvVarIdx: -1,
},
Expand All @@ -325,6 +335,8 @@ var _ = Describe("Dash0 Workload Modification", func() {
LdPreloadEnvVarIdx: -1,
NodeIpIdx: -1,
Dash0CollectorBaseUrlEnvVarIdx: -1,
Dash0NamespaceNameEnvVarIdx: -1,
Dash0PodNameEnvVarIdx: -1,
Dash0PodUidEnvVarIdx: -1,
Dash0ContainerNameEnvVarIdx: -1,
},
Expand Down
16 changes: 16 additions & 0 deletions test/util/resources.go
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,22 @@ func simulateInstrumentedPodSpec(podSpec *corev1.PodSpec, meta *metav1.ObjectMet
Name: "DASH0_OTEL_COLLECTOR_BASE_URL",
Value: OTelCollectorBaseUrlTest,
},
{
Name: "DASH0_NAMESPACE_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.namespace",
},
},
},
{
Name: "DASH0_POD_NAME",
ValueFrom: &corev1.EnvVarSource{
FieldRef: &corev1.ObjectFieldSelector{
FieldPath: "metadata.name",
},
},
},
{
Name: "DASH0_POD_UID",
ValueFrom: &corev1.EnvVarSource{
Expand Down
16 changes: 13 additions & 3 deletions test/util/verification.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ type ContainerExpectations struct {
NodeIpIdx int
Dash0CollectorBaseUrlEnvVarIdx int
Dash0CollectorBaseUrlEnvVarExpectedValue string
Dash0NamespaceNameEnvVarIdx int
Dash0PodNameEnvVarIdx int
Dash0PodUidEnvVarIdx int
Dash0ContainerNameEnvVarIdx int
Dash0ContainerNameEnvVarExpectedValue string
Expand Down Expand Up @@ -75,13 +77,15 @@ func BasicInstrumentedPodSpecExpectations() PodSpecExpectations {
Containers: []ContainerExpectations{{
VolumeMounts: 1,
Dash0VolumeMountIdx: 0,
EnvVars: 5,
EnvVars: 7,
LdPreloadEnvVarIdx: 0,
NodeIpIdx: 1,
Dash0CollectorBaseUrlEnvVarIdx: 2,
Dash0CollectorBaseUrlEnvVarExpectedValue: OTelCollectorBaseUrlTest,
Dash0PodUidEnvVarIdx: 3,
Dash0ContainerNameEnvVarIdx: 4,
Dash0NamespaceNameEnvVarIdx: 3,
Dash0PodNameEnvVarIdx: 4,
Dash0PodUidEnvVarIdx: 5,
Dash0ContainerNameEnvVarIdx: 6,
Dash0ContainerNameEnvVarExpectedValue: "test-container-0",
}},
}
Expand Down Expand Up @@ -310,6 +314,12 @@ func verifyPodSpec(podSpec corev1.PodSpec, expectations PodSpecExpectations) {
Expect(envVar.Name).To(Equal("DASH0_OTEL_COLLECTOR_BASE_URL"))
Expect(envVar.Value).To(Equal(containerExpectations.Dash0CollectorBaseUrlEnvVarExpectedValue))
Expect(envVar.ValueFrom).To(BeNil())
} else if j == containerExpectations.Dash0NamespaceNameEnvVarIdx {
Expect(envVar.Name).To(Equal("DASH0_NAMESPACE_NAME"))
Expect(envVar.ValueFrom.FieldRef.FieldPath).To(Equal("metadata.namespace"))
} else if j == containerExpectations.Dash0PodNameEnvVarIdx {
Expect(envVar.Name).To(Equal("DASH0_POD_NAME"))
Expect(envVar.ValueFrom.FieldRef.FieldPath).To(Equal("metadata.name"))
} else if j == containerExpectations.Dash0PodUidEnvVarIdx {
Expect(envVar.Name).To(Equal("DASH0_POD_UID"))
Expect(envVar.ValueFrom.FieldRef.FieldPath).To(Equal("metadata.uid"))
Expand Down

0 comments on commit 793b6fe

Please sign in to comment.