Skip to content

Commit b05067f

Browse files
authored
[Resources.Azure] Add support for Container App Jobs (open-telemetry#2064)
1 parent 1139fac commit b05067f

File tree

5 files changed

+87
-23
lines changed

5 files changed

+87
-23
lines changed

src/OpenTelemetry.Resources.Azure/AzureContainerAppsResourceDetector.cs

Lines changed: 37 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,35 +10,38 @@ namespace OpenTelemetry.Resources.Azure;
1010
/// </summary>
1111
internal sealed class AzureContainerAppsResourceDetector : IResourceDetector
1212
{
13-
internal static readonly IReadOnlyDictionary<string, string> AzureContainerResourceAttributes = new Dictionary<string, string>
13+
internal static readonly IReadOnlyDictionary<string, string> AzureContainerAppResourceAttributes = new Dictionary<string, string>
1414
{
1515
{ ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar },
1616
{ ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppsRevisionEnvVar },
1717
};
1818

19+
internal static readonly IReadOnlyDictionary<string, string> AzureContainerAppJobResourceAttributes = new Dictionary<string, string>
20+
{
21+
{ ResourceSemanticConventions.AttributeServiceInstance, ResourceAttributeConstants.AzureContainerAppsReplicaNameEnvVar },
22+
{ ResourceSemanticConventions.AttributeServiceVersion, ResourceAttributeConstants.AzureContainerAppJobExecutionNameEnvVar },
23+
};
24+
1925
/// <inheritdoc/>
2026
public Resource Detect()
2127
{
22-
List<KeyValuePair<string, object>> attributeList = new();
23-
28+
List<KeyValuePair<string, object>> attributeList = new List<KeyValuePair<string, object>>();
2429
try
2530
{
2631
var containerAppName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppsNameEnvVar);
32+
var containerAppJobName = Environment.GetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar);
2733

2834
if (containerAppName != null)
2935
{
30-
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, containerAppName));
31-
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue));
32-
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureContainerAppsPlatformValue));
33-
34-
foreach (var kvp in AzureContainerResourceAttributes)
35-
{
36-
var attributeValue = Environment.GetEnvironmentVariable(kvp.Value);
37-
if (attributeValue != null)
38-
{
39-
attributeList.Add(new KeyValuePair<string, object>(kvp.Key, attributeValue));
40-
}
41-
}
36+
AddBaseAttributes(attributeList, containerAppName);
37+
38+
AddResourceAttributes(attributeList, AzureContainerAppResourceAttributes);
39+
}
40+
else if (containerAppJobName != null)
41+
{
42+
AddBaseAttributes(attributeList, containerAppJobName);
43+
44+
AddResourceAttributes(attributeList, AzureContainerAppJobResourceAttributes);
4245
}
4346
}
4447
catch
@@ -49,4 +52,23 @@ public Resource Detect()
4952

5053
return new Resource(attributeList);
5154
}
55+
56+
private static void AddResourceAttributes(List<KeyValuePair<string, object>> attributeList, IReadOnlyDictionary<string, string> resourceAttributes)
57+
{
58+
foreach (var kvp in resourceAttributes)
59+
{
60+
var attributeValue = Environment.GetEnvironmentVariable(kvp.Value);
61+
if (attributeValue != null)
62+
{
63+
attributeList.Add(new KeyValuePair<string, object>(kvp.Key, attributeValue));
64+
}
65+
}
66+
}
67+
68+
private static void AddBaseAttributes(List<KeyValuePair<string, object>> attributeList, string serviceName)
69+
{
70+
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, serviceName));
71+
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudProvider, ResourceAttributeConstants.AzureCloudProviderValue));
72+
attributeList.Add(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeCloudPlatform, ResourceAttributeConstants.AzureContainerAppsPlatformValue));
73+
}
5274
}

src/OpenTelemetry.Resources.Azure/CHANGELOG.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,9 @@
22

33
## Unreleased
44

