Skip to content

Commit d8a79e5

Browse files
authored
summary: Azure function support (preview) (#2724)
feat: Preview support for instrumentation of "isolated" model Azure Functions. Instrumentation is disabled by default. Please reach out to your account team if you would like to try this new feature.
1 parent cf2313d commit d8a79e5

File tree

64 files changed

+3080
-754
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

64 files changed

+3080
-754
lines changed

.github/workflows/all_solutions.yml

+10-1
Original file line numberDiff line numberDiff line change
@@ -215,7 +215,7 @@ jobs:
215215
strategy:
216216
matrix:
217217
namespace: [
218-
AgentFeatures,
218+
AgentFeatures,
219219
AgentLogs,
220220
AgentMetrics,
221221
Api,
@@ -232,6 +232,7 @@ jobs:
232232
AwsLambda.Sns,
233233
AwsLambda.Sqs,
234234
AwsLambda.WebRequest,
235+
AzureFunction,
235236
BasicInstrumentation,
236237
CatInbound,
237238
CatOutbound,
@@ -279,6 +280,8 @@ jobs:
279280
# Make this variable true to enable extra data-gathering and logging to help troubleshoot test failures, at the cost of additional time and resources
280281
enhanced_logging: false
281282
NR_DOTNET_TEST_SAVE_WORKING_DIRECTORY: 1
283+
azure_func_exe_path: C:\ProgramData\chocolatey\lib\azure-functions-core-tools\tools\func.exe
284+
NEW_RELIC_AZURE_FUNCTION_LOG_LEVEL_OVERRIDE: 1 # enables profiler debug logs when testing an azure function
282285

283286
steps:
284287
- name: Checkout
@@ -330,6 +333,12 @@ jobs:
330333
pip install aiohttp
331334
shell: powershell
332335

336+
- name: Install Azure Functions Core Tools
337+
if: matrix.namespace == 'AzureFunction'
338+
run: |
339+
choco install azure-functions-core-tools -y --params "'/x64'"
340+
shell: powershell
341+
333342
- name: Run Integration Tests
334343
run: |
335344
if ($Env:enhanced_logging -eq $True) {

FullAgent.sln

+9-1
Original file line numberDiff line numberDiff line change
@@ -149,6 +149,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Home", "src\Agent\NewRelic\
149149
{279F8AD0-C959-476F-BD58-3581D9A33238} = {279F8AD0-C959-476F-BD58-3581D9A33238}
150150
{2E6CF650-CB50-453D-830A-D00F0540FC2C} = {2E6CF650-CB50-453D-830A-D00F0540FC2C}
151151
{2FB30555-65A4-43D7-82AA-56BF203D3A96} = {2FB30555-65A4-43D7-82AA-56BF203D3A96}
152+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8} = {338AD83A-ED68-438A-8FB1-E93A3AE87EA8}
152153
{37262C22-6A3A-4AD7-AB78-3853D2B2931D} = {37262C22-6A3A-4AD7-AB78-3853D2B2931D}
153154
{3D69B4C9-FD16-461F-95AF-6FCA6EAA914E} = {3D69B4C9-FD16-461F-95AF-6FCA6EAA914E}
154155
{44434B8F-EE14-49B0-855D-6EA0B48048BF} = {44434B8F-EE14-49B0-855D-6EA0B48048BF}
@@ -214,6 +215,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSerializationHelpers.Te
214215
EndProject
215216
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AwsSdk", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\AwsSdk\AwsSdk.csproj", "{37262C22-6A3A-4AD7-AB78-3853D2B2931D}"
216217
EndProject
218+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "AzureFunction", "src\Agent\NewRelic\Agent\Extensions\Providers\Wrapper\AzureFunction\AzureFunction.csproj", "{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}"
219+
EndProject
217220
Global
218221
GlobalSection(SolutionConfigurationPlatforms) = preSolution
219222
Debug|Any CPU = Debug|Any CPU
@@ -448,6 +451,10 @@ Global
448451
{37262C22-6A3A-4AD7-AB78-3853D2B2931D}.Debug|Any CPU.Build.0 = Debug|Any CPU
449452
{37262C22-6A3A-4AD7-AB78-3853D2B2931D}.Release|Any CPU.ActiveCfg = Release|Any CPU
450453
{37262C22-6A3A-4AD7-AB78-3853D2B2931D}.Release|Any CPU.Build.0 = Release|Any CPU
454+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
455+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Debug|Any CPU.Build.0 = Debug|Any CPU
456+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Release|Any CPU.ActiveCfg = Release|Any CPU
457+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8}.Release|Any CPU.Build.0 = Release|Any CPU
451458
EndGlobalSection
452459
GlobalSection(SolutionProperties) = preSolution
453460
HideSolutionNode = FALSE
@@ -516,10 +523,11 @@ Global
516523
{173B1B8E-51D9-4639-88E9-B08065C2B47B} = {E5B988C0-5D19-407E-8210-71FFB90C579A}
517524
{DC3E4801-A54A-42A4-AC45-DBD2F0CAE438} = {E5B988C0-5D19-407E-8210-71FFB90C579A}
518525
{37262C22-6A3A-4AD7-AB78-3853D2B2931D} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A}
526+
{338AD83A-ED68-438A-8FB1-E93A3AE87EA8} = {5E86E10A-C38F-48CB-ADE9-67B22BB2F50A}
519527
EndGlobalSection
520528
GlobalSection(ExtensibilityGlobals) = postSolution
521-
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35
522529
SolutionGuid = {D8B98070-6B8E-403C-A07F-A3F2E4A3A3D0}
530+
EnterpriseLibraryConfigurationToolBinariesPath = packages\Unity.2.1.505.2\lib\NET35
523531
EndGlobalSection
524532
GlobalSection(TestCaseManagementSettings) = postSolution
525533
CategoryFile = FullAgent.vsmdi

