using OpenTelemetry.Resources; using ZB.MOM.WW.Telemetry; namespace ZB.MOM.WW.Telemetry.Tests; public sealed class ZbResourceTests { [Fact] public void Build_PopulatesAllResourceAttributes() { var options = new ZbTelemetryOptions { ServiceName = "otopcua", ServiceNamespace = "ZB.MOM.WW", ServiceVersion = "1.2.3", SiteId = "site-7", NodeRole = "central", }; var resource = ZbResource.Build(options).Build(); var attributes = resource.Attributes.ToDictionary(a => a.Key, a => a.Value); Assert.Equal("otopcua", attributes["service.name"]); Assert.Equal("ZB.MOM.WW", attributes["service.namespace"]); Assert.Equal("1.2.3", attributes["service.version"]); Assert.Equal("site-7", attributes["site.id"]); Assert.Equal("central", attributes["node.role"]); Assert.Equal(Environment.MachineName, attributes["host.name"]); // service.instance.id must be the deterministic MachineName:ProcessId — NOT a random GUID. Assert.Equal(ZbResource.InstanceId, attributes["service.instance.id"]); } [Fact] public void Build_OmitsOptionalAttributes_WhenNull() { var options = new ZbTelemetryOptions { ServiceName = "mxgateway", // ServiceVersion / SiteId / NodeRole left null }; var resource = ZbResource.Build(options).Build(); var keys = resource.Attributes.Select(a => a.Key).ToHashSet(); Assert.Contains("service.name", keys); Assert.Contains("service.namespace", keys); Assert.Contains("host.name", keys); // service.instance.id is always present (deterministic, not optional). Assert.Contains("service.instance.id", keys); Assert.DoesNotContain("service.version", keys); Assert.DoesNotContain("site.id", keys); Assert.DoesNotContain("node.role", keys); } [Fact] public void InstanceId_is_deterministic_MachineName_colon_ProcessId() { // InstanceId must be stable within the process and follow the MachineName:ProcessId format. var expected = $"{Environment.MachineName}:{Environment.ProcessId}"; Assert.Equal(expected, ZbResource.InstanceId); // Calling it twice returns the same value (no random component). Assert.Equal(ZbResource.InstanceId, ZbResource.InstanceId); } [Fact] public void InstanceId_does_not_contain_a_random_guid() { // The old OTel SDK default was a random GUID; the deterministic id must NOT be a GUID. Assert.False( Guid.TryParse(ZbResource.InstanceId, out _), $"service.instance.id must not be a GUID; got '{ZbResource.InstanceId}'"); } }