diff --git a/src/WebJobs.Script/Diagnostics/OpenTelemetry/FunctionsResourceDetector.cs b/src/WebJobs.Script/Diagnostics/OpenTelemetry/FunctionsResourceDetector.cs index 958afe525f..8bd07d26f0 100644 --- a/src/WebJobs.Script/Diagnostics/OpenTelemetry/FunctionsResourceDetector.cs +++ b/src/WebJobs.Script/Diagnostics/OpenTelemetry/FunctionsResourceDetector.cs @@ -10,22 +10,31 @@ namespace Microsoft.Azure.WebJobs.Script.Diagnostics.OpenTelemetry { internal sealed class FunctionsResourceDetector : IResourceDetector { + private static readonly string _assemblyVersion = typeof(ScriptHost).Assembly.GetName().Version.ToString(); + private static readonly int _processId = Process.GetCurrentProcess().Id; + public Resource Detect() { List> attributeList = new(9); try { - string serviceName = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName); - string version = typeof(ScriptHost).Assembly.GetName().Version.ToString(); + // Determine service name with override hierarchy: OTEL_SERVICE_NAME > AzureWebsiteName > AssemblyName + string serviceName = GetServiceName(); + + // Determine service version with override hierarchy: OTEL_SERVICE_VERSION > AssemblyVersion + string serviceVersion = GetServiceVersion(); - attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ServiceVersion, version)); - attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AISDKPrefix, $@"{OpenTelemetryConstants.SDKPrefix}:{version}")); - attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ProcessId, Process.GetCurrentProcess().Id)); + // Add version and SDK prefix attributes + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ServiceVersion, serviceVersion)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.AISDKPrefix, $"{OpenTelemetryConstants.SDKPrefix}:{serviceVersion}")); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ProcessId, _processId)); + attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ServiceName, serviceName)); - // Add these attributes only if running in Azure. - if (!string.IsNullOrEmpty(serviceName)) + // Only add Azure-specific attributes if WEBSITE_SITE_NAME is defined + string azureWebsiteName = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName); + + if (!string.IsNullOrEmpty(azureWebsiteName)) { - attributeList.Add(new KeyValuePair(ResourceSemanticConventions.ServiceName, serviceName)); attributeList.Add(new KeyValuePair(ResourceSemanticConventions.CloudProvider, OpenTelemetryConstants.AzureCloudProviderValue)); attributeList.Add(new KeyValuePair(ResourceSemanticConventions.CloudPlatform, OpenTelemetryConstants.AzurePlatformValue)); @@ -35,7 +44,7 @@ public Resource Detect() attributeList.Add(new KeyValuePair(ResourceSemanticConventions.CloudRegion, region)); } - var azureResourceUri = GetAzureResourceURI(serviceName); + var azureResourceUri = GetAzureResourceURI(azureWebsiteName); if (azureResourceUri != null) { attributeList.Add(new KeyValuePair(ResourceSemanticConventions.CloudResourceId, azureResourceUri)); @@ -71,5 +80,31 @@ private static string GetAzureResourceURI(string websiteSiteName) return $"/subscriptions/{subscriptionId}/resourceGroups/{websiteResourceGroup}/providers/Microsoft.Web/sites/{websiteSiteName}"; } + + private static string GetServiceName() + { + // Priority: OTEL_SERVICE_NAME > AzureWebsiteName > AssemblyName + string serviceName = Environment.GetEnvironmentVariable(ResourceSemanticConventions.ServiceNameEnvVar); + if (!string.IsNullOrEmpty(serviceName)) + { + return serviceName; + } + + serviceName = Environment.GetEnvironmentVariable(EnvironmentSettingNames.AzureWebsiteName); + if (!string.IsNullOrEmpty(serviceName)) + { + return serviceName; + } + + // Fallback to assembly name + return typeof(ScriptHost).Assembly.GetName().Name; + } + + private static string GetServiceVersion() + { + // Priority: OTEL_SERVICE_VERSION > AssemblyVersion + string version = Environment.GetEnvironmentVariable(ResourceSemanticConventions.ServiceVersionEnvVar); + return !string.IsNullOrEmpty(version) ? version : _assemblyVersion; + } } } diff --git a/src/WebJobs.Script/Diagnostics/OpenTelemetry/ResourceSemanticConventions.cs b/src/WebJobs.Script/Diagnostics/OpenTelemetry/ResourceSemanticConventions.cs index c6c7eca606..d6ada0de9c 100644 --- a/src/WebJobs.Script/Diagnostics/OpenTelemetry/ResourceSemanticConventions.cs +++ b/src/WebJobs.Script/Diagnostics/OpenTelemetry/ResourceSemanticConventions.cs @@ -9,6 +9,8 @@ internal static class ResourceSemanticConventions internal const string ServiceName = "service.name"; internal const string ServiceVersion = "service.version"; internal const string ServiceInstanceId = "service.instance.id"; + internal const string ServiceNameEnvVar = "OTEL_SERVICE_NAME"; + internal const string ServiceVersionEnvVar = "OTEL_SERVICE_VERSION"; // Cloud internal const string CloudProvider = "cloud.provider";