build/ArtifactBuilder/CoreAgentComponents.cs

+2
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ protected override void CreateAgentComponents()
5858
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Bedrock.dll",
5959
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsLambda.dll",
6060
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsSdk.dll",
61+
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AzureFunction.dll",
6162
};
6263

6364
var wrapperXmls = new[]
@@ -84,6 +85,7 @@ protected override void CreateAgentComponents()
8485
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Bedrock.Instrumentation.xml",
8586
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsLambda.Instrumentation.xml",
8687
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml",
88+
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml",
8789
};
8890

8991
ExtensionXsd = $@"{SourceHomeBuilderPath}\extensions\extension.xsd";

build/ArtifactBuilder/FrameworkAgentComponents.cs

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,7 @@ protected override void CreateAgentComponents()
6565
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Kafka.dll",
6666
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Bedrock.dll",
6767
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsSdk.dll",
68+
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AzureFunction.dll",
6869
};
6970

7071
var wrapperXmls = new[]
@@ -105,6 +106,7 @@ protected override void CreateAgentComponents()
105106
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Kafka.Instrumentation.xml",
106107
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.Bedrock.Instrumentation.xml",
107108
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml",
109+
$@"{SourceHomeBuilderPath}\extensions\NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml",
108110
};
109111

110112
ExtensionXsd = $@"{SourceHomeBuilderPath}\extensions\extension.xsd";

src/Agent/MsiInstaller/Installer/Product.wxs

+14-2
Original file line numberDiff line numberDiff line change
@@ -398,6 +398,9 @@ SPDX-License-Identifier: Apache-2.0
398398
<Component Id="AwsSdkWrapperComponent" Guid="{00D58C03-D517-41CA-BBAD-DAC605EADD3E}">
399399
<File Id="AwsSdkWrapperFile" Name="NewRelic.Providers.Wrapper.AwsSdk.dll" KeyPath="yes" Source="$(var.HomeFolderPath)\extensions\NewRelic.Providers.Wrapper.AwsSdk.dll" />
400400
</Component>
401+
<Component Id="AzureFunctionWrapperComponent" Guid="{949893C5-0212-447A-88A3-DDE3638DDC6E}">
402+
<File Id="AzureFunctionWrapperFile" Name="NewRelic.Providers.Wrapper.AzureFunction.dll" KeyPath="yes" Source="$(var.HomeFolderPath)\extensions\NewRelic.Providers.Wrapper.AzureFunction.dll" />
403+
</Component>
401404
</ComponentGroup>
402405

403406
<ComponentGroup Id="CoreNewRelic.Agent.Extensions" Directory="CoreProgramFilesExtensionsFolder">
@@ -470,7 +473,10 @@ SPDX-License-Identifier: Apache-2.0
470473
<Component Id="CoreAwsSdkWrapperComponent" Guid="{7C5E31CB-BA85-4E00-BA1B-99FA0B42E414}">
471474
<File Id="CoreAwsSdkWrapperFile" Name="NewRelic.Providers.Wrapper.AwsSdk.dll" KeyPath="yes" Source="$(var.HomeFolderPath)_coreclr\extensions\NewRelic.Providers.Wrapper.AwsSdk.dll" />
472475
</Component>
473-
</ComponentGroup>
476+
<Component Id="CoreAzureFunctionWrapperComponent" Guid="{6DC23A07-4063-462E-B43A-532D6F810AFE}">
477+
<File Id="CoreAzureFunctionWrapperFile" Name="NewRelic.Providers.Wrapper.AzureFunction.dll" KeyPath="yes" Source="$(var.HomeFolderPath)_coreclr\extensions\NewRelic.Providers.Wrapper.AzureFunction.dll" />
478+
</Component>
479+
</ComponentGroup>
474480

