From a6f1834252b6e6456c60dcbd0daef38b72bdf2d9 Mon Sep 17 00:00:00 2001
From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com>
Date: Thu, 1 Aug 2024 14:17:58 -0500
Subject: [PATCH 1/4] Enable auto-instrumentation for AspNetCore lambda
functions
---
.../Providers/Wrapper/AwsLambda/Instrumentation.xml | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
index 436a2878f1..8c6b9e2a90 100644
--- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
+++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
@@ -17,5 +17,11 @@ SPDX-License-Identifier: Apache-2.0
+
+
+
+
+
+
From bc58ac761c8391917665004c20c0075f4e2ab3a5 Mon Sep 17 00:00:00 2001
From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com>
Date: Tue, 6 Aug 2024 11:52:57 -0500
Subject: [PATCH 2/4] wip- auto-instrumentation integration tests
---
.../AppLifecycleManager.cs | 5 +-
.../AspNetCoreWebApiLambdaApplication.csproj | 21 +++
.../Controllers/ValuesController.cs | 48 ++++++
.../LambdaEntryPoint.cs | 42 +++++
.../Program.cs | 97 ++++++++++++
.../Startup.cs | 45 ++++++
.../appsettings.Development.json | 5 +
.../appsettings.json | 7 +
.../aws-lambda-tools-defaults.json | 14 ++
.../serverless.template | 47 ++++++
.../RemoteApplicationFixture.cs | 6 +-
.../IntegrationTests/IntegrationTests.sln | 10 +-
...piV2ProxyRequestAutoInstrumentationTest.cs | 88 +++++++++++
...PIGatewayRequestAutoInstrumentationTest.cs | 100 ++++++++++++
...dBalancerRequestAutoInstrumentationTest.cs | 89 +++++++++++
...ambdaAutoInstrumentationTriggerFixtures.cs | 149 ++++++++++++++++++
.../LambdaSelfExecutingAssemblyFixture.cs | 6 +-
.../AwsLambda/LambdaTestToolFixture.cs | 11 +-
18 files changed, 781 insertions(+), 9 deletions(-)
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Controllers/ValuesController.cs
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/LambdaEntryPoint.cs
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Startup.cs
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.Development.json
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.json
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/aws-lambda-tools-defaults.json
create mode 100644 tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/serverless.template
create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayRequestAutoInstrumentationTest.cs
create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest.cs
create mode 100644 tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
diff --git a/tests/Agent/IntegrationTests/ApplicationHelperLibraries/ApplicationLifecycle/AppLifecycleManager.cs b/tests/Agent/IntegrationTests/ApplicationHelperLibraries/ApplicationLifecycle/AppLifecycleManager.cs
index a14d3a8e56..743a98b2e1 100644
--- a/tests/Agent/IntegrationTests/ApplicationHelperLibraries/ApplicationLifecycle/AppLifecycleManager.cs
+++ b/tests/Agent/IntegrationTests/ApplicationHelperLibraries/ApplicationLifecycle/AppLifecycleManager.cs
@@ -1,4 +1,4 @@
-// Copyright 2020 New Relic, Inc. All rights reserved.
+// Copyright 2020 New Relic, Inc. All rights reserved.
// SPDX-License-Identifier: Apache-2.0
using CommandLine;
@@ -47,7 +47,8 @@ public static string GetPortFromArgs(string[] args)
var commandLine = string.Join(" ", args);
Log($"Joined args: {commandLine}");
- Parser.Default.ParseArguments(args)
+ new Parser(with => { with.IgnoreUnknownArguments = true;})
+ .ParseArguments(args)
.WithParsed(o =>
{
portToUse = o.Port ?? DefaultPort;
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
new file mode 100644
index 0000000000..e1d3ebae26
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
@@ -0,0 +1,21 @@
+
+
+ Exe
+ net8.0
+ enable
+ true
+ Lambda
+
+ true
+
+ true
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Controllers/ValuesController.cs b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Controllers/ValuesController.cs
new file mode 100644
index 0000000000..ce27e08ac6
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Controllers/ValuesController.cs
@@ -0,0 +1,48 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using Microsoft.AspNetCore.Mvc;
+
+namespace AspNetCoreWebApiLambdaApplication.Controllers
+{
+ [Route("api/[controller]")]
+ public class ValuesController : ControllerBase
+ {
+ public ValuesController()
+ {
+
+ }
+
+ // GET api/values
+ [HttpGet]
+ public IEnumerable Get()
+ {
+ return new string[] { "value1", "value2" };
+ }
+
+ // GET api/values/5
+ [HttpGet("{id}")]
+ public string Get(int id)
+ {
+ return "value";
+ }
+
+ // POST api/values
+ [HttpPost]
+ public void Post([FromBody] string value)
+ {
+ }
+
+ // PUT api/values/5
+ [HttpPut("{id}")]
+ public void Put(int id, [FromBody] string value)
+ {
+ }
+
+ // DELETE api/values/5
+ [HttpDelete("{id}")]
+ public void Delete(int id)
+ {
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/LambdaEntryPoint.cs b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/LambdaEntryPoint.cs
new file mode 100644
index 0000000000..c562469437
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/LambdaEntryPoint.cs
@@ -0,0 +1,42 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+namespace AspNetCoreWebApiLambdaApplication
+{
+ public class APIGatewayProxyFunctionEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayProxyFunction
+ {
+ protected override void Init(IWebHostBuilder builder)
+ {
+ builder
+ .UseStartup();
+ }
+
+ protected override void Init(IHostBuilder builder)
+ {
+ }
+ }
+
+ public class ApplicationLoadBalancerFunctionEntryPoint :Amazon.Lambda.AspNetCoreServer.ApplicationLoadBalancerFunction
+ {
+ protected override void Init(IWebHostBuilder builder)
+ {
+ builder.UseStartup();
+ }
+
+ protected override void Init(IHostBuilder builder)
+ {
+ }
+ }
+
+ public class APIGatewayHttpApiV2ProxyFunctionEntryPoint : Amazon.Lambda.AspNetCoreServer.APIGatewayHttpApiV2ProxyFunction
+ {
+ protected override void Init(IWebHostBuilder builder)
+ {
+ builder.UseStartup();
+ }
+
+ protected override void Init(IHostBuilder builder)
+ {
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
new file mode 100644
index 0000000000..578d358abe
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
@@ -0,0 +1,97 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System.Diagnostics;
+using Amazon.Lambda.APIGatewayEvents;
+using Amazon.Lambda.ApplicationLoadBalancerEvents;
+using Amazon.Lambda.Core;
+using Amazon.Lambda.RuntimeSupport;
+using Amazon.Lambda.Serialization.SystemTextJson;
+using ApplicationLifecycle;
+using CommandLine;
+
+namespace AspNetCoreWebApiLambdaApplication
+{
+ internal class Program
+ {
+ private class Options
+ {
+ [Option("handler", Required = true, HelpText = "Handler function to use.")]
+ public string Handler { get; set; }
+ }
+
+ private static string _port = "";
+ private static string _handlerToInvoke = "";
+
+ private static void Main(string[] args)
+ {
+ _port = AppLifecycleManager.GetPortFromArgs(args);
+
+ _handlerToInvoke = GetHandlerFromArgs(args);
+
+ using var cancellationTokenSource = new CancellationTokenSource();
+ using var handlerWrapper = GetHandlerWrapper();
+
+ // Instantiate a LambdaBootstrap and run it.
+ // It will wait for invocations from AWS Lambda and call the handler function for each one.
+ using var bootstrap = new LambdaBootstrap(handlerWrapper);
+
+ _ = bootstrap.RunAsync(cancellationTokenSource.Token);
+
+ AppLifecycleManager.CreatePidFile();
+
+ AppLifecycleManager.WaitForTestCompletion(_port);
+
+ cancellationTokenSource.Cancel();
+ }
+
+ private static string GetHandlerFromArgs(string[] args)
+ {
+ var handler = string.Empty;
+
+ var commandLine = string.Join(" ", args);
+
+ new Parser(with => { with.IgnoreUnknownArguments = true; })
+ .ParseArguments(args)
+ .WithParsed(o =>
+ {
+ handler = o.Handler;
+ });
+
+ if (string.IsNullOrEmpty(handler))
+ throw new Exception("--handler commandline argument could not be parsed.");
+
+ return handler;
+ }
+
+ private static HandlerWrapper GetHandlerWrapper()
+ {
+ switch (_handlerToInvoke)
+ {
+ case "APIGatewayProxyFunctionEntryPoint":
+ {
+ var entryPoint = new APIGatewayProxyFunctionEntryPoint();
+ Func> handlerFunc = entryPoint.FunctionHandlerAsync;
+
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ }
+ case "ApplicationLoadBalancerFunctionEntryPoint":
+ {
+ var entryPoint = new ApplicationLoadBalancerFunctionEntryPoint();
+ Func> handlerFunc = entryPoint.FunctionHandlerAsync;
+
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ }
+ case "APIGatewayHttpApiV2ProxyFunctionEntryPoint":
+ {
+ var entryPoint = new APIGatewayHttpApiV2ProxyFunctionEntryPoint();
+ Func> handlerFunc = entryPoint.FunctionHandlerAsync;
+
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ }
+ default:
+ throw new ArgumentException("Handler not found.");
+ }
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Startup.cs b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Startup.cs
new file mode 100644
index 0000000000..2999eed427
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Startup.cs
@@ -0,0 +1,45 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+namespace AspNetCoreWebApiLambdaApplication
+{
+ public class Startup
+ {
+ public Startup(IConfiguration configuration)
+ {
+ Configuration = configuration;
+ }
+
+ public IConfiguration Configuration { get; }
+
+ // This method gets called by the runtime. Use this method to add services to the container
+ public void ConfigureServices(IServiceCollection services)
+ {
+ services.AddControllers();
+ }
+
+ // This method gets called by the runtime. Use this method to configure the HTTP request pipeline
+ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
+ {
+ if (env.IsDevelopment())
+ {
+ app.UseDeveloperExceptionPage();
+ }
+
+ //app.UseHttpsRedirection();
+
+ app.UseRouting();
+
+ //app.UseAuthorization();
+
+ app.UseEndpoints(endpoints =>
+ {
+ endpoints.MapControllers();
+ endpoints.MapGet("/", async context =>
+ {
+ await context.Response.WriteAsync("Welcome to running ASP.NET Core on AWS Lambda");
+ });
+ });
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.Development.json b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.Development.json
new file mode 100644
index 0000000000..905d15a0aa
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.Development.json
@@ -0,0 +1,5 @@
+{
+ "AWS": {
+ "Region": ""
+ }
+}
\ No newline at end of file
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.json b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.json
new file mode 100644
index 0000000000..8c4d28e044
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/appsettings.json
@@ -0,0 +1,7 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information"
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/aws-lambda-tools-defaults.json b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/aws-lambda-tools-defaults.json
new file mode 100644
index 0000000000..9858f72779
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/aws-lambda-tools-defaults.json
@@ -0,0 +1,14 @@
+{
+ "Information": [
+ "This file provides default values for the deployment wizard inside Visual Studio and the AWS Lambda commands added to the .NET Core CLI.",
+ "To learn more about the Lambda commands with the .NET Core CLI execute the following command at the command line in the project root directory.",
+ "dotnet lambda help",
+ "All the command line options for the Lambda command can be specified in this file."
+ ],
+ "profile": "",
+ "region": "",
+ "configuration": "Release",
+ "s3-prefix": "AspNetCoreWebApiLambdaApplication/",
+ "template": "serverless.template",
+ "template-parameters": ""
+}
\ No newline at end of file
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/serverless.template b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/serverless.template
new file mode 100644
index 0000000000..59ccfdfe6a
--- /dev/null
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/serverless.template
@@ -0,0 +1,47 @@
+{
+ "AWSTemplateFormatVersion": "2010-09-09",
+ "Transform": "AWS::Serverless-2016-10-31",
+ "Description": "An AWS Serverless Application that uses the ASP.NET Core framework running in Amazon Lambda.",
+ "Parameters": {},
+ "Conditions": {},
+ "Resources": {
+ "AspNetCoreFunction": {
+ "Type": "AWS::Serverless::Function",
+ "Properties": {
+ "Handler": "AspNetCoreWebApiLambdaApplication::AspNetCoreWebApiLambdaApplication.APIGatewayHttpApiV2ProxyFunctionEntryPoint::FunctionHandlerAsync",
+ "Runtime": "dotnet8",
+ "CodeUri": "",
+ "MemorySize": 512,
+ "Timeout": 30,
+ "Role": null,
+ "Policies": [
+ "AWSLambda_FullAccess"
+ ],
+ "Events": {
+ "ProxyResource": {
+ "Type": "Api",
+ "Properties": {
+ "Path": "/{proxy+}",
+ "Method": "ANY"
+ }
+ },
+ "RootResource": {
+ "Type": "Api",
+ "Properties": {
+ "Path": "/",
+ "Method": "ANY"
+ }
+ }
+ }
+ }
+ }
+ },
+ "Outputs": {
+ "ApiURL": {
+ "Description": "API endpoint URL for Prod environment",
+ "Value": {
+ "Fn::Sub": "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/"
+ }
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs
index ade1d0a527..7025b93b81 100644
--- a/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTestHelpers/RemoteServiceFixtures/RemoteApplicationFixture.cs
@@ -348,7 +348,11 @@ public virtual void Initialize()
throw new Exception(message);
}
}
-
+ catch (Exception ex)
+ {
+ TestLogger?.WriteLine("Exception occurred in Initialize: " + ex.ToString());
+ throw;
+ }
finally
{
if (AgentLogExpected)
diff --git a/tests/Agent/IntegrationTests/IntegrationTests.sln b/tests/Agent/IntegrationTests/IntegrationTests.sln
index 8a2b0522bc..5e98947bc1 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests.sln
+++ b/tests/Agent/IntegrationTests/IntegrationTests.sln
@@ -51,6 +51,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IntegrationTests", "Integra
{C4F7465E-C9E7-4087-A99B-E5CDD6182FB5} = {C4F7465E-C9E7-4087-A99B-E5CDD6182FB5}
{D2013833-D5F9-4C25-A0B3-9D7B2DFF9051} = {D2013833-D5F9-4C25-A0B3-9D7B2DFF9051}
{D203693A-F862-4598-92F2-B91C3959EDE6} = {D203693A-F862-4598-92F2-B91C3959EDE6}
+ {D7E78459-8139-4CB4-B830-E8914454CD60} = {D7E78459-8139-4CB4-B830-E8914454CD60}
{E28E36CD-A15F-4438-ADCA-40B26844592A} = {E28E36CD-A15F-4438-ADCA-40B26844592A}
{E49FCAB4-88AB-47C3-BCD1-DCE4EFE203D2} = {E49FCAB4-88AB-47C3-BCD1-DCE4EFE203D2}
{EDA8AF34-CC6C-47A6-87BF-FFE7D6DC878D} = {EDA8AF34-CC6C-47A6-87BF-FFE7D6DC878D}
@@ -183,7 +184,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSerializationHelpers",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "TestSerializationHelpers.Test", "..\Shared\TestSerializationHelpers.Test\TestSerializationHelpers.Test.csproj", "{D33E155E-C7EC-49F1-AA24-B293A74F472D}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MFALatestPackages", "SharedApplications\Common\MFALatestPackages\MFALatestPackages.csproj", "{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MFALatestPackages", "SharedApplications\Common\MFALatestPackages\MFALatestPackages.csproj", "{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspNetCoreWebApiLambdaApplication", "Applications\AspNetCoreWebApiLambdaApplication\AspNetCoreWebApiLambdaApplication.csproj", "{D7E78459-8139-4CB4-B830-E8914454CD60}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -423,6 +426,10 @@ Global
{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2}.Debug|Any CPU.Build.0 = Debug|Any CPU
{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2}.Release|Any CPU.ActiveCfg = Release|Any CPU
{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2}.Release|Any CPU.Build.0 = Release|Any CPU
+ {D7E78459-8139-4CB4-B830-E8914454CD60}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {D7E78459-8139-4CB4-B830-E8914454CD60}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {D7E78459-8139-4CB4-B830-E8914454CD60}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {D7E78459-8139-4CB4-B830-E8914454CD60}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -479,6 +486,7 @@ Global
{31DB04AF-2ED3-4379-98D7-7D02F38864F9} = {F0F6F2CE-8AE8-49E1-8EE9-A44B451EFC29}
{472F6F9A-97E9-4DC3-9D70-AE79A20FA240} = {F0F6F2CE-8AE8-49E1-8EE9-A44B451EFC29}
{78C0CA57-4E16-4E3E-B0CF-E8C9259BA1F2} = {30CF078E-E531-441E-83AB-24AB9B1C179F}
+ {D7E78459-8139-4CB4-B830-E8914454CD60} = {F0F6F2CE-8AE8-49E1-8EE9-A44B451EFC29}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {3830ABDF-4AEA-4D91-83A2-13F091D1DF5F}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
new file mode 100644
index 0000000000..91e6eb459f
--- /dev/null
+++ b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
@@ -0,0 +1,88 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NewRelic.Agent.IntegrationTestHelpers;
+using NewRelic.Agent.IntegrationTests.RemoteServiceFixtures.AwsLambda;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace NewRelic.Agent.IntegrationTests.AwsLambda.AutoInstrumentation;
+
+[NetCoreTest]
+public abstract class AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest : NewRelicIntegrationTest where T : AspNetCoreWebApiLambdaFixtureBase
+{
+ private readonly T _fixture;
+ private readonly object _expectedTransactionName;
+
+ protected AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest(T fixture, ITestOutputHelper output, string expectedTransactionName) : base(fixture)
+ {
+ _fixture = fixture;
+ _expectedTransactionName = expectedTransactionName;
+ _fixture.TestLogger = output;
+ _fixture.SetAdditionalEnvironmentVariable("NEW_RELIC_ATTRIBUTES_INCLUDE", "request.headers.*,request.parameters.*");
+ _fixture.Actions(
+ exerciseApplication: () =>
+ {
+ _fixture.EnqueueAPIGatewayHttpApiV2ProxyRequest();
+ _fixture.AgentLog.WaitForLogLines(AgentLogBase.ServerlessPayloadLogLineRegex, TimeSpan.FromMinutes(1), 1);
+ }
+ );
+ _fixture.Initialize();
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var serverlessPayloads = _fixture.AgentLog.GetServerlessPayloads().ToList();
+
+ Assert.Multiple(
+ () => Assert.Single(serverlessPayloads),
+ () => ValidateServerlessPayload(serverlessPayloads[0])
+ );
+ }
+
+ private void ValidateServerlessPayload(ServerlessPayload serverlessPayload)
+ {
+ var transactionEvent = serverlessPayload.Telemetry.TransactionEventsPayload.TransactionEvents.Single();
+
+ var expectedAgentAttributes = new[]
+ {
+ "aws.lambda.arn",
+ "aws.requestId",
+ "host.displayName"
+ };
+
+ var expectedAgentAttributeValues = new Dictionary
+ {
+ { "aws.lambda.eventSource.accountId", "123456789012" },
+ { "aws.lambda.eventSource.apiId", "api-id" },
+ { "aws.lambda.eventSource.eventType", "apiGateway" },
+ { "aws.lambda.eventSource.stage", "$default" },
+ { "request.headers.header1", "value1" },
+ { "request.headers.header2", "value1,value2" },
+ { "request.method", "GET" },
+ { "request.uri", "/api.values" },
+ { "request.parameters.parameter1", "value1,value2" },
+ { "request.parameters.parameter2", "value" },
+ { "http.statusCode", 200 },
+ { "response.status", "200" },
+ };
+
+ Assert.Equal(_expectedTransactionName, transactionEvent.IntrinsicAttributes["name"]);
+
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributes, TransactionEventAttributeType.Agent, transactionEvent);
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributeValues, TransactionEventAttributeType.Agent, transactionEvent);
+ }
+}
+
+public class AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTestTestNet8 : AwsLambdaAPIGatewayRequestAutoInstrumentationTest
+{
+ public AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTestTestNet8(LambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTriggerFixtureNet8 fixture, ITestOutputHelper output)
+ : base(fixture, output, "WebTransaction/MVC/Values/Get")
+ {
+ }
+}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayRequestAutoInstrumentationTest.cs b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayRequestAutoInstrumentationTest.cs
new file mode 100644
index 0000000000..5e332ec49a
--- /dev/null
+++ b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayRequestAutoInstrumentationTest.cs
@@ -0,0 +1,100 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NewRelic.Agent.IntegrationTestHelpers;
+using NewRelic.Agent.IntegrationTests.RemoteServiceFixtures.AwsLambda;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace NewRelic.Agent.IntegrationTests.AwsLambda.AutoInstrumentation;
+
+[NetCoreTest]
+public abstract class AwsLambdaAPIGatewayRequestAutoInstrumentationTest : NewRelicIntegrationTest where T : AspNetCoreWebApiLambdaFixtureBase
+{
+ private readonly T _fixture;
+ private readonly object _expectedTransactionName;
+
+ protected AwsLambdaAPIGatewayRequestAutoInstrumentationTest(T fixture, ITestOutputHelper output, string expectedTransactionName) : base(fixture)
+ {
+ _fixture = fixture;
+ _expectedTransactionName = expectedTransactionName;
+ _fixture.TestLogger = output;
+ _fixture.SetAdditionalEnvironmentVariable("NEW_RELIC_ATTRIBUTES_INCLUDE", "request.headers.*,request.parameters.*");
+ _fixture.Actions(
+ exerciseApplication: () =>
+ {
+ _fixture.EnqueueAPIGatewayProxyRequest();
+ _fixture.AgentLog.WaitForLogLines(AgentLogBase.ServerlessPayloadLogLineRegex, TimeSpan.FromMinutes(1), 1);
+ }
+ );
+ _fixture.Initialize();
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var serverlessPayloads = _fixture.AgentLog.GetServerlessPayloads().ToList();
+
+ Assert.Multiple(
+ () => Assert.Single(serverlessPayloads),
+ () => ValidateServerlessPayload(serverlessPayloads[0])
+ );
+ }
+
+ private void ValidateServerlessPayload(ServerlessPayload serverlessPayload)
+ {
+ var transactionEvent = serverlessPayload.Telemetry.TransactionEventsPayload.TransactionEvents.Single();
+
+ var expectedAgentAttributes = new[]
+ {
+ "aws.lambda.arn",
+ "aws.requestId",
+ "host.displayName"
+ };
+
+ var expectedAgentAttributeValues = new Dictionary
+ {
+ { "aws.lambda.eventSource.accountId", "123456789012" },
+ { "aws.lambda.eventSource.apiId", "1234567890" },
+ { "aws.lambda.eventSource.eventType", "apiGateway" },
+ { "aws.lambda.eventSource.resourceId", "123456" },
+ { "aws.lambda.eventSource.resourcePath", "/{proxy+}" },
+ { "aws.lambda.eventSource.stage", "prod" },
+ {"request.headers.accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" },
+ {"request.headers.accept-encoding", "gzip, deflate, sdch" },
+ {"request.headers.accept-language", "en-US,en;q=0.8" },
+ {"request.headers.cache-control", "max-age=0" },
+ {"request.headers.cloudfront-forwarded-proto", "https" },
+ {"request.headers.cloudfront-is-desktop-viewer", "true" },
+ {"request.headers.cloudfront-is-mobile-viewer", "false" },
+ {"request.headers.cloudfront-is-smarttv-viewer", "false" },
+ {"request.headers.cloudfront-is-tablet-viewer", "false" },
+ {"request.headers.cloudfront-viewer-country", "US" },
+ {"request.headers.host", "1234567890.execute-api.{dns_suffix}" },
+ {"request.headers.upgrade-insecure-requests", "1" },
+ {"request.headers.user-agent", "Custom User Agent String" },
+ {"request.headers.via", "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)" },
+ {"request.method", "GET" },
+ {"request.uri", "/api/values" },
+ { "http.statusCode", 200 },
+ { "response.status", "200" },
+ };
+
+ Assert.Equal(_expectedTransactionName, transactionEvent.IntrinsicAttributes["name"]);
+
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributes, TransactionEventAttributeType.Agent, transactionEvent);
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributeValues, TransactionEventAttributeType.Agent, transactionEvent);
+ }
+}
+
+public class AwsLambdaAPIGatewayRequestAutoInstrumentationTestTestNet8 : AwsLambdaAPIGatewayRequestAutoInstrumentationTest
+{
+ public AwsLambdaAPIGatewayRequestAutoInstrumentationTestTestNet8(LambdaAPIGatewayProxyRequestAutoInstrumentationTriggerFixtureNet8 fixture, ITestOutputHelper output)
+ : base(fixture, output, "WebTransaction/MVC/Values/Get")
+ {
+ }
+}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest.cs b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest.cs
new file mode 100644
index 0000000000..e7b9764c12
--- /dev/null
+++ b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest.cs
@@ -0,0 +1,89 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using NewRelic.Agent.IntegrationTestHelpers;
+using NewRelic.Agent.IntegrationTests.RemoteServiceFixtures.AwsLambda;
+using NewRelic.Agent.Tests.TestSerializationHelpers.Models;
+using Xunit;
+using Xunit.Abstractions;
+
+namespace NewRelic.Agent.IntegrationTests.AwsLambda.AutoInstrumentation;
+
+[NetCoreTest]
+public abstract class AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest : NewRelicIntegrationTest where T : AspNetCoreWebApiLambdaFixtureBase
+{
+ private readonly T _fixture;
+ private readonly object _expectedTransactionName;
+
+ protected AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest(T fixture, ITestOutputHelper output, string expectedTransactionName) : base(fixture)
+ {
+ _fixture = fixture;
+ _expectedTransactionName = expectedTransactionName;
+ _fixture.TestLogger = output;
+ _fixture.SetAdditionalEnvironmentVariable("NEW_RELIC_ATTRIBUTES_INCLUDE", "request.headers.*,request.parameters.*");
+ _fixture.Actions(
+ exerciseApplication: () =>
+ {
+ _fixture.EnqueueApplicationLoadBalancerRequest();
+ _fixture.AgentLog.WaitForLogLines(AgentLogBase.ServerlessPayloadLogLineRegex, TimeSpan.FromMinutes(1), 1);
+ }
+ );
+ _fixture.Initialize();
+ }
+
+ [Fact]
+ public void Test()
+ {
+ var serverlessPayloads = _fixture.AgentLog.GetServerlessPayloads().ToList();
+
+ Assert.Multiple(
+ () => Assert.Single(serverlessPayloads),
+ () => ValidateServerlessPayload(serverlessPayloads[0])
+ );
+ }
+
+ private void ValidateServerlessPayload(ServerlessPayload serverlessPayload)
+ {
+ var transactionEvent = serverlessPayload.Telemetry.TransactionEventsPayload.TransactionEvents.Single();
+
+ var expectedAgentAttributes = new[]
+ {
+ "aws.lambda.arn",
+ "aws.requestId",
+ "host.displayName"
+ };
+
+ var expectedAgentAttributeValues = new Dictionary
+ {
+ { "aws.lambda.eventSource.eventType", "alb" },
+ { "aws.lambda.eventSource.arn", "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"},
+ { "request.headers.accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8" },
+ { "request.headers.accept-encoding", "gzip" },
+ { "request.headers.accept-language", "en-US,en;q=0.9" },
+ { "request.headers.connection", "keep-alive" },
+ { "request.headers.host", "lambda-alb-123578498.us-east-2.elb.amazonaws.com" },
+ { "request.headers.upgrade-insecure-requests", "1" },
+ { "request.headers.user-agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36" },
+ { "request.method", "GET" },
+ { "request.uri", "/api/values" },
+ { "http.statusCode", 200 },
+ { "response.status", "200" },
+ };
+
+ Assert.Equal(_expectedTransactionName, transactionEvent.IntrinsicAttributes["name"]);
+
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributes, TransactionEventAttributeType.Agent, transactionEvent);
+ Assertions.TransactionEventHasAttributes(expectedAgentAttributeValues, TransactionEventAttributeType.Agent, transactionEvent);
+ }
+}
+
+public class AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTestTestNet8 : AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTest
+{
+ public AwsLambdaApplicationLoadBalancerRequestAutoInstrumentationTestTestNet8(LambdaApplicationLoadBalancerRequestAutoInstrumentationTriggerFixtureNet8 fixture, ITestOutputHelper output)
+ : base(fixture, output, "WebTransaction/MVC/Values/Get")
+ {
+ }
+}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
new file mode 100644
index 0000000000..c144c8cc27
--- /dev/null
+++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
@@ -0,0 +1,149 @@
+// Copyright 2020 New Relic, Inc. All rights reserved.
+// SPDX-License-Identifier: Apache-2.0
+
+using NewRelic.Agent.IntegrationTestHelpers.RemoteServiceFixtures;
+
+namespace NewRelic.Agent.IntegrationTests.RemoteServiceFixtures.AwsLambda
+{
+ public abstract class AspNetCoreWebApiLambdaFixtureBase : LambdaTestToolFixture
+ {
+ protected AspNetCoreWebApiLambdaFixtureBase(string targetFramework) :
+ base(new RemoteService("AspNetCoreWebApiLambdaApplication", "AspNetCoreWebApiLambdaApplication.exe", targetFramework, ApplicationType.Bounded, createsPidFile: true, isCoreApp: true, publishApp: true),
+ "",
+ "AspNetCoreWebApiLambdaApplication::AspNetCoreWebApiLambdaApplication.LambdaEntryPoint::FunctionHandlerAsync",
+ "AspNetCoreWebApiLambda",
+ "latest",
+ "aspnetcore",
+ false)
+ {
+
+ }
+
+ public void EnqueueAPIGatewayProxyRequest()
+ {
+ var apiGatewayProxyRequestJson = $$"""
+ {
+ "path": "/api/values",
+ "httpMethod": "GET",
+ "headers": {
+ "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
+ "Accept-Encoding": "gzip, deflate, sdch",
+ "Accept-Language": "en-US,en;q=0.8",
+ "Cache-Control": "max-age=0",
+ "CloudFront-Forwarded-Proto": "https",
+ "CloudFront-Is-Desktop-Viewer": "true",
+ "CloudFront-Is-Mobile-Viewer": "false",
+ "CloudFront-Is-SmartTV-Viewer": "false",
+ "CloudFront-Is-Tablet-Viewer": "false",
+ "CloudFront-Viewer-Country": "US",
+ "Host": "1234567890.execute-api.{dns_suffix}",
+ "Upgrade-Insecure-Requests": "1",
+ "User-Agent": "Custom User Agent String",
+ "Via": "1.1 08f323deadbeefa7af34d5feb414ce27.cloudfront.net (CloudFront)",
+ "X-Amz-Cf-Id": "cDehVQoZnx43VYQb9j2-nvCh-9z396Uhbp027Y2JvkCPNLmGJHqlaA==",
+ "X-Forwarded-For": "127.0.0.1, 127.0.0.2",
+ "X-Forwarded-Port": "443",
+ "X-Forwarded-Proto": "https"
+ },
+ "requestContext": {
+ "accountId": "123456789012",
+ "resourceId": "123456",
+ "stage": "prod",
+ "requestId": "c6af9ac6-7b61-11e6-9a41-93e8deadbeef",
+ "identity": {
+ "cognitoIdentityPoolId": null,
+ "accountId": null,
+ "cognitoIdentityId": null,
+ "caller": null,
+ "apiKey": null,
+ "sourceIp": "127.0.0.1",
+ "cognitoAuthenticationType": null,
+ "cognitoAuthenticationProvider": null,
+ "userArn": null,
+ "userAgent": "Custom User Agent String",
+ "user": null
+ },
+ "resourcePath": "/{proxy+}",
+ "httpMethod": "GET",
+ "apiId": "1234567890"
+ }
+ }
+ """;
+ EnqueueLambdaEvent(apiGatewayProxyRequestJson);
+ }
+
+ public void EnqueueAPIGatewayHttpApiV2ProxyRequest()
+ {
+ var apiGatewayProxyRequestJson = $$"""
+ {
+ "version": "2.0",
+ "routeKey": "$default",
+ "rawPath": "/",
+ "requestContext": {
+ "http": {
+ "method": "GET",
+ "path": "/"
+ }
+ }
+ }
+ """;
+
+ EnqueueLambdaEvent(apiGatewayProxyRequestJson);
+ }
+
+ public void EnqueueApplicationLoadBalancerRequest()
+ {
+ var ApplicationLoadBalancerRequestJson = $$"""
+ {
+ "requestContext": {
+ "elb": {
+ "targetGroupArn": "arn:aws:elasticloadbalancing:us-east-2:123456789012:targetgroup/lambda-279XGJDqGZ5rsrHC2Fjr/49e9d65c45c6791a"
+ }
+ },
+ "httpMethod": "GET",
+ "path": "/api/values",
+ "headers": {
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8",
+ "accept-encoding": "gzip",
+ "accept-language": "en-US,en;q=0.9",
+ "connection": "keep-alive",
+ "host": "lambda-alb-123578498.us-east-2.elb.amazonaws.com",
+ "upgrade-insecure-requests": "1",
+ "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
+ "x-amzn-trace-id": "Root=1-5c536348-3d683b8b04734faae651f476",
+ "x-forwarded-for": "72.12.164.125",
+ "x-forwarded-port": "443",
+ "x-forwarded-proto": "https",
+ "x-imforwards": "20"
+ },
+ "body": "request_body",
+ "isBase64Encoded": false
+ }
+ """;
+ EnqueueLambdaEvent(ApplicationLoadBalancerRequestJson);
+ }
+ }
+
+
+ public class LambdaAPIGatewayProxyRequestAutoInstrumentationTriggerFixtureNet8 : AspNetCoreWebApiLambdaFixtureBase
+ {
+ public LambdaAPIGatewayProxyRequestAutoInstrumentationTriggerFixtureNet8() : base("net8.0")
+ {
+ CommandLineArguments = "--handler APIGatewayProxyFunctionEntryPoint";
+ }
+ }
+ public class LambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTriggerFixtureNet8 : AspNetCoreWebApiLambdaFixtureBase
+ {
+ public LambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTriggerFixtureNet8() : base("net8.0")
+ {
+ CommandLineArguments = "--handler APIGatewayHttpApiV2ProxyFunctionEntryPoint";
+ }
+ }
+ public class LambdaApplicationLoadBalancerRequestAutoInstrumentationTriggerFixtureNet8 : AspNetCoreWebApiLambdaFixtureBase
+ {
+ public LambdaApplicationLoadBalancerRequestAutoInstrumentationTriggerFixtureNet8() : base("net8.0")
+ {
+ CommandLineArguments = "--handler ApplicationLoadBalancerFunctionEntryPoint";
+ }
+ }
+}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaSelfExecutingAssemblyFixture.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaSelfExecutingAssemblyFixture.cs
index 88dc0b3719..010090ecb3 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaSelfExecutingAssemblyFixture.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaSelfExecutingAssemblyFixture.cs
@@ -8,13 +8,15 @@ namespace NewRelic.Agent.IntegrationTests.RemoteServiceFixtures.AwsLambda
{
public abstract class LambdaSelfExecutingAssemblyFixture : LambdaTestToolFixture
{
- public LambdaSelfExecutingAssemblyFixture(string targetFramework, string newRelicLambdaHandler, string lambdaHandler, string lambdaName, string lambdaVersion) :
+ protected LambdaSelfExecutingAssemblyFixture(string targetFramework, string newRelicLambdaHandler,
+ string lambdaHandler, string lambdaName, string lambdaVersion) :
base(new RemoteService("LambdaSelfExecutingAssembly", "LambdaSelfExecutingAssembly.exe", targetFramework, ApplicationType.Bounded, createsPidFile: true, isCoreApp: true, publishApp: true),
newRelicLambdaHandler,
lambdaHandler,
lambdaName,
lambdaVersion,
- "self executing assembly")
+ "self executing assembly",
+ true)
{
}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaTestToolFixture.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaTestToolFixture.cs
index 4cd13e1ba0..1bfa075918 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaTestToolFixture.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaTestToolFixture.cs
@@ -16,7 +16,9 @@ public class LambdaTestToolFixture : RemoteApplicationFixture
public DotnetTool LambdaTestTool { get; set; }
public Action AdditionalSetupConfiguration { get; set; }
- public LambdaTestToolFixture(RemoteApplication remoteApplication, string newRelicLambdaHandler, string lambdaHandler, string lambdaName, string lambdaVersion, string lambdaExecutionEnvironment) : base(remoteApplication)
+ public LambdaTestToolFixture(RemoteApplication remoteApplication, string newRelicLambdaHandler,
+ string lambdaHandler, string lambdaName, string lambdaVersion, string lambdaExecutionEnvironment,
+ bool setNewRelicLambdaHandlerEventVar) : base(remoteApplication)
{
LambdaTestTool = new DotnetTool("Amazon.Lambda.TestTool-8.0", "lambda-test-tool-8.0", DestinationApplicationDirectoryPath);
@@ -33,8 +35,11 @@ public LambdaTestToolFixture(RemoteApplication remoteApplication, string newReli
SetAdditionalEnvironmentVariable("NEW_RELIC_ACCOUNT_ID", TestConfiguration.NewRelicAccountId);
SetAdditionalEnvironmentVariable("AWS_LAMBDA_RUNTIME_API", $"localhost:{LambdaTestTool.Port}");
- AddAdditionalEnvironmentVariableIfNotNull("NEW_RELIC_LAMBDA_HANDLER", newRelicLambdaHandler);
+ if (setNewRelicLambdaHandlerEventVar)
+ AddAdditionalEnvironmentVariableIfNotNull("NEW_RELIC_LAMBDA_HANDLER", newRelicLambdaHandler);
+
AddAdditionalEnvironmentVariableIfNotNull("_HANDLER", lambdaHandler);
+
AddAdditionalEnvironmentVariableIfNotNull("AWS_LAMBDA_FUNCTION_NAME", lambdaName);
AddAdditionalEnvironmentVariableIfNotNull("AWS_LAMBDA_FUNCTION_VERSION", lambdaVersion);
AddAdditionalEnvironmentVariableIfNotNull("AWS_EXECUTION_ENV", lambdaExecutionEnvironment);
@@ -82,7 +87,7 @@ private void WarmUpTestTool()
GetString(address);
return;
}
- catch(Exception e)
+ catch (Exception e)
{
TestLogger?.WriteLine($"Unable to warm up lambda test tool during attempt {attempt}. Exception: {e}");
if (attempt == 3)
From 77ce40fd8c5259aaa293f73e3c662fed45ed4052 Mon Sep 17 00:00:00 2001
From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com>
Date: Tue, 6 Aug 2024 16:16:51 -0500
Subject: [PATCH 3/4] Integration tests complete
---
.../Wrapper/AwsLambda/HandlerMethodWrapper.cs | 3 +-
.../Wrapper/AwsLambda/Instrumentation.xml | 2 +-
.../AspNetCoreWebApiLambdaApplication.csproj | 2 +-
.../Program.cs | 10 +++--
...piV2ProxyRequestAutoInstrumentationTest.cs | 6 +--
...ambdaAutoInstrumentationTriggerFixtures.cs | 40 ++++++++++++++-----
6 files changed, 42 insertions(+), 21 deletions(-)
diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/HandlerMethodWrapper.cs b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/HandlerMethodWrapper.cs
index 237724e75c..54e2959040 100644
--- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/HandlerMethodWrapper.cs
+++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/HandlerMethodWrapper.cs
@@ -128,7 +128,8 @@ public bool ValidateWebRequestParameters(InstrumentedMethodCall instrumentedMeth
{
dynamic requestContext = input.RequestContext;
- return !string.IsNullOrEmpty(requestContext.Http.Method) && !string.IsNullOrEmpty(requestContext.Http.Path);
+ if (requestContext.Http != null)
+ return !string.IsNullOrEmpty(requestContext.Http.Method) && !string.IsNullOrEmpty(requestContext.Http.Path);
}
return false;
diff --git a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
index 8c6b9e2a90..90b1759b58 100644
--- a/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
+++ b/src/Agent/NewRelic/Agent/Extensions/Providers/Wrapper/AwsLambda/Instrumentation.xml
@@ -17,7 +17,7 @@ SPDX-License-Identifier: Apache-2.0
-
+
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
index e1d3ebae26..8bb17b790b 100644
--- a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
@@ -13,7 +13,7 @@
-
+
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
index 578d358abe..dfb95079e7 100644
--- a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/Program.cs
@@ -66,6 +66,8 @@ private static string GetHandlerFromArgs(string[] args)
private static HandlerWrapper GetHandlerWrapper()
{
+ var defaultLambdaJsonSerializer = new DefaultLambdaJsonSerializer();
+
switch (_handlerToInvoke)
{
case "APIGatewayProxyFunctionEntryPoint":
@@ -73,24 +75,24 @@ private static HandlerWrapper GetHandlerWrapper()
var entryPoint = new APIGatewayProxyFunctionEntryPoint();
Func> handlerFunc = entryPoint.FunctionHandlerAsync;
- return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, defaultLambdaJsonSerializer);
}
case "ApplicationLoadBalancerFunctionEntryPoint":
{
var entryPoint = new ApplicationLoadBalancerFunctionEntryPoint();
Func> handlerFunc = entryPoint.FunctionHandlerAsync;
- return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, defaultLambdaJsonSerializer);
}
case "APIGatewayHttpApiV2ProxyFunctionEntryPoint":
{
var entryPoint = new APIGatewayHttpApiV2ProxyFunctionEntryPoint();
Func> handlerFunc = entryPoint.FunctionHandlerAsync;
- return HandlerWrapper.GetHandlerWrapper(handlerFunc, new DefaultLambdaJsonSerializer());
+ return HandlerWrapper.GetHandlerWrapper(handlerFunc, defaultLambdaJsonSerializer);
}
default:
- throw new ArgumentException("Handler not found.");
+ throw new ArgumentException($"Handler not found: {_handlerToInvoke}");
}
}
}
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
index 91e6eb459f..108cdb2091 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/AwsLambda/AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest.cs
@@ -65,9 +65,7 @@ private void ValidateServerlessPayload(ServerlessPayload serverlessPayload)
{ "request.headers.header1", "value1" },
{ "request.headers.header2", "value1,value2" },
{ "request.method", "GET" },
- { "request.uri", "/api.values" },
- { "request.parameters.parameter1", "value1,value2" },
- { "request.parameters.parameter2", "value" },
+ { "request.uri", "/api/values" },
{ "http.statusCode", 200 },
{ "response.status", "200" },
};
@@ -79,7 +77,7 @@ private void ValidateServerlessPayload(ServerlessPayload serverlessPayload)
}
}
-public class AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTestTestNet8 : AwsLambdaAPIGatewayRequestAutoInstrumentationTest
+public class AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTestTestNet8 : AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTest
{
public AwsLambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTestTestNet8(LambdaAPIGatewayHttpApiV2ProxyRequestAutoInstrumentationTriggerFixtureNet8 fixture, ITestOutputHelper output)
: base(fixture, output, "WebTransaction/MVC/Values/Get")
diff --git a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
index c144c8cc27..00229b70fb 100644
--- a/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
+++ b/tests/Agent/IntegrationTests/IntegrationTests/RemoteServiceFixtures/AwsLambda/LambdaAutoInstrumentationTriggerFixtures.cs
@@ -74,21 +74,41 @@ public void EnqueueAPIGatewayProxyRequest()
public void EnqueueAPIGatewayHttpApiV2ProxyRequest()
{
- var apiGatewayProxyRequestJson = $$"""
+ var apiGatewayHttpApiV2ProxyRequestJson = $$$"""
{
- "version": "2.0",
- "routeKey": "$default",
- "rawPath": "/",
- "requestContext": {
- "http": {
- "method": "GET",
- "path": "/"
+ "Version": "2.0",
+ "RouteKey": "$default",
+ "RawPath": "/api/values",
+ "Headers": {
+ "Header1": "value1",
+ "Header2": "value1,value2"
+ },
+ "RequestContext": {
+ "AccountId": "123456789012",
+ "ApiId": "api-id",
+ "DomainName": "id.execute-api.us-east-1.amazonaws.com",
+ "DomainPrefix": "id",
+ "Http": {
+ "Method": "GET",
+ "Path": "/api/values",
+ "Protocol": "HTTP/1.1",
+ "SourceIp": "192.168.0.1/32",
+ "UserAgent": "agent"
+ },
+ "RequestId": "id",
+ "RouteKey": "$default",
+ "Stage": "$default",
+ "Time": "12/Mar/2020:19:03:58 +0000",
+ "TimeEpoch": 1583348638390
+ },
+ "StageVariables": {
+ "stageVariable1": "value1",
+ "stageVariable2": "value2"
}
- }
}
""";
- EnqueueLambdaEvent(apiGatewayProxyRequestJson);
+ EnqueueLambdaEvent(apiGatewayHttpApiV2ProxyRequestJson);
}
public void EnqueueApplicationLoadBalancerRequest()
From 4be49cd61712537e4c09eadffbc1fadf24f5b64b Mon Sep 17 00:00:00 2001
From: Marty Tippin <120425148+tippmar-nr@users.noreply.github.com>
Date: Wed, 7 Aug 2024 09:29:56 -0500
Subject: [PATCH 4/4] Fix build errors
---
.github/workflows/all_solutions.yml | 1 +
.../AspNetCoreWebApiLambdaApplication.csproj | 2 --
2 files changed, 1 insertion(+), 2 deletions(-)
diff --git a/.github/workflows/all_solutions.yml b/.github/workflows/all_solutions.yml
index 4cce3a6e0b..a5093c0af3 100644
--- a/.github/workflows/all_solutions.yml
+++ b/.github/workflows/all_solutions.yml
@@ -221,6 +221,7 @@ jobs:
Api,
AppDomainCaching,
AspNetCore,
+ AwsLambda.AutoInstrumentation,
AwsLambda.CloudWatch,
AwsLambda.Custom,
AwsLambda.DynamoDb,
diff --git a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
index 8bb17b790b..0e4192f882 100644
--- a/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
+++ b/tests/Agent/IntegrationTests/Applications/AspNetCoreWebApiLambdaApplication/AspNetCoreWebApiLambdaApplication.csproj
@@ -7,8 +7,6 @@
Lambda
true
-
- true