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