From c9041770e208d1695b8c1c6cc2e7fb3e3d45947d Mon Sep 17 00:00:00 2001 From: Raphael Manke Date: Sat, 7 Mar 2026 18:22:53 +0100 Subject: [PATCH 1/5] Add cloud.account.id resource attribute to all language wrapper scripts Read the AWS account ID from the symlink written by the collector extension during registration (/tmp/.otel-aws-account-id, introduced in #2127) and append it as cloud.account.id to OTEL_RESOURCE_ATTRIBUTES in the language-specific wrapper scripts. This ensures the account ID is available as a resource attribute on telemetry produced by the language SDKs (Node.js, Java, Python, Ruby), since the wrapper scripts execute after the extension has registered and created the symlink. --- java/layer-javaagent/scripts/otel-handler | 9 +++++++++ java/layer-wrapper/scripts/otel-handler | 9 +++++++++ nodejs/packages/layer/scripts/otel-handler | 9 +++++++++ python/src/otel/otel_sdk/otel-instrument | 10 ++++++++++ ruby/src/otel/layer/otel-handler | 10 ++++++++++ 5 files changed, 47 insertions(+) diff --git a/java/layer-javaagent/scripts/otel-handler b/java/layer-javaagent/scripts/otel-handler index adb31a263e..968812a5aa 100755 --- a/java/layer-javaagent/scripts/otel-handler +++ b/java/layer-javaagent/scripts/otel-handler @@ -8,6 +8,15 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" fi +ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$ACCOUNT_ID" ]]; then + if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + fi +else + echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +fi + if [[ -z "$OTEL_PROPAGATORS" ]]; then export OTEL_PROPAGATORS="tracecontext,baggage,xray" fi diff --git a/java/layer-wrapper/scripts/otel-handler b/java/layer-wrapper/scripts/otel-handler index 0bc9d33dd6..2d42327adf 100755 --- a/java/layer-wrapper/scripts/otel-handler +++ b/java/layer-wrapper/scripts/otel-handler @@ -9,6 +9,15 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" fi +ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$ACCOUNT_ID" ]]; then + if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + fi +else + echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +fi + if [[ -z "$OTEL_PROPAGATORS" ]]; then export OTEL_PROPAGATORS="tracecontext,baggage,xray" fi diff --git a/nodejs/packages/layer/scripts/otel-handler b/nodejs/packages/layer/scripts/otel-handler index b3c615e6d3..872d533cce 100755 --- a/nodejs/packages/layer/scripts/otel-handler +++ b/nodejs/packages/layer/scripts/otel-handler @@ -12,6 +12,15 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then fi fi +ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$ACCOUNT_ID" ]]; then + if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + fi +else + echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +fi + if [[ -z "$OTEL_PROPAGATORS" ]]; then export OTEL_PROPAGATORS="tracecontext,baggage,xray" fi diff --git a/python/src/otel/otel_sdk/otel-instrument b/python/src/otel/otel_sdk/otel-instrument index 9d89c96b62..abd5ae7880 100755 --- a/python/src/otel/otel_sdk/otel-instrument +++ b/python/src/otel/otel_sdk/otel-instrument @@ -146,6 +146,16 @@ else export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES"; fi +ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [ -n "$ACCOUNT_ID" ]; then + case "$OTEL_RESOURCE_ATTRIBUTES" in + *cloud.account.id=*) ;; + *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; + esac +else + echo "otel-instrument: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +fi + # - Uses the default `OTEL_PROPAGATORS` which is set to `tracecontext,baggage` diff --git a/ruby/src/otel/layer/otel-handler b/ruby/src/otel/layer/otel-handler index a7994f48ed..cb2f9d3097 100755 --- a/ruby/src/otel/layer/otel-handler +++ b/ruby/src/otel/layer/otel-handler @@ -19,4 +19,14 @@ else export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES"; fi +ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [ -n "$ACCOUNT_ID" ]; then + case "$OTEL_RESOURCE_ATTRIBUTES" in + *cloud.account.id=*) ;; + *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; + esac +else + echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +fi + exec "$@" From 2b0137925a32a0e536483604c310742bdd19bf15 Mon Sep 17 00:00:00 2001 From: Raphael Manke Date: Sat, 7 Mar 2026 18:26:24 +0100 Subject: [PATCH 2/5] Rename ACCOUNT_ID to CLOUD_ACCOUNT_ID in wrapper scripts --- java/layer-javaagent/scripts/otel-handler | 6 +++--- java/layer-wrapper/scripts/otel-handler | 6 +++--- nodejs/packages/layer/scripts/otel-handler | 6 +++--- python/src/otel/otel_sdk/otel-instrument | 6 +++--- ruby/src/otel/layer/otel-handler | 6 +++--- 5 files changed, 15 insertions(+), 15 deletions(-) diff --git a/java/layer-javaagent/scripts/otel-handler b/java/layer-javaagent/scripts/otel-handler index 968812a5aa..1061a6f822 100755 --- a/java/layer-javaagent/scripts/otel-handler +++ b/java/layer-javaagent/scripts/otel-handler @@ -8,10 +8,10 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" fi -ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$ACCOUNT_ID" ]]; then +CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi else echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 diff --git a/java/layer-wrapper/scripts/otel-handler b/java/layer-wrapper/scripts/otel-handler index 2d42327adf..43d100c182 100755 --- a/java/layer-wrapper/scripts/otel-handler +++ b/java/layer-wrapper/scripts/otel-handler @@ -9,10 +9,10 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then export OTEL_RESOURCE_ATTRIBUTES="service.name=${AWS_LAMBDA_FUNCTION_NAME},${OTEL_RESOURCE_ATTRIBUTES}" fi -ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$ACCOUNT_ID" ]]; then +CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi else echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 diff --git a/nodejs/packages/layer/scripts/otel-handler b/nodejs/packages/layer/scripts/otel-handler index 872d533cce..2e7f033de2 100755 --- a/nodejs/packages/layer/scripts/otel-handler +++ b/nodejs/packages/layer/scripts/otel-handler @@ -12,10 +12,10 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then fi fi -ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$ACCOUNT_ID" ]]; then +CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi else echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 diff --git a/python/src/otel/otel_sdk/otel-instrument b/python/src/otel/otel_sdk/otel-instrument index abd5ae7880..e6910b6060 100755 --- a/python/src/otel/otel_sdk/otel-instrument +++ b/python/src/otel/otel_sdk/otel-instrument @@ -146,11 +146,11 @@ else export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES"; fi -ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [ -n "$ACCOUNT_ID" ]; then +CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [ -n "$CLOUD_ACCOUNT_ID" ]; then case "$OTEL_RESOURCE_ATTRIBUTES" in *cloud.account.id=*) ;; - *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; + *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; esac else echo "otel-instrument: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 diff --git a/ruby/src/otel/layer/otel-handler b/ruby/src/otel/layer/otel-handler index cb2f9d3097..10c544b55d 100755 --- a/ruby/src/otel/layer/otel-handler +++ b/ruby/src/otel/layer/otel-handler @@ -19,11 +19,11 @@ else export OTEL_RESOURCE_ATTRIBUTES="$LAMBDA_RESOURCE_ATTRIBUTES,$OTEL_RESOURCE_ATTRIBUTES"; fi -ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [ -n "$ACCOUNT_ID" ]; then +CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) +if [ -n "$CLOUD_ACCOUNT_ID" ]; then case "$OTEL_RESOURCE_ATTRIBUTES" in *cloud.account.id=*) ;; - *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; + *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; esac else echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 From acd694b83537b858be3954323b004807bec72076 Mon Sep 17 00:00:00 2001 From: Raphael Manke Date: Sat, 7 Mar 2026 19:00:53 +0100 Subject: [PATCH 3/5] Remove error log when symlink is not found --- java/layer-javaagent/scripts/otel-handler | 8 ++------ java/layer-wrapper/scripts/otel-handler | 8 ++------ nodejs/packages/layer/scripts/otel-handler | 8 ++------ python/src/otel/otel_sdk/otel-instrument | 2 -- ruby/src/otel/layer/otel-handler | 2 -- 5 files changed, 6 insertions(+), 22 deletions(-) diff --git a/java/layer-javaagent/scripts/otel-handler b/java/layer-javaagent/scripts/otel-handler index 1061a6f822..08cd69a747 100755 --- a/java/layer-javaagent/scripts/otel-handler +++ b/java/layer-javaagent/scripts/otel-handler @@ -9,12 +9,8 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then fi CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then - if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" - fi -else - echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +if [[ -n "$CLOUD_ACCOUNT_ID" && $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi if [[ -z "$OTEL_PROPAGATORS" ]]; then diff --git a/java/layer-wrapper/scripts/otel-handler b/java/layer-wrapper/scripts/otel-handler index 43d100c182..155eaef865 100755 --- a/java/layer-wrapper/scripts/otel-handler +++ b/java/layer-wrapper/scripts/otel-handler @@ -10,12 +10,8 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then fi CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then - if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" - fi -else - echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +if [[ -n "$CLOUD_ACCOUNT_ID" && $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi if [[ -z "$OTEL_PROPAGATORS" ]]; then diff --git a/nodejs/packages/layer/scripts/otel-handler b/nodejs/packages/layer/scripts/otel-handler index 2e7f033de2..32e612a1a6 100755 --- a/nodejs/packages/layer/scripts/otel-handler +++ b/nodejs/packages/layer/scripts/otel-handler @@ -13,12 +13,8 @@ if [[ $OTEL_RESOURCE_ATTRIBUTES != *"service.name="* ]]; then fi CLOUD_ACCOUNT_ID=$(readlink /tmp/.otel-aws-account-id 2>/dev/null || true) -if [[ -n "$CLOUD_ACCOUNT_ID" ]]; then - if [[ $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then - export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" - fi -else - echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 +if [[ -n "$CLOUD_ACCOUNT_ID" && $OTEL_RESOURCE_ATTRIBUTES != *"cloud.account.id="* ]]; then + export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" fi if [[ -z "$OTEL_PROPAGATORS" ]]; then diff --git a/python/src/otel/otel_sdk/otel-instrument b/python/src/otel/otel_sdk/otel-instrument index e6910b6060..90df003d30 100755 --- a/python/src/otel/otel_sdk/otel-instrument +++ b/python/src/otel/otel_sdk/otel-instrument @@ -152,8 +152,6 @@ if [ -n "$CLOUD_ACCOUNT_ID" ]; then *cloud.account.id=*) ;; *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; esac -else - echo "otel-instrument: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 fi diff --git a/ruby/src/otel/layer/otel-handler b/ruby/src/otel/layer/otel-handler index 10c544b55d..87ae1811af 100755 --- a/ruby/src/otel/layer/otel-handler +++ b/ruby/src/otel/layer/otel-handler @@ -25,8 +25,6 @@ if [ -n "$CLOUD_ACCOUNT_ID" ]; then *cloud.account.id=*) ;; *) export OTEL_RESOURCE_ATTRIBUTES="cloud.account.id=${CLOUD_ACCOUNT_ID},${OTEL_RESOURCE_ATTRIBUTES}" ;; esac -else - echo "otel-handler: ERROR: could not read cloud.account.id from symlink /tmp/.otel-aws-account-id" >&2 fi exec "$@" From 150d8d41d3920d6ea06bddca4440a15799bc47f9 Mon Sep 17 00:00:00 2001 From: Raphael Manke Date: Sat, 7 Mar 2026 19:08:56 +0100 Subject: [PATCH 4/5] Document wrapper script environment variable configuration in README --- README.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/README.md b/README.md index 5256248624..440cec3841 100644 --- a/README.md +++ b/README.md @@ -53,6 +53,23 @@ These 2 layers are meant to be used in conjunction to instrument your lambda fun To get a better understanding of the proposed design for the OpenTelemetry Lambda extension, you can see the [Design Proposal here.](docs/design_proposal.md) +## Wrapper Script Configuration + +Each language layer includes a wrapper script (`otel-handler` or `otel-instrument`) that is invoked via `AWS_LAMBDA_EXEC_WRAPPER` before the Lambda runtime starts. These scripts configure the following environment variables: + +### `OTEL_PROPAGATORS` + +If not already set, the wrapper scripts default `OTEL_PROPAGATORS` to `tracecontext,baggage,xray`. + +### `OTEL_RESOURCE_ATTRIBUTES` + +The wrapper scripts extend `OTEL_RESOURCE_ATTRIBUTES` with: + +- **`service.name`** — set to the Lambda function name (`AWS_LAMBDA_FUNCTION_NAME`) if not already present. +- **`cloud.account.id`** — the AWS account ID, read from a symlink at `/tmp/.otel-aws-account-id` that is created by the collector extension during registration (see [#2127](https://github.com/open-telemetry/opentelemetry-lambda/pull/2127)). This is added automatically when the collector layer is used alongside a language layer. If the symlink does not exist (e.g., when running without the collector layer), the attribute is silently skipped. + +User-provided values in `OTEL_RESOURCE_ATTRIBUTES` are never overwritten. + ## Features The following is a list of features provided by the OpenTelemetry layers. From 10accbc0c5cb834096c8fbad70dba23ee4e97d16 Mon Sep 17 00:00:00 2001 From: Raphael Manke Date: Sat, 7 Mar 2026 19:13:28 +0100 Subject: [PATCH 5/5] Remove link from README to fix check-links CI --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 440cec3841..7b384acd8a 100644 --- a/README.md +++ b/README.md @@ -66,7 +66,7 @@ If not already set, the wrapper scripts default `OTEL_PROPAGATORS` to `tracecont The wrapper scripts extend `OTEL_RESOURCE_ATTRIBUTES` with: - **`service.name`** — set to the Lambda function name (`AWS_LAMBDA_FUNCTION_NAME`) if not already present. -- **`cloud.account.id`** — the AWS account ID, read from a symlink at `/tmp/.otel-aws-account-id` that is created by the collector extension during registration (see [#2127](https://github.com/open-telemetry/opentelemetry-lambda/pull/2127)). This is added automatically when the collector layer is used alongside a language layer. If the symlink does not exist (e.g., when running without the collector layer), the attribute is silently skipped. +- **`cloud.account.id`** — the AWS account ID, read from a symlink at `/tmp/.otel-aws-account-id` that is created by the collector extension during registration. This is added automatically when the collector layer is used alongside a language layer. If the symlink does not exist (e.g., when running without the collector layer), the attribute is silently skipped. User-provided values in `OTEL_RESOURCE_ATTRIBUTES` are never overwritten.