diff --git a/src/OpenTelemetry.Resources.Host/CHANGELOG.md b/src/OpenTelemetry.Resources.Host/CHANGELOG.md index a73c10d701..e26d945f69 100644 --- a/src/OpenTelemetry.Resources.Host/CHANGELOG.md +++ b/src/OpenTelemetry.Resources.Host/CHANGELOG.md @@ -5,6 +5,10 @@ * Updated OpenTelemetry core component version(s) to `1.13.0`. ([#3158](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3158)) +* Added support for the `host.arch` resource attribute in `HostDetector` + for .NET only. + ([#3147](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/3147)) + ## 1.12.0-beta.1 Released 2025-May-06 diff --git a/src/OpenTelemetry.Resources.Host/HostDetector.cs b/src/OpenTelemetry.Resources.Host/HostDetector.cs index 1127e2037c..cfb16076ad 100644 --- a/src/OpenTelemetry.Resources.Host/HostDetector.cs +++ b/src/OpenTelemetry.Resources.Host/HostDetector.cs @@ -76,6 +76,29 @@ internal HostDetector( this.getWindowsMachineId = getWindowsMachineId; } +#if !NETFRAMEWORK + public static string? MapArchitectureToOtel(Architecture arch) + { + return arch switch + { + Architecture.X86 => "x86", + Architecture.X64 => "x64", + Architecture.Arm => "arm32", + Architecture.Arm64 => "arm64", +#if NET + Architecture.S390x => "s390x", + Architecture.Armv6 => "arm32", + Architecture.Ppc64le => "ppc64", + + // following architectures do not have a mapping in OTEL spec https://github.com/open-telemetry/semantic-conventions/blob/v1.37.0/docs/resource/host.md + Architecture.Wasm => null, + Architecture.LoongArch64 => null, +#endif + _ => null, + }; + } +#endif + /// /// Detects the resource attributes from host. /// @@ -84,10 +107,11 @@ public Resource Detect() { try { - var attributes = new List>(2) + var attributes = new List>(3) { new(HostSemanticConventions.AttributeHostName, Environment.MachineName), }; + var machineId = this.GetMachineId(); if (machineId != null && !string.IsNullOrEmpty(machineId)) @@ -95,6 +119,17 @@ public Resource Detect() attributes.Add(new(HostSemanticConventions.AttributeHostId, machineId)); } +#if !NETFRAMEWORK + var arch = MapArchitectureToOtel(RuntimeInformation.OSArchitecture); + if (arch != null) + { + attributes.Add(new(HostSemanticConventions.AttributeHostArch, arch)); + } +#endif +#if NET471_OR_GREATER +#error Architecture is available in .NET Framework 4.7.1+, enable it when we move to that as minimum supported version +#endif + return new Resource(attributes); } catch (InvalidOperationException ex) diff --git a/src/OpenTelemetry.Resources.Host/HostSemanticConventions.cs b/src/OpenTelemetry.Resources.Host/HostSemanticConventions.cs index 7f10aaa7c9..a3218c532d 100644 --- a/src/OpenTelemetry.Resources.Host/HostSemanticConventions.cs +++ b/src/OpenTelemetry.Resources.Host/HostSemanticConventions.cs @@ -7,4 +7,5 @@ internal static class HostSemanticConventions { public const string AttributeHostName = "host.name"; public const string AttributeHostId = "host.id"; + public const string AttributeHostArch = "host.arch"; } diff --git a/src/OpenTelemetry.Resources.Host/README.md b/src/OpenTelemetry.Resources.Host/README.md index a9b308cea9..585ea2f824 100644 --- a/src/OpenTelemetry.Resources.Host/README.md +++ b/src/OpenTelemetry.Resources.Host/README.md @@ -54,7 +54,10 @@ using var loggerFactory = LoggerFactory.Create(builder => The resource detectors will record the following metadata based on where your application is running: -- **HostDetector**: `host.id` (when running on non-containerized systems), `host.name`. +- **HostDetector**: + - `host.arch` (supported only on .NET), + - `host.id` (when running on non-containerized systems), + - `host.name`. ## References diff --git a/test/OpenTelemetry.Resources.Host.Tests/HostDetectorTests.cs b/test/OpenTelemetry.Resources.Host.Tests/HostDetectorTests.cs index d6c9ea9add..eecb183b2f 100644 --- a/test/OpenTelemetry.Resources.Host.Tests/HostDetectorTests.cs +++ b/test/OpenTelemetry.Resources.Host.Tests/HostDetectorTests.cs @@ -51,10 +51,20 @@ public void TestHostAttributes() var resourceAttributes = resource.Attributes.ToDictionary(x => x.Key, x => (string)x.Value); +#if NET + Assert.Equal(3, resourceAttributes.Count); +#else Assert.Equal(2, resourceAttributes.Count); +#endif Assert.NotEmpty(resourceAttributes[HostSemanticConventions.AttributeHostName]); Assert.NotEmpty(resourceAttributes[HostSemanticConventions.AttributeHostId]); +#if NET + Assert.NotEmpty(resourceAttributes["host.arch"]); +#pragma warning disable CA1308 // Normalize strings to uppercase + Assert.Equal(RuntimeInformation.ProcessArchitecture.ToString().ToLowerInvariant(), resourceAttributes["host.arch"]); +#pragma warning restore CA1308 // Normalize strings to uppercase +#endif } #if NET