Skip to content

Commit 8f86699

Browse files
authored
[SVLS-8161] Update Azure Function metadata detection logic (#7100)
* Check DD_AZURE_RESOURCE_GROUP env var when detecting resource group metadata for Azure Flex Consumption Functions * Add tests, add DD_AZURE_RESOURCE_GROUP to supported configurations * Make flex consumption function detection a function
1 parent b08f6e9 commit 8f86699

5 files changed

Lines changed: 59 additions & 5 deletions

File tree

packages/dd-trace/src/azure_metadata.js

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// Modeled after https://github.com/DataDog/libdatadog/blob/f3994857a59bb5679a65967138c5a3aec418a65f/ddcommon/src/azure_app_services.rs
44

55
const os = require('os')
6-
const { getIsAzureFunction } = require('./serverless')
6+
const { getIsAzureFunction, getIsFlexConsumptionAzureFunction } = require('./serverless')
77
const { getEnvironmentVariable, getEnvironmentVariables } = require('../../dd-trace/src/config-helper')
88

99
function extractSubscriptionID (ownerName) {
@@ -38,6 +38,7 @@ function buildMetadata () {
3838
const {
3939
COMPUTERNAME,
4040
DD_AAS_DOTNET_EXTENSION_VERSION,
41+
DD_AZURE_RESOURCE_GROUP,
4142
FUNCTIONS_EXTENSION_VERSION,
4243
FUNCTIONS_WORKER_RUNTIME,
4344
FUNCTIONS_WORKER_RUNTIME_VERSION,
@@ -56,7 +57,12 @@ function buildMetadata () {
5657
? ['functionapp', 'function']
5758
: ['app', 'app']
5859

59-
const resourceGroup = WEBSITE_RESOURCE_GROUP ?? extractResourceGroup(WEBSITE_OWNER_NAME)
60+
// Azure Functions on Flex Consumption plans require the `DD_AZURE_RESOURCE_GROUP` env var.
61+
// If this logic ever changes, update the logic in `libdatadog`, `serverless-components/src/datadog-trace-agent`,
62+
// and the serverless compat layers accordingly.
63+
const resourceGroup = getIsFlexConsumptionAzureFunction()
64+
? (DD_AZURE_RESOURCE_GROUP ?? WEBSITE_RESOURCE_GROUP ?? extractResourceGroup(WEBSITE_OWNER_NAME))
65+
: (WEBSITE_RESOURCE_GROUP ?? extractResourceGroup(WEBSITE_OWNER_NAME))
6066

6167
return trimObject({
6268
extensionVersion: DD_AAS_DOTNET_EXTENSION_VERSION,

packages/dd-trace/src/profiling/config.js

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,10 @@ const SpaceProfiler = require('./profilers/space')
1212
const EventsProfiler = require('./profilers/events')
1313
const { oomExportStrategies, snapshotKinds } = require('./constants')
1414
const { GIT_REPOSITORY_URL, GIT_COMMIT_SHA } = require('../plugins/util/tags')
15+
const { getIsAzureFunction } = require('../serverless')
1516
const { tagger } = require('./tagger')
1617
const { isFalse, isTrue } = require('../util')
17-
const { getAzureTagsFromMetadata, getAzureAppMetadata } = require('../azure_metadata')
18+
const { getAzureTagsFromMetadata, getAzureAppMetadata, getAzureFunctionMetadata } = require('../azure_metadata')
1819
const { getEnvironmentVariables } = require('../config-helper')
1920
const defaults = require('../config_defaults')
2021

@@ -73,7 +74,7 @@ class Config {
7374
tagger.parse(DD_TAGS),
7475
tagger.parse(options.tags),
7576
tagger.parse({ env, host, service, version, functionname }),
76-
getAzureTagsFromMetadata(getAzureAppMetadata())
77+
getAzureTagsFromMetadata(getIsAzureFunction() ? getAzureFunctionMetadata() : getAzureAppMetadata())
7778
)
7879

7980
// Add source code integration tags if available

packages/dd-trace/src/serverless.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,10 @@ function getIsAzureFunction () {
2121
return isAzureFunction
2222
}
2323

24+
function getIsFlexConsumptionAzureFunction () {
25+
return getIsAzureFunction() && getEnvironmentVariable('WEBSITE_SKU') === 'FlexConsumption'
26+
}
27+
2428
function isInServerlessEnvironment () {
2529
const inAWSLambda = getEnvironmentVariable('AWS_LAMBDA_FUNCTION_NAME') !== undefined
2630
const isGCPFunction = getIsGCPFunction()
@@ -32,5 +36,6 @@ function isInServerlessEnvironment () {
3236
module.exports = {
3337
getIsGCPFunction,
3438
getIsAzureFunction,
39+
getIsFlexConsumptionAzureFunction,
3540
isInServerlessEnvironment
3641
}

packages/dd-trace/src/supported-configurations.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@
3737
"DD_APPSEC_STACK_TRACE_ENABLED": ["A"],
3838
"DD_APPSEC_TRACE_RATE_LIMIT": ["A"],
3939
"DD_APPSEC_WAF_TIMEOUT": ["A"],
40+
"DD_AZURE_RESOURCE_GROUP": ["A"],
4041
"DD_CIVISIBILITY_AGENTLESS_ENABLED": ["A"],
4142
"DD_CIVISIBILITY_AGENTLESS_URL": ["A"],
4243
"DD_CIVISIBILITY_AUTO_INSTRUMENTATION_PROVIDER": ["A"],

packages/dd-trace/test/azure_metadata.spec.js

Lines changed: 42 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ const os = require('node:os')
66

77
require('./setup/core')
88

9-
const { getAzureAppMetadata, getAzureTagsFromMetadata } = require('../src/azure_metadata')
9+
const { getAzureAppMetadata, getAzureTagsFromMetadata, getAzureFunctionMetadata } = require('../src/azure_metadata')
1010

1111
describe('Azure metadata', () => {
1212
describe('for apps is', () => {
@@ -107,4 +107,45 @@ describe('Azure metadata', () => {
107107
}
108108
assert.deepStrictEqual(getAzureTagsFromMetadata(getAzureAppMetadata()), expected)
109109
})
110+
111+
it('uses DD_AZURE_RESOURCE_GROUP for Flex Consumption Azure Functions', () => {
112+
delete process.env.WEBSITE_RESOURCE_GROUP
113+
delete process.env.WEBSITE_OS
114+
delete process.env.DD_AAS_DOTNET_EXTENSION_VERSION
115+
process.env.COMPUTERNAME = 'flex_function'
116+
process.env.WEBSITE_SITE_NAME = 'flex_function_app'
117+
process.env.WEBSITE_OWNER_NAME = 'subscription_id+flex-regionwebspace'
118+
process.env.WEBSITE_INSTANCE_ID = 'instance_id'
119+
process.env.WEBSITE_SKU = 'FlexConsumption'
120+
process.env.FUNCTIONS_EXTENSION_VERSION = '4'
121+
process.env.FUNCTIONS_WORKER_RUNTIME = 'node'
122+
process.env.DD_AZURE_RESOURCE_GROUP = 'flex_resource_group'
123+
const expected = {
124+
functionRuntimeVersion: '4',
125+
instanceID: 'instance_id',
126+
instanceName: 'flex_function',
127+
operatingSystem: os.platform(),
128+
resourceGroup: 'flex_resource_group',
129+
resourceID:
130+
'/subscriptions/subscription_id/resourcegroups/flex_resource_group' +
131+
'/providers/microsoft.web/sites/flex_function_app',
132+
runtime: 'node',
133+
siteKind: 'functionapp',
134+
siteName: 'flex_function_app',
135+
siteType: 'function',
136+
subscriptionID: 'subscription_id'
137+
}
138+
assert.deepStrictEqual(getAzureFunctionMetadata(), expected)
139+
})
140+
141+
it('uses WEBSITE_RESOURCE_GROUP for non-Flex Consumption plans', () => {
142+
process.env.WEBSITE_SITE_NAME = 'regular_function_app'
143+
process.env.WEBSITE_RESOURCE_GROUP = 'regular_resource_group'
144+
process.env.WEBSITE_OWNER_NAME = 'subscription_id+extracted_group-regionwebspace'
145+
process.env.WEBSITE_SKU = 'Consumption'
146+
process.env.FUNCTIONS_EXTENSION_VERSION = '4'
147+
process.env.DD_AZURE_RESOURCE_GROUP = 'should_not_use_this'
148+
const metadata = getAzureFunctionMetadata()
149+
assert.strictEqual(metadata.resourceGroup, 'regular_resource_group')
150+
})
110151
})

0 commit comments

Comments
 (0)