475481
<!-- Wrapper Instrumentation Files-->
476482
<ComponentGroup Id="NewRelic.Agent.Extensions.Instrumentation" Directory="FrameworkExtensionsFolder">
@@ -582,7 +588,10 @@ SPDX-License-Identifier: Apache-2.0
582588
<Component Id="AwsSdkInstrumentationComponent" Guid="{E719FAC8-8D69-41EA-9395-B71868DA7449}">
583589
<File Id="AwsSdkInstrumentationFile" Name="NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml" KeyPath="yes" Source="$(var.HomeFolderPath)\extensions\NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml" />
584590
</Component>
585-
</ComponentGroup>
591+
<Component Id="AzureFunctionInstrumentationComponent" Guid="{0D802289-3B47-4D94-8907-285FFD2779AB}">
592+
<File Id="AzureFunctionInstrumentationFile" Name="NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml" KeyPath="yes" Source="$(var.HomeFolderPath)\extensions\NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml" />
593+
</Component>
594+
</ComponentGroup>
586595

587596
<ComponentGroup Id="CoreNewRelic.Agent.Extensions.Instrumentation" Directory="CoreExtensionsFolder">
588597
<Component Id="CoreAspNetCoreInstrumentationComponent" Guid="{E69FA7D5-DC09-4146-A77E-6EE697EF2910}">
@@ -651,6 +660,9 @@ SPDX-License-Identifier: Apache-2.0
651660
<Component Id="CoreAwsSdkInstrumentationComponent" Guid="{CAB15FAE-EF3F-4998-9376-56DA4E11BAEF}">
652661
<File Id="CoreAwsSdkInstrumentationFile" Name="NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml" KeyPath="yes" Source="$(var.HomeFolderPath)_coreclr\extensions\NewRelic.Providers.Wrapper.AwsSdk.Instrumentation.xml"/>
653662
</Component>
663+
<Component Id="CoreAzureFunctionInstrumentationComponent" Guid="{BF3BEE66-A563-4A59-ADEC-65C3381C582E}">
664+
<File Id="CoreAzureFunctionInstrumentationFile" Name="NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml" KeyPath="yes" Source="$(var.HomeFolderPath)_coreclr\extensions\NewRelic.Providers.Wrapper.AzureFunction.Instrumentation.xml"/>
665+
</Component>
654666
</ComponentGroup>
655667

656668
<!-- Extensions XSD-->

src/Agent/NewRelic/Agent/Core/AgentManager.cs

+2-1
Original file line numberDiff line numberDiff line change
@@ -284,7 +284,8 @@ private void LogInitialized()
284284
"NEW_RELIC_FORCE_NEW_TRANSACTION_ON_NEW_THREAD",
285285
"NEW_RELIC_CODE_LEVEL_METRICS_ENABLED",
286286
"NEW_RELIC_SEND_DATA_ON_EXIT",
287-
"NEW_RELIC_SEND_DATA_ON_EXIT_THRESHOLD_MS"
287+
"NEW_RELIC_SEND_DATA_ON_EXIT_THRESHOLD_MS",
288+
"NEW_RELIC_AZURE_FUNCTION_MODE_ENABLED"
288289
};
289290

290291
List<string> environmentVariablesSensitive = new List<string> {

src/Agent/NewRelic/Agent/Core/Attributes/AttributeDefinitionService.cs

+18
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ public interface IAttributeDefinitions
125125
AttributeDefinition<object, object> GetCustomAttributeForTransaction(string name);
126126

127127
AttributeDefinition<object, object> GetLambdaAttribute(string name);
128+
AttributeDefinition<object, object> GetFaasAttribute(string name);
128129

129130
AttributeDefinition<string, string> GetRequestParameterAttribute(string paramName);
130131

@@ -188,6 +189,7 @@ public AttributeDefinitions(IAttributeFilter attribFilter)
188189
private readonly ConcurrentDictionary<string, AttributeDefinition<string, string>> _requestParameterAttributes = new ConcurrentDictionary<string, AttributeDefinition<string, string>>();
189190
private readonly ConcurrentDictionary<string, AttributeDefinition<string, string>> _requestHeadersAttributes = new ConcurrentDictionary<string, AttributeDefinition<string, string>>();
190191
private readonly ConcurrentDictionary<string, AttributeDefinition<object, object>> _lambdaAttributes = new ConcurrentDictionary<string, AttributeDefinition<object, object>>();
192+
private readonly ConcurrentDictionary<string, AttributeDefinition<object, object>> _faasAttributes = new();
191193

192194
private readonly ConcurrentDictionary<TypeAttributeValue, AttributeDefinition<TypeAttributeValue, string>> _typeAttributes = new ConcurrentDictionary<TypeAttributeValue, AttributeDefinition<TypeAttributeValue, string>>();
193195

@@ -263,6 +265,22 @@ public AttributeDefinition<object, object> GetLambdaAttribute(string name)
263265
return _lambdaAttributes.GetOrAdd(name, CreateLambdaAttribute);
264266
}
265267

