Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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<KeyValuePair<string, object>> 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();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have traditionally always wanted the functions host version for this telemetry. Are we sure we want to let this be customer configurable?


attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.ServiceVersion, version));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AISDKPrefix, $@"{OpenTelemetryConstants.SDKPrefix}:{version}"));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.ProcessId, Process.GetCurrentProcess().Id));
// Add version and SDK prefix attributes
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.ServiceVersion, serviceVersion));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AISDKPrefix, $"{OpenTelemetryConstants.SDKPrefix}:{serviceVersion}"));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.ProcessId, _processId));
attributeList.Add(new KeyValuePair<string, object>(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<string, object>(ResourceSemanticConventions.ServiceName, serviceName));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.CloudProvider, OpenTelemetryConstants.AzureCloudProviderValue));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.CloudPlatform, OpenTelemetryConstants.AzurePlatformValue));

Expand All @@ -35,7 +44,7 @@ public Resource Detect()
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.CloudRegion, region));
}

var azureResourceUri = GetAzureResourceURI(serviceName);
var azureResourceUri = GetAzureResourceURI(azureWebsiteName);
if (azureResourceUri != null)
{
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.CloudResourceId, azureResourceUri));
Expand Down Expand Up @@ -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;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down
Loading