Skip to content

Commit

Permalink
[Resources.Azure] Add support for Container App Jobs (#2064)
Browse files Browse the repository at this point in the history
  • Loading branch information
hansmbakker authored Sep 24, 2024
1 parent 1139fac commit b05067f
Show file tree
Hide file tree
Showing 5 changed files with 87 additions and 23 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,38 @@ namespace OpenTelemetry.Resources.Azure;
/// </summary>
internal sealed class AzureContainerAppsResourceDetector : IResourceDetector
{
internal static readonly IReadOnlyDictionary<string, string> AzureContainerResourceAttributes = new Dictionary<string, string>
internal static readonly IReadOnlyDictionary<string, string> AzureContainerAppResourceAttributes = new Dictionary<string, string>
{
{ ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar },
{ ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppsRevisionEnvVar },
};

internal static readonly IReadOnlyDictionary<string, string> AzureContainerAppJobResourceAttributes = new Dictionary<string, string>
{
{ ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar },
{ ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppJobExecutionNameEnvVar },
};

/// <inheritdoc/>
public Resource Detect()
{
List<KeyValuePair<string, object>> attributeList = new();

List<KeyValuePair<string, object>> attributeList = new List<KeyValuePair<string, object>>();
try
{
var containerAppName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppsNameEnvVar);
var containerAppJobName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar);

if (containerAppName != null)
{
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, containerAppName));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureContainerAppsPlatformValue));

foreach (var kvp in AzureContainerResourceAttributes)
{
var attributeValue = Environment.GetEnvironmentVariable(kvp.Value);
if (attributeValue != null)
{
attributeList.Add(new KeyValuePair<string, object>(kvp.Key, attributeValue));
}
}
AddBaseAttributes(attributeList, containerAppName);

AddResourceAttributes(attributeList, AzureContainerAppResourceAttributes);
}
else if (containerAppJobName != null)
{
AddBaseAttributes(attributeList, containerAppJobName);

AddResourceAttributes(attributeList, AzureContainerAppJobResourceAttributes);
}
}
catch
Expand All @@ -49,4 +52,23 @@ public Resource Detect()

return new Resource(attributeList);
}

private static void AddResourceAttributes(List<KeyValuePair<string, object>> attributeList, IReadOnlyDictionary<string, string> resourceAttributes)
{
foreach (var kvp in resourceAttributes)
{
var attributeValue = Environment.GetEnvironmentVariable(kvp.Value);
if (attributeValue != null)
{
attributeList.Add(new KeyValuePair<string, object>(kvp.Key, attributeValue));
}
}
}

private static void AddBaseAttributes(List<KeyValuePair<string, object>> attributeList, string serviceName)
{
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, serviceName));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue));
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureContainerAppsPlatformValue));
}
}
3 changes: 3 additions & 0 deletions src/OpenTelemetry.Resources.Azure/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

## Unreleased

* Added support for [Azure Container Apps jobs](https://learn.microsoft.com/en-us/azure/container-apps/jobs?tabs=azure-cli).
([#2064](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2064))

* Added direct reference to `System.Text.Encodings.Web` with minimum version of
`4.7.2` in response to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377).
([#2056](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2056))
Expand Down
10 changes: 5 additions & 5 deletions src/OpenTelemetry.Resources.Azure/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -98,9 +98,9 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder()

## Azure Container Apps Resource Detector

Adds resource attributes for the applications running in Azure Container Apps.
The following example shows how to add `AzureContainerAppsResourceDetector` to
the `ResourceBuilder`.
Adds resource attributes for the applications running in Azure Container Apps
or Azure Container App jobs. The following example shows how to add
`AzureContainerAppsResourceDetector` to the `ResourceBuilder`.

```csharp
using OpenTelemetry;
Expand All @@ -122,5 +122,5 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder()
| cloud.platform | The cloud platform. Here, it's always "azure_container_apps". |
| cloud.provider | The cloud service provider. In this context, it's always "azure". |
| service.instance.id | Represents the specific instance ID of Azure Container Apps, useful in scaled-out configurations. |
| service.name | The name of the Azure Container Apps. |
| service.version | The current revision or version of Azure Container Apps. |
| service.name | The name of the Azure Container Apps or Azure Container Apps job. |
| service.version | The current revision or version of Azure Container Apps, or in case of a Azure Container Apps job - the job execution name. |
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,10 @@ internal sealed class ResourceAttributeConstants
internal const string AzureContainerAppsReplicaNameEnvVar = "CONTAINER_APP_REPLICA_NAME";
internal const string AzureContainerAppsRevisionEnvVar = "CONTAINER_APP_REVISION";

// Azure Container Apps Jobs environment variables
internal const string AzureContainerAppJobNameEnvVar = "CONTAINER_APP_JOB_NAME";
internal const string AzureContainerAppJobExecutionNameEnvVar = "CONTAINER_APP_JOB_EXECUTION_NAME";

// Azure resource attributes constant values
internal const string AzureAppServicePlatformValue = "azure_app_service";
internal const string AzureCloudProviderValue = "azure";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ public void AzureContainerAppsResourceDetectorReturnsResourceWithAttributes()
{
try
{
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
{
Environment.SetEnvironmentVariable(kvp.Value, kvp.Key);
}
Expand All @@ -113,7 +113,34 @@ public void AzureContainerAppsResourceDetectorReturnsResourceWithAttributes()

Assert.Contains(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, "containerAppName"), resource.Attributes);

foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
{
Assert.Contains(new KeyValuePair<string, object>(kvp.Key, kvp.Key), resource.Attributes);
}
}

[Fact]
public void AzureContainerAppsJobResourceDetectorReturnsResourceWithAttributes()
{
try
{
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
{
Environment.SetEnvironmentVariable(kvp.Value, kvp.Key);
}

Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar, "containerAppJobName");
}
catch
{
}

var resource = ResourceBuilder.CreateEmpty().AddAzureContainerAppsDetector().Build();
Assert.NotNull(resource);

Assert.Contains(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, "containerAppJobName"), resource.Attributes);

foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
{
Assert.Contains(new KeyValuePair<string, object>(kvp.Key, kvp.Key), resource.Attributes);
}
Expand All @@ -126,9 +153,17 @@ public void Dispose()
Environment.SetEnvironmentVariable(kvp.Value, null);
}

foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
{
Environment.SetEnvironmentVariable(kvp.Value, null);
}

foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
{
Environment.SetEnvironmentVariable(kvp.Value, null);
}

Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppsNameEnvVar, null);
Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar, null);
}
}

0 comments on commit b05067f

Please sign in to comment.