268+
private AttributeDefinition<object, object> CreateFaasAttribute(string attribName)
269+
{
270+
return AttributeDefinitionBuilder
271+
.Create<object, object>(attribName, AttributeClassification.Intrinsics)
272+
.AppliesTo(AttributeDestinations.TransactionTrace)
273+
.AppliesTo(AttributeDestinations.TransactionEvent)
274+
.AppliesTo(AttributeDestinations.SpanEvent)
275+
.Build(_attribFilter);
276+
}
277+
278+
public AttributeDefinition<object, object> GetFaasAttribute(string name)
279+
{
280+
return _faasAttributes.GetOrAdd(name, CreateFaasAttribute);
281+
}
282+
283+
266284
public AttributeDefinition<object, object> GetCustomAttributeForTransaction(string name)
267285
{
268286
return _trxCustomAttributes.GetOrAdd(name, CreateCustomAttributeForTransaction);

src/Agent/NewRelic/Agent/Core/Config/BootstrapConfiguration.cs

+3
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ public interface IBootstrapConfiguration
2020
ILogConfig LogConfig { get; }
2121
string ServerlessFunctionName { get; }
2222
string ServerlessFunctionVersion { get; }
23+
bool AzureFunctionModeDetected { get; }
2324
}
2425

2526
/// <summary>
@@ -130,6 +131,8 @@ public string AgentEnabledAt
130131

131132
public ILogConfig LogConfig { get; private set; }
132133

134+
public bool AzureFunctionModeDetected => ConfigLoaderHelpers.GetEnvironmentVar("FUNCTIONS_WORKER_RUNTIME") != null;
135+
133136
private bool CheckServerlessModeEnabled(configuration localConfiguration)
134137
{
135138
// We may need these later even if we don't use it now.

src/Agent/NewRelic/Agent/Core/Config/Configuration.cs

+17
Original file line numberDiff line numberDiff line change
@@ -5722,6 +5722,8 @@ public partial class configurationUtilization
57225722

57235723
private bool detectKubernetesField;
57245724

5725+
private bool detectAzureFunctionField;
5726+
57255727
private System.Nullable<int> logicalProcessorsField;
57265728

57275729
private System.Nullable<int> totalRamMibField;
@@ -5739,6 +5741,7 @@ public configurationUtilization()
57395741
this.detectPcfField = true;
57405742
this.detectDockerField = true;
57415743
this.detectKubernetesField = true;
5744+
this.detectAzureFunctionField = true;
57425745
}
57435746

57445747
[System.Xml.Serialization.XmlAttributeAttribute()]
@@ -5825,6 +5828,20 @@ public bool detectKubernetes
58255828
}
58265829
}
58275830

5831+
[System.Xml.Serialization.XmlAttributeAttribute()]
5832+
[System.ComponentModel.DefaultValueAttribute(true)]
5833+
public bool detectAzureFunction
5834+
{
5835+
get
5836+
{
5837+
return this.detectAzureFunctionField;
5838+
}
5839+
set
5840+
{
5841+
this.detectAzureFunctionField = value;
5842+
}
5843+
}
5844+
58285845
[System.Xml.Serialization.XmlAttributeAttribute()]
58295846
public int logicalProcessors
58305847
{

src/Agent/NewRelic/Agent/Core/Config/Configuration.xsd

+7
Original file line numberDiff line numberDiff line change
@@ -1962,6 +1962,13 @@
19621962
</xs:annotation>
19631963
</xs:attribute>
19641964

1965+
<xs:attribute name="detectAzureFunction" type="xs:boolean" default="true" use="optional">
1966+
<xs:annotation>
1967+
<xs:documentation>
1968+
This attribute controls whether to look for Azure Function environment variables (optional). The default is true.
1969+
</xs:documentation>
1970+
</xs:annotation>
1971+
</xs:attribute>
19651972
<xs:attribute name="logicalProcessors" type="xs:int" use="optional">
19661973
<xs:annotation>
19671974
<xs:documentation>

0 commit comments

Comments
 (0)