5+
* Added support for [Azure Container Apps jobs](https://learn.microsoft.com/en-us/azure/container-apps/jobs?tabs=azure-cli).
6+
([#2064](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2064))
7+
58
* Added direct reference to `System.Text.Encodings.Web` with minimum version of
69
`4.7.2` in response to [CVE-2021-26701](https://github.com/dotnet/runtime/issues/49377).
710
([#2056](https://github.com/open-telemetry/opentelemetry-dotnet-contrib/pull/2056))

src/OpenTelemetry.Resources.Azure/README.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,9 +98,9 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder()
9898

9999
## Azure Container Apps Resource Detector
100100

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

105105
```csharp
106106
using OpenTelemetry;
@@ -122,5 +122,5 @@ using var meterProvider = Sdk.CreateMeterProviderBuilder()
122122
| cloud.platform | The cloud platform. Here, it's always "azure_container_apps". |
123123
| cloud.provider | The cloud service provider. In this context, it's always "azure". |
124124
| service.instance.id | Represents the specific instance ID of Azure Container Apps, useful in scaled-out configurations. |
125-
| service.name | The name of the Azure Container Apps. |
126-
| service.version | The current revision or version of Azure Container Apps. |
125+
| service.name | The name of the Azure Container Apps or Azure Container Apps job. |
126+
| service.version | The current revision or version of Azure Container Apps, or in case of a Azure Container Apps job - the job execution name. |

src/OpenTelemetry.Resources.Azure/ResourceAttributeConstants.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,10 @@ internal sealed class ResourceAttributeConstants
2727
internal const string AzureContainerAppsReplicaNameEnvVar = "CONTAINER_APP_REPLICA_NAME";
2828
internal const string AzureContainerAppsRevisionEnvVar = "CONTAINER_APP_REVISION";
2929

30+
// Azure Container Apps Jobs environment variables
31+
internal const string AzureContainerAppJobNameEnvVar = "CONTAINER_APP_JOB_NAME";
32+
internal const string AzureContainerAppJobExecutionNameEnvVar = "CONTAINER_APP_JOB_EXECUTION_NAME";
33+
3034
// Azure resource attributes constant values
3135
internal const string AzureAppServicePlatformValue = "azure_app_service";
3236
internal const string AzureCloudProviderValue = "azure";

test/OpenTelemetry.Resources.Azure.Tests/AzureResourceDetectorTests.cs

Lines changed: 38 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,7 @@ public void AzureContainerAppsResourceDetectorReturnsResourceWithAttributes()
9797
{
9898
try
9999
{
100-
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
100+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
101101
{
102102
Environment.SetEnvironmentVariable(kvp.Value, kvp.Key);
103103
}
@@ -113,7 +113,34 @@ public void AzureContainerAppsResourceDetectorReturnsResourceWithAttributes()
113113

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

116-
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
116+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
117+
{
118+
Assert.Contains(new KeyValuePair<string, object>(kvp.Key, kvp.Key), resource.Attributes);
119+
}
120+
}
121+
122+
[Fact]
123+
public void AzureContainerAppsJobResourceDetectorReturnsResourceWithAttributes()
124+
{
125+
try
126+
{
127+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
128+
{
129+
Environment.SetEnvironmentVariable(kvp.Value, kvp.Key);
130+
}
131+
132+
Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar, "containerAppJobName");
133+
}
134+
catch
135+
{
136+
}
137+
138+
var resource = ResourceBuilder.CreateEmpty().AddAzureContainerAppsDetector().Build();
139+
Assert.NotNull(resource);
140+
141+
Assert.Contains(new KeyValuePair<string, object>(ResourceSemanticConventions.AttributeServiceName, "containerAppJobName"), resource.Attributes);
142+
143+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
117144
{
118145
Assert.Contains(new KeyValuePair<string, object>(kvp.Key, kvp.Key), resource.Attributes);
119146
}
@@ -126,9 +153,17 @@ public void Dispose()
126153
Environment.SetEnvironmentVariable(kvp.Value, null);
127154
}
128155

129-
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerResourceAttributes)
156+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppResourceAttributes)
157+
{
158+
Environment.SetEnvironmentVariable(kvp.Value, null);
159+
}
160+
161+
foreach (var kvp in AzureContainerAppsResourceDetector.AzureContainerAppJobResourceAttributes)
130162
{
131163
Environment.SetEnvironmentVariable(kvp.Value, null);
132164
}
165+
166+
Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppsNameEnvVar, null);
167+
Environment.SetEnvironmentVariable(ResourceAttributeConstants.AzureContainerAppJobNameEnvVar, null);
133168
}
134169
}

0 commit comments

Comments
 (0)