From 4f1462d74ecc25203d68cc4702fda7a152c73a24 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 2 Dec 2025 09:44:57 -0800 Subject: [PATCH 1/4] Fix env var parsing spec gap for OtelEnvResourceDetector --- .../Resources/OtelEnvResourceDetector.cs | 8 ++++--- .../Resources/OtelEnvResourceDetectorTests.cs | 21 +++++++++++++++++++ 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs b/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs index 468b37ca1a9..15440aa4831 100644 --- a/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs +++ b/src/OpenTelemetry/Resources/OtelEnvResourceDetector.cs @@ -1,6 +1,7 @@ // Copyright The OpenTelemetry Authors // SPDX-License-Identifier: Apache-2.0 +using System.Net; using Microsoft.Extensions.Configuration; namespace OpenTelemetry.Resources; @@ -9,7 +10,7 @@ internal sealed class OtelEnvResourceDetector : IResourceDetector { public const string EnvVarKey = "OTEL_RESOURCE_ATTRIBUTES"; private const char AttributeListSplitter = ','; - private const char AttributeKeyValueSplitter = '='; + private static readonly char[] AttributeKeyValueSplitter = ['=']; private readonly IConfiguration configuration; @@ -38,13 +39,14 @@ private static List> ParseResourceAttributes(string string[] rawAttributes = resourceAttributes.Split(AttributeListSplitter); foreach (string rawKeyValuePair in rawAttributes) { - string[] keyValuePair = rawKeyValuePair.Split(AttributeKeyValueSplitter); + string[] keyValuePair = rawKeyValuePair.Split(AttributeKeyValueSplitter, 2); if (keyValuePair.Length != 2) { continue; } - attributes.Add(new KeyValuePair(keyValuePair[0].Trim(), keyValuePair[1].Trim())); + var value = WebUtility.UrlDecode(keyValuePair[1].Trim()); + attributes.Add(new KeyValuePair(keyValuePair[0].Trim(), value)); } return attributes; diff --git a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs index 2f2c337d67e..3dc0e774ff0 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs @@ -68,6 +68,27 @@ public void OtelEnvResource_WithEnvVar_2() Assert.Contains(new KeyValuePair("Key2", "Val2"), resource.Attributes); } + [Theory] + [InlineData("Key1=Val1%20With%20Spaces", "Key1", "Val1 With Spaces")] + [InlineData(" query= select%20*%20from%20foo ", "query", "select * from foo")] + [InlineData("raw=100%25%", "raw", "100%%")] + [InlineData("bad=%G1value=value", "bad", "%G1value=value")] + [InlineData("a=%2C%3B%3D", "a", ",;=")] + + public void OtelEnvResource_WithEnvVar_Decoding(string envVarValue, string key, string value) + { + // Arrange + Environment.SetEnvironmentVariable(OtelEnvResourceDetector.EnvVarKey, envVarValue); + var resource = new OtelEnvResourceDetector( + new ConfigurationBuilder().AddEnvironmentVariables().Build()) + .Detect(); + + // Assert + Assert.NotEqual(Resource.Empty, resource); + Assert.Single(resource.Attributes); + Assert.Contains(new KeyValuePair(key, value), resource.Attributes); + } + [Fact] public void OtelEnvResource_UsingIConfiguration() { From e412d92f7559f6f444883763faedc4d37ab3a5b4 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 2 Dec 2025 10:58:42 -0800 Subject: [PATCH 2/4] Update CHANGELOG.md --- src/OpenTelemetry/CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index c46a345cd2f..52da2f0ad0c 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -12,6 +12,9 @@ Notes](../../RELEASENOTES.md). * Added support for `Meter.TelemetrySchemaUrl` property. ([#6714](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6714)) +* Fix env var parsing spec gap for OTEL_RESOURCE_ATTRIBUTES. + ([#6737](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6737)) + ## 1.14.0 Released 2025-Nov-12 From 70796bef146362dbacbf1203b38b707256e7233b Mon Sep 17 00:00:00 2001 From: Sean Li Date: Tue, 2 Dec 2025 11:20:59 -0800 Subject: [PATCH 3/4] Update CHANGELOG --- src/OpenTelemetry/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/OpenTelemetry/CHANGELOG.md b/src/OpenTelemetry/CHANGELOG.md index 52da2f0ad0c..f6cce12eb99 100644 --- a/src/OpenTelemetry/CHANGELOG.md +++ b/src/OpenTelemetry/CHANGELOG.md @@ -12,7 +12,7 @@ Notes](../../RELEASENOTES.md). * Added support for `Meter.TelemetrySchemaUrl` property. ([#6714](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6714)) -* Fix env var parsing spec gap for OTEL_RESOURCE_ATTRIBUTES. +* Decode `value` in OTEL_RESOURCE_ATTRIBUTES environment variable. ([#6737](https://github.com/open-telemetry/opentelemetry-dotnet/pull/6737)) ## 1.14.0 From d3bda20816dd284cc66314a38e23909424a55629 Mon Sep 17 00:00:00 2001 From: Sean Li Date: Thu, 4 Dec 2025 14:57:29 -0800 Subject: [PATCH 4/4] address feedback --- .../Resources/OtelEnvResourceDetectorTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs index 3dc0e774ff0..c47bc6ea517 100644 --- a/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs +++ b/test/OpenTelemetry.Tests/Resources/OtelEnvResourceDetectorTests.cs @@ -72,9 +72,9 @@ public void OtelEnvResource_WithEnvVar_2() [InlineData("Key1=Val1%20With%20Spaces", "Key1", "Val1 With Spaces")] [InlineData(" query= select%20*%20from%20foo ", "query", "select * from foo")] [InlineData("raw=100%25%", "raw", "100%%")] - [InlineData("bad=%G1value=value", "bad", "%G1value=value")] + [InlineData("bad=%G1value", "bad", "%G1value")] [InlineData("a=%2C%3B%3D", "a", ",;=")] - + [InlineData("url=https://x.com?a=1", "url", "https://x.com?a=1")] public void OtelEnvResource_WithEnvVar_Decoding(string envVarValue, string key, string value) { // Arrange