diff --git a/.azure-pipelines/ultimate-pipeline.yml b/.azure-pipelines/ultimate-pipeline.yml index ebf6063a22f2..cc7f6eb8a90e 100644 --- a/.azure-pipelines/ultimate-pipeline.yml +++ b/.azure-pipelines/ultimate-pipeline.yml @@ -1956,6 +1956,13 @@ stages: command: "BuildLinuxIntegrationTests --framework $(publishTargetFramework) --SampleName Samples.Aws.Lambda" apiKey: $(DD_LOGGER_DD_API_KEY) + - template: steps/run-in-docker.yml + parameters: + build: true + baseImage: $(baseImage) + command: "BuildLinuxIntegrationTests --framework $(publishTargetFramework) --SampleName Samples.Amazon.Lambda.RuntimeSupport" + apiKey: $(DD_LOGGER_DD_API_KEY) + - script: | # Include the serverless dockerfile docker-compose -p ddtrace_$(Build.BuildNumber) \ @@ -2041,7 +2048,8 @@ stages: serverless-lambda-generic-abstract \ serverless-lambda-generic-abstract-async \ serverless-lambda-generic-complex \ - serverless-lambda-generic-complex-nested + serverless-lambda-generic-complex-nested \ + serverless-lambda-toplevel-statement env: baseImage: $(baseImage) framework: $(publishTargetFramework) diff --git a/Datadog.Trace.sln b/Datadog.Trace.sln index a917777c6878..9f45fd749a25 100644 --- a/Datadog.Trace.sln +++ b/Datadog.Trace.sln @@ -546,6 +546,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Datadog.Trace.Tools.dd_dotn EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.AWS.DynamoDBv2", "tracer\test\test-applications\integrations\Samples.AWS.DynamoDBv2\Samples.AWS.DynamoDBv2.csproj", "{D59C5649-BE0E-4A33-B868-B652D8614534}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Samples.Amazon.Lambda.RuntimeSupport", "tracer\test\test-applications\integrations\Samples.Amazon.Lambda.RuntimeSupport\Samples.Amazon.Lambda.RuntimeSupport.csproj", "{18A6904A-5AFD-4816-AC3F-9F5E433720B5}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU @@ -1302,6 +1304,10 @@ Global {D59C5649-BE0E-4A33-B868-B652D8614534}.Debug|Any CPU.Build.0 = Debug|Any CPU {D59C5649-BE0E-4A33-B868-B652D8614534}.Release|Any CPU.ActiveCfg = Release|Any CPU {D59C5649-BE0E-4A33-B868-B652D8614534}.Release|Any CPU.Build.0 = Release|Any CPU + {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Debug|Any CPU.Build.0 = Debug|Any CPU + {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Release|Any CPU.ActiveCfg = Release|Any CPU + {18A6904A-5AFD-4816-AC3F-9F5E433720B5}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/docker-compose.serverless.yml b/docker-compose.serverless.yml index 7b0fa11675aa..7b8e5eabb542 100644 --- a/docker-compose.serverless.yml +++ b/docker-compose.serverless.yml @@ -40,6 +40,7 @@ services: - serverless-lambda-generic-abstract-async - serverless-lambda-generic-complex - serverless-lambda-generic-complex-nested + - serverless-lambda-toplevel-statement - serverless-dummy-api environment: - AWS_LAMBDA_ENDPOINT_NO_PARAM_SYNC=http://serverless-lambda-no-param-sync:8080 @@ -79,6 +80,7 @@ services: - AWS_LAMBDA_ENDPOINT_GENERICBASE_ABSTRACT_ASYNC=http://serverless-lambda-generic-abstract-async:8080 - AWS_LAMBDA_ENDPOINT_GENERICBASE_COMPLEX=http://serverless-lambda-generic-complex:8080 - AWS_LAMBDA_ENDPOINT_GENERICBASE_COMPLEX_NESTED=http://serverless-lambda-generic-complex-nested:8080 + - AWS_LAMBDA_ENDPOINT_TOPLEVEL_STATEMENT=http://serverless-lambda-toplevel-statement:8080 - DUMMY_API_HOST=http://serverless-dummy-api:9005 StartDependencies.Serverless: @@ -121,6 +123,7 @@ services: - serverless-lambda-generic-abstract-async - serverless-lambda-generic-complex - serverless-lambda-generic-complex-nested + - serverless-lambda-toplevel-statement - serverless-dummy-api environment: - TIMEOUT_LENGTH=120 @@ -162,6 +165,7 @@ services: serverless-lambda-generic-abstract-async:8080 serverless-lambda-generic-complex:8080 serverless-lambda-generic-complex-nested:8080 + serverless-lambda-toplevel-statement:8080 serverless-dummy-api:9005 serverless-lambda-no-param-sync: @@ -1015,6 +1019,29 @@ services: - ./:/project - ./tracer/build_data/logs/serverless-lambda-generic-complex-nested:/var/log/datadog/dotnet + serverless-lambda-toplevel-statement: + build: + context: ./tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport + dockerfile: serverless.lambda.dockerfile + args: + - lambdaBaseImage=${lambdaBaseImage:-public.ecr.aws/lambda/dotnet:6} + - framework=${framework:-net6.0} + depends_on: + - serverless-dummy-api + command: "Samples.Amazon.Lambda.RuntimeSupport" + image: dd-trace-dotnet/serverless-lambda-toplevel-statement + environment: + - DD_TRACE_AGENT_URL=http://integrationtests:5002 + - _DD_EXTENSION_ENDPOINT=http://integrationtests:9003 + - DUMMY_API_HOST=http://serverless-dummy-api:9005 + - DD_INSTRUMENTATION_TELEMETRY_ENABLED=0 + - DD_TRACE_DEBUG=1 + ports: + - "8080" + volumes: + - ./:/project + - ./tracer/build_data/logs/serverless-lambda-toplevel-statement:/var/log/datadog/dotnet + # The serverless function calls this API, which always returns 200 OK serverless-dummy-api: image: andrewlock/ok-api:latest diff --git a/tracer/build/PackageVersionsGeneratorDefinitions.json b/tracer/build/PackageVersionsGeneratorDefinitions.json index 5c28b0f76641..d3375436c931 100644 --- a/tracer/build/PackageVersionsGeneratorDefinitions.json +++ b/tracer/build/PackageVersionsGeneratorDefinitions.json @@ -31,6 +31,20 @@ "IncludeOnlyTargetFrameworks": ["net462"] }] }, + { + "IntegrationName": "AwsLambda", + "SampleProjectName": "Samples.Amazon.Lambda.RuntimeSupport", + "NugetPackageSearchName": "Amazon.Lambda.RuntimeSupport", + "MinVersion": "1.4.0", + "MaxVersionExclusive": "2.0.0", + "SpecificVersions": [ + "1.8.*" + ], + "VersionConditions": [{ + "MinVersion": "1.4.0", + "IncludeOnlyTargetFrameworks": ["net6.0","net7.0"] + }] + }, { "IntegrationName": "AwsSqs", "SampleProjectName": "Samples.AWS.SQS", diff --git a/tracer/build/PackageVersionsLatestMajors.g.props b/tracer/build/PackageVersionsLatestMajors.g.props index 2b1409551b06..b714f77c01e4 100644 --- a/tracer/build/PackageVersionsLatestMajors.g.props +++ b/tracer/build/PackageVersionsLatestMajors.g.props @@ -96,6 +96,18 @@ NOTE: This code was generated by the GeneratePackageVersions tool. To safely All Samples.AWS.Kinesis + + ApiVersion=1.9.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.9.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + ApiVersion=3.7.200.59;RestoreRecursive=false;BuildProjectReferences=false net462 diff --git a/tracer/build/PackageVersionsLatestMinors.g.props b/tracer/build/PackageVersionsLatestMinors.g.props index 712514744dc8..56f53f4aabd4 100644 --- a/tracer/build/PackageVersionsLatestMinors.g.props +++ b/tracer/build/PackageVersionsLatestMinors.g.props @@ -276,6 +276,78 @@ NOTE: This code was generated by the GeneratePackageVersions tool. To safely All Samples.AWS.Kinesis + + ApiVersion=1.4.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.5.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.6.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.7.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.8.8;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.9.0;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.4.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.5.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.6.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.7.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.8.8;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.9.0;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + ApiVersion=3.1.0.13;RestoreRecursive=false;BuildProjectReferences=false net462 diff --git a/tracer/build/PackageVersionsLatestSpecific.g.props b/tracer/build/PackageVersionsLatestSpecific.g.props index 5e4593b80bee..d960fcf50bf1 100644 --- a/tracer/build/PackageVersionsLatestSpecific.g.props +++ b/tracer/build/PackageVersionsLatestSpecific.g.props @@ -192,6 +192,18 @@ NOTE: This code was generated by the GeneratePackageVersions tool. To safely All Samples.AWS.Kinesis + + ApiVersion=1.8.8;RestoreRecursive=false;BuildProjectReferences=false + net6.0 + All + Samples.Amazon.Lambda.RuntimeSupport + + + ApiVersion=1.8.8;RestoreRecursive=false;BuildProjectReferences=false + net7.0 + All + Samples.Amazon.Lambda.RuntimeSupport + ApiVersion=3.1.0.13;RestoreRecursive=false;BuildProjectReferences=false net462 diff --git a/tracer/build/_build/Build.Steps.cs b/tracer/build/_build/Build.Steps.cs index da9e0431ea11..46c0506a33b6 100644 --- a/tracer/build/_build/Build.Steps.cs +++ b/tracer/build/_build/Build.Steps.cs @@ -2111,10 +2111,12 @@ var name when multiPackageProjects.Contains(name) => false, .Executes(() => { - var projectFile = TracerDirectory.GlobFiles("test/test-applications/integrations/*/Samples.AWS.Lambda.csproj").FirstOrDefault(); - var target = projectFile / ".." / "bin" / "artifacts" / "monitoring-home"; - - CopyDirectoryRecursively(MonitoringHomeDirectory, target, DirectoryExistsPolicy.Merge, FileExistsPolicy.Overwrite); + var serverlessProjects = new List { "Samples.AWS.Lambda.csproj", "Samples.Amazon.Lambda.RuntimeSupport.csproj" }; + foreach (var target in serverlessProjects.Select(projectName => TracerDirectory.GlobFiles($"test/test-applications/integrations/*/{projectName}").FirstOrDefault()) + .Select(projectFile => projectFile / ".." / "bin" / "artifacts" / "monitoring-home")) + { + CopyDirectoryRecursively(MonitoringHomeDirectory, target, DirectoryExistsPolicy.Merge, FileExistsPolicy.Overwrite); + } }); Target CreateRootDescriptorsFile => _ => _ diff --git a/tracer/build/_build/Honeypot/IntegrationGroups.cs b/tracer/build/_build/Honeypot/IntegrationGroups.cs index e6243bfd380e..a6050496d5e7 100644 --- a/tracer/build/_build/Honeypot/IntegrationGroups.cs +++ b/tracer/build/_build/Honeypot/IntegrationGroups.cs @@ -35,6 +35,7 @@ static IntegrationMap() NugetPackages.Add("AerospikeClient", new [] { "Aerospike.Client" }); NugetPackages.Add("Microsoft.AspNetCore.Http", new string[] { }); NugetPackages.Add("System.Web.Mvc", new [] { "Microsoft.AspNet.Mvc" }); + NugetPackages.Add("Amazon.Lambda.RuntimeSupport", new [] { "Amazon.Lambda.RuntimeSupport" }); NugetPackages.Add("AWSSDK.DynamoDBv2", new [] { "AWSSDK.DynamoDBv2" }); NugetPackages.Add("AWSSDK.Core", new [] { "AWSSDK.Core" }); NugetPackages.Add("AWSSDK.Kinesis", new [] { "AWSSDK.Kinesis" }); diff --git a/tracer/dependabot/Datadog.Dependabot.Integrations.csproj b/tracer/dependabot/Datadog.Dependabot.Integrations.csproj index e953b4bf8b0d..1fd960f0b39e 100644 --- a/tracer/dependabot/Datadog.Dependabot.Integrations.csproj +++ b/tracer/dependabot/Datadog.Dependabot.Integrations.csproj @@ -276,6 +276,11 @@ + + + + + diff --git a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml index d06cb126d608..e971321fdf69 100644 --- a/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml +++ b/tracer/src/Datadog.Trace.Trimming/build/Datadog.Trace.Trimming.xml @@ -1,5 +1,6 @@ + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/HandlerWrapperSetHandlerIntegration.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/HandlerWrapperSetHandlerIntegration.cs new file mode 100644 index 000000000000..ac516f7ee7de --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/HandlerWrapperSetHandlerIntegration.cs @@ -0,0 +1,130 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +#if NET6_0_OR_GREATER +using System; +using System.ComponentModel; +using System.IO; +using System.Text; +using System.Threading.Tasks; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK; +using Datadog.Trace.ClrProfiler.CallTarget; +using Datadog.Trace.Configuration; +using Datadog.Trace.DuckTyping; +using Datadog.Trace.Util.Delegates; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; + +/// +/// Instrumenting the HandlerWrapper's GetHandlerWrapper method to wrap the Handler with Datadog wrapping methods +/// +[InstrumentMethod( + AssemblyName = "Amazon.Lambda.RuntimeSupport", + TypeName = "Amazon.Lambda.RuntimeSupport.HandlerWrapper", + MethodName = "set_Handler", + ReturnTypeName = ClrNames.Void, + ParameterTypeNames = new[] { "Amazon.Lambda.RuntimeSupport.LambdaBootstrapHandler" }, + MinimumVersion = "1.4.0", + MaximumVersion = "1.*.*", + IntegrationName = IntegrationName)] +[Browsable(false)] +[EditorBrowsable(EditorBrowsableState.Never)] +public class HandlerWrapperSetHandlerIntegration +{ + private const string IntegrationName = nameof(IntegrationId.AwsLambda); + private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); + private static readonly Async1Callbacks Callbacks = new(); + + /// + /// OnMethodBegin callback. The input Delegate handler is the customer's handler. + /// And it's already wrapped by the Amazon.Lambda.RuntimeSupport.HandlerWrapper. + /// Here we will try further wrap it with our DelegateWrapper class + /// in order to make it notify the Datadog-Extension before and after the handler's each invocation. + /// + /// Type of the target + /// Instance value, aka `this` of the instrumented method + /// Instance of Amazon.Lambda.RuntimeSupport.LambdaBootstrapHandler + /// CallTarget state value + internal static CallTargetState OnMethodBegin(TTarget instance, ref Delegate handler) + { + handler = handler.Instrument(Callbacks); + return CallTargetState.GetDefault(); + } + + private static string ConvertPayloadStream(Stream payloadStream) + { + var reader = new StreamReader(payloadStream, Encoding.UTF8, leaveOpen: true); + var result = reader.ReadToEnd(); + // Reset the offset so that it can be read by the originally intended consumer, i.e. the user defined handler + payloadStream.Seek(0, SeekOrigin.Begin); + return result; + } + + private readonly struct Async1Callbacks : IBegin1Callbacks, IReturnAsyncCallback, IReturnCallback + { + public bool PreserveAsyncContext => false; + + public object OnDelegateBegin(object sender, ref TArg1 arg) + { + LambdaCommon.Log("DelegateWrapper Running OnDelegateBegin"); + + Scope scope; + var proxyInstance = arg.DuckCast(); + if (proxyInstance == null) + { + LambdaCommon.Log("DuckCast.IInvocationRequest got null proxyInstance", debug: false); + scope = LambdaCommon.SendStartInvocation(new LambdaRequestBuilder(), string.Empty, null); + } + else + { + var jsonString = ConvertPayloadStream(proxyInstance.InputStream); + scope = LambdaCommon.SendStartInvocation(new LambdaRequestBuilder(), jsonString, proxyInstance.LambdaContext?.ClientContext?.Custom); + } + + LambdaCommon.Log("DelegateWrapper FINISHED Running OnDelegateBegin"); + return new CallTargetState(scope); + } + + public void OnException(object sender, Exception ex) + { + LambdaCommon.Log("OnDelegateBegin could not send payload to the extension", ex, false); + } + + public TReturn OnDelegateEnd(object sender, TReturn returnValue, Exception exception, object state) + { + // Needed in order to make this Async1Callbacks work with Func1Wrapper, which expects IReturnCallback + return returnValue; + } + + /// + public Task OnDelegateEndAsync(object sender, TInnerReturn returnValue, Exception exception, object state) + { + LambdaCommon.Log("DelegateWrapper Running OnDelegateEndAsync"); + try + { + var proxyInstance = returnValue.DuckCast(); + if (proxyInstance == null) + { + LambdaCommon.Log("DuckCast.IInvocationResponse got null proxyInstance", debug: false); + LambdaCommon.EndInvocationAsync(string.Empty, exception, ((CallTargetState)state!).Scope, RequestBuilder).ConfigureAwait(false); + } + else + { + var jsonString = ConvertPayloadStream(proxyInstance.OutputStream); + LambdaCommon.EndInvocationAsync(jsonString, exception, ((CallTargetState)state!).Scope, RequestBuilder).ConfigureAwait(false); + } + } + catch (Exception ex) + { + LambdaCommon.Log("OnDelegateEndAsync could not send payload to the extension", ex, false); + LambdaCommon.EndInvocationAsync(string.Empty, ex, ((CallTargetState)state!).Scope, RequestBuilder).ConfigureAwait(false); + } + + LambdaCommon.Log("DelegateWrapper FINISHED Running OnDelegateEndAsync"); + return Task.FromResult(returnValue); + } + } +} +#endif diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/ILambdaExtensionRequest.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/ILambdaExtensionRequest.cs new file mode 100644 index 000000000000..86bdb1bf91de --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/ILambdaExtensionRequest.cs @@ -0,0 +1,26 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// +#if NET6_0_OR_GREATER + +using System.Net; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; + +internal interface ILambdaExtensionRequest +{ + /// + /// Get the start invocation request + /// + /// The start invocation request + WebRequest GetStartInvocationRequest(); + + /// + /// Get the end invocation request + /// + /// The end invocation request + WebRequest GetEndInvocationRequest(Scope scope, bool isError); +} + +#endif diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaCommon.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaCommon.cs new file mode 100644 index 000000000000..16ee11397cb1 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaCommon.cs @@ -0,0 +1,143 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// +#if NET6_0_OR_GREATER +using System; +using System.Collections.Generic; +using System.Net; +using System.Text; +using System.Threading.Tasks; +using Datadog.Trace.Sampling; +using Datadog.Trace.Telemetry; +using Datadog.Trace.Telemetry.Metrics; +using Datadog.Trace.Util; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; + +internal abstract class LambdaCommon +{ + private const string PlaceholderServiceName = "placeholder-service"; + private const string PlaceholderOperationName = "placeholder-operation"; + private const double ServerlessMaxWaitingFlushTime = 3; + private const string LogLevelEnvName = "DD_LOG_LEVEL"; + + internal static Scope CreatePlaceholderScope(Tracer tracer, string traceId, string samplingPriority) + { + Span span; + + if (traceId == null) + { + Log("traceId not found"); + span = tracer.StartSpan(PlaceholderOperationName, tags: null, serviceName: PlaceholderServiceName, addToTraceContext: false); + } + else + { + Log($"creating the placeholder traceId = {traceId}"); + span = tracer.StartSpan(PlaceholderOperationName, tags: null, serviceName: PlaceholderServiceName, traceId: (TraceId)Convert.ToUInt64(traceId), addToTraceContext: false); + } + + if (samplingPriority == null) + { + Log("samplingPriority not found"); + + var samplingDecision = tracer.CurrentTraceSettings.TraceSampler?.MakeSamplingDecision(span) ?? SamplingDecision.Default; + span.Context.TraceContext?.SetSamplingPriority(samplingDecision); + } + else + { + Log($"setting the placeholder sampling priority to = {samplingPriority}"); + span.Context.TraceContext?.SetSamplingPriority(Convert.ToInt32(samplingPriority), notifyDistributedTracer: false); + } + + TelemetryFactory.Metrics.RecordCountSpanCreated(MetricTags.IntegrationName.AwsLambda); + return tracer.TracerManager.ScopeManager.Activate(span, false); + } + + internal static Scope SendStartInvocation(ILambdaExtensionRequest requestBuilder, string data, IDictionary context) + { + var request = requestBuilder.GetStartInvocationRequest(); + WriteRequestPayload(request, data); + WriteRequestHeaders(request, context); + var response = (HttpWebResponse)request.GetResponse(); + var traceId = response.Headers.Get(HttpHeaderNames.TraceId); + var samplingPriority = response.Headers.Get(HttpHeaderNames.SamplingPriority); + if (ValidateOkStatus(response)) + { + return CreatePlaceholderScope(Tracer.Instance, traceId, samplingPriority); + } + + return null; + } + + internal static void SendEndInvocation(ILambdaExtensionRequest requestBuilder, Scope scope, bool isError, string data) + { + var request = requestBuilder.GetEndInvocationRequest(scope, isError); + WriteRequestPayload(request, data); + if (!ValidateOkStatus((HttpWebResponse)request.GetResponse())) + { + Log("Extension does not send a status 200 OK", debug: false); + } + } + + internal static async Task EndInvocationAsync(string returnValue, Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) + { + try + { + await Tracer.Instance.TracerManager.AgentWriter.FlushTracesAsync() + .WaitAsync(TimeSpan.FromSeconds(ServerlessMaxWaitingFlushTime)) + .ConfigureAwait(false); + } + catch (Exception ex) + { + Log("Could not flush to the extension", ex, false); + } + + try + { + SendEndInvocation(requestBuilder, scope, exception != null, returnValue); + } + catch (Exception ex) + { + Log("Could not send payload to the extension", ex, false); + } + + scope?.Dispose(); + } + + private static bool ValidateOkStatus(HttpWebResponse response) + { + var statusCode = response.StatusCode; + Log("The extension responds with statusCode = " + statusCode); + return statusCode == HttpStatusCode.OK; + } + + private static void WriteRequestPayload(WebRequest request, string data) + { + var byteArray = Encoding.UTF8.GetBytes(data); + request.ContentLength = byteArray.Length; + var dataStream = request.GetRequestStream(); + dataStream.Write(byteArray, 0, byteArray.Length); + dataStream.Close(); + } + + private static void WriteRequestHeaders(WebRequest request, IDictionary context) + { + if (context != null) + { + foreach (var kv in context) + { + request.Headers.Add(kv.Key, kv.Value); + } + } + } + + internal static void Log(string message, Exception ex = null, bool debug = true) + { + if (!debug || EnvironmentHelpers.GetEnvironmentVariable(LogLevelEnvName)?.ToLower() == "debug") + { + Console.WriteLine($"{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss:fff} [DD_TRACE_DOTNET] {message} {ex?.ToString().Replace("\n", "\\n")}"); + } + } +} +#endif diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaRequestBuilder.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaRequestBuilder.cs new file mode 100644 index 000000000000..e48e6261a84c --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaRequestBuilder.cs @@ -0,0 +1,65 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// +#if NET6_0_OR_GREATER +using System.Globalization; +using System.Net; +using Datadog.Trace.Agent.Transports; +using Datadog.Trace.Util; +#pragma warning disable CS0618 // WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead. + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; + +internal class LambdaRequestBuilder : ILambdaExtensionRequest +{ + private const string EndInvocationPath = "/lambda/end-invocation"; + private const string StartInvocationPath = "/lambda/start-invocation"; + private const string ExtensionUri = "http://127.0.0.1:8124"; + private const string ExtensionUriEnvName = "_DD_EXTENSION_ENDPOINT"; + + internal LambdaRequestBuilder() + { + Uri = EnvironmentHelpers.GetEnvironmentVariable(ExtensionUriEnvName) ?? ExtensionUri; + } + + internal string Uri { get; } + + WebRequest ILambdaExtensionRequest.GetStartInvocationRequest() + { + var request = WebRequest.Create(Uri + StartInvocationPath); + request.Method = "POST"; + request.Headers.Set(HttpHeaderNames.TracingEnabled, "false"); + request.ContentType = MimeTypes.Json; + return request; + } + + WebRequest ILambdaExtensionRequest.GetEndInvocationRequest(Scope scope, bool isError) + { + var request = WebRequest.Create(Uri + EndInvocationPath); + request.Method = "POST"; + request.Headers.Set(HttpHeaderNames.TracingEnabled, "false"); + + if (scope is { Span: var span }) + { + // TODO: add support for 128-bit trace ids in serverless + request.Headers.Set(HttpHeaderNames.TraceId, span.TraceId128.Lower.ToString(CultureInfo.InvariantCulture)); + request.Headers.Set(HttpHeaderNames.SpanId, span.SpanId.ToString(CultureInfo.InvariantCulture)); + + if (span.Context.TraceContext?.SamplingPriority is { } samplingPriority) + { + request.Headers.Set(HttpHeaderNames.SamplingPriority, samplingPriority.ToString()); + } + } + + if (isError) + { + request.Headers.Set(HttpHeaderNames.InvocationError, "true"); + } + + return request; + } +} + +#endif + diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IClientContext.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IClientContext.cs new file mode 100644 index 000000000000..8a28b051dc9f --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IClientContext.cs @@ -0,0 +1,21 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +using System.Collections.Generic; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK; + +/// +/// Information about client configuration and execution environment. +/// +internal interface IClientContext +{ + /// + /// Gets the datadog injected trace context + /// Used with the datadog ducktyping library + /// + /// The trace context + IDictionary Custom { get; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationRequest.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationRequest.cs new file mode 100644 index 000000000000..0009c3d5664f --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationRequest.cs @@ -0,0 +1,26 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +using System; +using System.IO; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK; + +/// +/// Interface that contains all the information necessary to handle an invocation of an AWS Lambda function. +/// This is the DuckType for Amazon.Lambda.RuntimeSupport.InvocationRequest +/// +internal interface IInvocationRequest : IDisposable +{ + /// + /// Gets or sets input to the function invocation. + /// + public Stream InputStream { get; internal set; } + + /// + /// Gets or sets context for the invocation. + /// + public ILambdaContext LambdaContext { get; internal set; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationResponse.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationResponse.cs new file mode 100644 index 000000000000..f5268e05a974 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/IInvocationResponse.cs @@ -0,0 +1,26 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// + +using System.IO; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK; + +/// +/// Interface that contains the response for an invocation of an AWS Lambda function. +/// This is the DuckType for Amazon.Lambda.RuntimeSupport.InvocationResponse +/// +internal interface IInvocationResponse +{ + /// + /// Gets or sets output from the function invocation. + /// + public Stream OutputStream { get; internal set; } + + /// + /// Gets or sets a value indicating whether true if the LambdaBootstrap should dispose the stream after it's read, false otherwise. + /// Set this to false if you plan to reuse the same output stream for multiple invocations of the function. + /// + public bool DisposeOutputStream { get; internal set; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/ILambdaContext.cs b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/ILambdaContext.cs new file mode 100644 index 000000000000..af2137c43a85 --- /dev/null +++ b/tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/SDK/ILambdaContext.cs @@ -0,0 +1,91 @@ +// +// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. +// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. +// +using System; + +namespace Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK; + +/// +/// Object that allows you to access useful information available within +/// the Lambda execution environment. +/// +internal interface ILambdaContext +{ + // /// + // /// Gets the AWS request ID associated with the request. + // /// This is the same ID returned to the client that called invoke(). + // /// This ID is reused for retries on the same request. + // /// + // string AwsRequestId { get; } + + /// + /// Gets information about the client application and device when invoked + /// through the AWS Mobile SDK. It can be null. + /// Client context provides client information such as client ID, + /// application title, version name, version code, and the application + /// package name. + /// + IClientContext ClientContext { get; } + + // /// + // /// Gets name of the Lambda function that is running. + // /// + // string FunctionName { get; } + // + // /// + // /// Gets the Lambda function version that is executing. + // /// If an alias is used to invoke the function, then this will be + // /// the version the alias points to. + // /// + // string FunctionVersion { get; } + // + // // /// + // // /// Information about the Amazon Cognito identity provider when + // // /// invoked through the AWS Mobile SDK. + // // /// Can be null. + // // /// + // // ICognitoIdentity Identity { get; } + // + // /// + // /// Gets the ARN used to invoke this function. + // /// It can be function ARN or alias ARN. + // /// An unqualified ARN executes the $LATEST version and aliases execute + // /// the function version they are pointing to. + // /// + // string InvokedFunctionArn { get; } + // + // // /// + // // /// Lambda logger associated with the Context object. + // // /// + // // ILambdaLogger Logger { get; } + // + // /// + // /// Gets the CloudWatch log group name associated with the invoked function. + // /// It can be null if the IAM user provided does not have permission for + // /// CloudWatch actions. + // /// + // string LogGroupName { get; } + // + // /// + // /// Gets the CloudWatch log stream name for this function execution. + // /// It can be null if the IAM user provided does not have permission + // /// for CloudWatch actions. + // /// + // string LogStreamName { get; } + // + // /// + // /// Gets memory limit, in MB, you configured for the Lambda function. + // /// + // int MemoryLimitInMB { get; } + + // /// + // /// Gets remaining execution time till the function will be terminated. + // /// At the time you create the Lambda function you set maximum time + // /// limit, at which time AWS Lambda will terminate the function + // /// execution. + // /// Information about the remaining time of function execution can be + // /// used to specify function behavior when nearing the timeout. + // /// + // TimeSpan RemainingTime { get; } +} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/Instrumentation.cs b/tracer/src/Datadog.Trace/ClrProfiler/Instrumentation.cs index 8051f510ee0a..a20e313f0dad 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/Instrumentation.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/Instrumentation.cs @@ -135,8 +135,6 @@ public static void Initialize() sw.Restart(); InitializeTracer(sw); - - InitializeServerless(sw, Tracer.Instance.Settings.LambdaMetadata); } #if NETSTANDARD2_0 || NETCOREAPP3_1 @@ -216,8 +214,6 @@ public static void InitializeLegacy() InitializeTracer(sw); - InitializeServerless(sw, Tracer.Instance.Settings.LambdaMetadata); - InitializeAppSecLegacy(sw); InitializeIastLegacy(sw); @@ -403,24 +399,6 @@ private static void InitializeTracer(Stopwatch sw) } } - private static void InitializeServerless(Stopwatch sw, LambdaMetadata metadata) - { - try - { - Serverless.InitIfNeeded(metadata); - } - catch (Exception ex) - { - Serverless.Error("Error while loading Serverless definitions", ex); - } - - if (sw != null) - { - TelemetryFactory.Metrics.RecordDistributionSharedInitTime(MetricTags.InitializationComponent.Serverless, sw.ElapsedMilliseconds); - sw.Restart(); - } - } - private static void InitializeAppSecLegacy(Stopwatch sw) { if (!legacyMode) { return; } diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/IClientContext.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/IClientContext.cs deleted file mode 100644 index 14fb2d33f61b..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/IClientContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System.Collections.Generic; -using System.Net; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - internal interface IClientContext - { - /// - /// Gets the datadog injected trace context - /// Used with the datadog ducktyping library - /// - /// The trace context - IDictionary Custom { get; } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaContext.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaContext.cs deleted file mode 100644 index c8c98e6c8cbb..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaContext.cs +++ /dev/null @@ -1,20 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System.Net; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - internal interface ILambdaContext - { - /// - /// Gets the lambda context client - /// Contains the trace context - /// Used with the datadog ducktyping library - /// - /// The client context - IClientContext ClientContext { get; } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaExtensionRequest.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaExtensionRequest.cs deleted file mode 100644 index 3a58a04eb09d..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/ILambdaExtensionRequest.cs +++ /dev/null @@ -1,24 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System.Net; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - internal interface ILambdaExtensionRequest - { - /// - /// Get the start invocation request - /// - /// The start invocation request - WebRequest GetStartInvocationRequest(); - - /// - /// Get the end invocation request - /// - /// The end invocation request - WebRequest GetEndInvocationRequest(Scope scope, bool isError); - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaCommon.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaCommon.cs deleted file mode 100644 index f4d029b8a06c..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaCommon.cs +++ /dev/null @@ -1,331 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Text; -using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler.CallTarget; -using Datadog.Trace.Configuration; -using Datadog.Trace.DuckTyping; -using Datadog.Trace.Sampling; -using Datadog.Trace.Telemetry; -using Datadog.Trace.Telemetry.Metrics; -using Datadog.Trace.Util; -using Datadog.Trace.Vendors.Newtonsoft.Json; -using Datadog.Trace.Vendors.Newtonsoft.Json.Linq; -using Datadog.Trace.Vendors.Newtonsoft.Json.Serialization; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - internal class LambdaCommon - { - private const string PlaceholderServiceName = "placeholder-service"; - private const string PlaceholderOperationName = "placeholder-operation"; - private const string DefaultJson = "{}"; - private const double ServerlessMaxWaitingFlushTime = 3; - private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc); - - private static readonly DateTimeJsonConverter DateTimeConverter = new(); - private static readonly MemoryStreamJsonConverter MemoryStreamConverter = new(); - private static readonly ConverterContractResolver ContractResolver = new(); - - private static readonly JsonSerializerSettings SerializerSettings = new() - { - ContractResolver = ContractResolver, - Converters = new List - { - MemoryStreamConverter, - DateTimeConverter - } - }; - - internal static CallTargetState StartInvocation(ILambdaExtensionRequest requestBuilder, TArg payload, IDictionary context) - { - var json = SerializeObject(payload); - return new CallTargetState(NotifyExtensionStart(requestBuilder, json, context)); - } - - internal static CallTargetState StartInvocationWithoutEvent(ILambdaExtensionRequest requestBuilder) - { - return StartInvocation(requestBuilder, DefaultJson, null); - } - - internal static CallTargetState StartInvocationOneParameter(ILambdaExtensionRequest requestBuilder, TArg eventOrContext) - { - var dict = GetTraceContext(eventOrContext); - if (dict != null) - { - return StartInvocation(requestBuilder, DefaultJson, dict); - } - - return StartInvocation(requestBuilder, eventOrContext, null); - } - - internal static CallTargetState StartInvocationTwoParameters(ILambdaExtensionRequest requestBuilder, TArg1 payload, TArg2 context) - { - var dict = GetTraceContext(context); - return StartInvocation(requestBuilder, payload, dict); - } - - internal static CallTargetReturn EndInvocationSync(TReturn returnValue, Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) - { - var json = SerializeObject(returnValue); - Flush(); - NotifyExtensionEnd(requestBuilder, scope, exception != null, json); - scope?.Dispose(); - return new CallTargetReturn(returnValue); - } - - internal static async Task EndInvocationAsync(TReturn returnValue, Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) - { - var json = SerializeObject(returnValue); - - try - { - await Tracer.Instance.TracerManager.AgentWriter.FlushTracesAsync() - .WaitAsync(TimeSpan.FromSeconds(ServerlessMaxWaitingFlushTime)) - .ConfigureAwait(false); - } - catch (Exception ex) - { - Serverless.Error("Could not flush to the extension", ex); - } - - NotifyExtensionEnd(requestBuilder, scope, exception != null, json); - scope?.Dispose(); - return returnValue; - } - - internal static CallTargetReturn EndInvocationVoid(Exception exception, Scope scope, ILambdaExtensionRequest requestBuilder) - { - scope?.Dispose(); - Flush(); - NotifyExtensionEnd(requestBuilder, scope, exception != null); - return CallTargetReturn.GetDefault(); - } - - internal static Scope CreatePlaceholderScope(Tracer tracer, string traceId, string samplingPriority) - { - Span span; - - if (traceId == null) - { - Serverless.Debug("traceId not found"); - span = tracer.StartSpan(PlaceholderOperationName, tags: null, serviceName: PlaceholderServiceName, addToTraceContext: false); - } - else - { - Serverless.Debug($"creating the placeholder traceId = {traceId}"); - span = tracer.StartSpan(PlaceholderOperationName, tags: null, serviceName: PlaceholderServiceName, traceId: (TraceId)Convert.ToUInt64(traceId), addToTraceContext: false); - } - - if (samplingPriority == null) - { - Serverless.Debug("samplingPriority not found"); - - var samplingDecision = tracer.CurrentTraceSettings.TraceSampler?.MakeSamplingDecision(span) ?? SamplingDecision.Default; - span.Context.TraceContext?.SetSamplingPriority(samplingDecision); - } - else - { - Serverless.Debug($"setting the placeholder sampling priority to = {samplingPriority}"); - span.Context.TraceContext?.SetSamplingPriority(Convert.ToInt32(samplingPriority), notifyDistributedTracer: false); - } - - TelemetryFactory.Metrics.RecordCountSpanCreated(MetricTags.IntegrationName.AwsLambda); - return tracer.TracerManager.ScopeManager.Activate(span, false); - } - - internal static Scope SendStartInvocation(ILambdaExtensionRequest requestBuilder, string data, IDictionary context) - { - var request = requestBuilder.GetStartInvocationRequest(); - WriteRequestPayload(request, data); - WriteRequestHeaders(request, context); - HttpWebResponse response = (HttpWebResponse)request.GetResponse(); - var traceId = response.Headers.Get(HttpHeaderNames.TraceId); - var samplingPriority = response.Headers.Get(HttpHeaderNames.SamplingPriority); - if (ValidateOKStatus(response)) - { - return CreatePlaceholderScope(Tracer.Instance, traceId, samplingPriority); - } - - return null; - } - - internal static bool SendEndInvocation(ILambdaExtensionRequest requestBuilder, Scope scope, bool isError, string data) - { - var request = requestBuilder.GetEndInvocationRequest(scope, isError); - WriteRequestPayload(request, data); - return ValidateOKStatus((HttpWebResponse)request.GetResponse()); - } - - private static bool ValidateOKStatus(HttpWebResponse response) - { - var statusCode = response.StatusCode; - Serverless.Debug("The extension responds with statusCode = " + statusCode); - return statusCode == HttpStatusCode.OK; - } - - private static Scope NotifyExtensionStart(ILambdaExtensionRequest requestBuilder, string json, IDictionary context) - { - Scope scope = null; - try - { - scope = SendStartInvocation(requestBuilder, json, context); - if (scope == null) - { - Serverless.Debug("Error while creating the scope"); - } - } - catch (Exception ex) - { - Serverless.Error("Could not send payload to the extension", ex); - } - - return scope; - } - - private static void NotifyExtensionEnd(ILambdaExtensionRequest requestBuilder, Scope scope, bool isError, string json = DefaultJson) - { - try - { - if (!SendEndInvocation(requestBuilder, scope, isError, json)) - { - Serverless.Debug("Extension does not send a status 200 OK"); - } - } - catch (Exception ex) - { - Serverless.Error("Could not send payload to the extension", ex); - } - } - - private static void Flush() - { - try - { - // here we need a sync flush, since the lambda environment can be destroy after each invocation - // 3 seconds is enough to send payload to the extension (via localhost) - AsyncUtil.RunSync( - () => Tracer.Instance.TracerManager.AgentWriter.FlushTracesAsync() - .WaitAsync(TimeSpan.FromSeconds(ServerlessMaxWaitingFlushTime))); - } - catch (Exception ex) - { - Serverless.Error("Could not flush to the extension", ex); - } - } - - internal static string SerializeObject(T obj) - { - try - { - return JsonConvert.SerializeObject(obj, SerializerSettings); - } - catch (Exception ex) - { - Serverless.Debug("Failed to serialize object with the following error: " + ex.ToString()); - return DefaultJson; - } - } - - private static void WriteRequestPayload(WebRequest request, string data) - { - var byteArray = Encoding.UTF8.GetBytes(data); - request.ContentLength = byteArray.Length; - Stream dataStream = request.GetRequestStream(); - dataStream.Write(byteArray, 0, byteArray.Length); - dataStream.Close(); - } - - private static void WriteRequestHeaders(WebRequest request, IDictionary context) - { - if (context != null) - { - foreach (KeyValuePair kv in context) - { - request.Headers.Add(kv.Key, kv.Value); - } - } - } - - private static IDictionary GetTraceContext(object obj) - { - // Datadog duck typing library - var proxyInstance = obj.DuckAs(); - return proxyInstance?.ClientContext?.Custom; - } - - private class ConverterContractResolver : DefaultContractResolver - { - // A custom `ContractResolver` is needed to reduce overhead. - // https://www.newtonsoft.com/json/help/html/Performance.htm#JsonConverters - protected override JsonContract CreateContract(Type objectType) - { - // Create a contract with custom settings - var contract = base.CreateContract(objectType); - - if (objectType == typeof(MemoryStream)) - { - contract.Converter = MemoryStreamConverter; - } - else if (objectType == typeof(DateTime)) - { - contract.Converter = DateTimeConverter; - } - - return contract; - } - } - - private class MemoryStreamJsonConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, MemoryStream value, JsonSerializer serializer) - { - if (value == null) - { - writer.WriteNull(); - return; - } - - try - { - var base64String = Convert.ToBase64String(value.ToArray()); - writer.WriteValue(base64String); - } - catch (Exception ex) - { - Serverless.Debug($"Failed to serialize MemoryStream with the following error: {ex}"); - writer.WriteNull(); - } - } - - public override MemoryStream ReadJson(JsonReader reader, Type objectType, MemoryStream existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } - - private class DateTimeJsonConverter : JsonConverter - { - public override void WriteJson(JsonWriter writer, DateTime value, JsonSerializer serializer) - { - var elapsedTime = value - Epoch; - // `.TotalSeconds` includes milliseconds in the - // decimals, which is what the Extension expects. - var timestamp = elapsedTime.TotalSeconds; - writer.WriteValue(timestamp); - } - - public override DateTime ReadJson(JsonReader reader, Type objectType, DateTime existingValue, bool hasExistingValue, JsonSerializer serializer) - { - throw new NotImplementedException(); - } - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamAsync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamAsync.cs deleted file mode 100644 index 6c3168b4ccf7..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamAsync.cs +++ /dev/null @@ -1,50 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; -using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaNoParamAsync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance) - { - Serverless.Debug("OnMethodBegin - no param"); - return LambdaCommon.StartInvocationWithoutEvent(RequestBuilder); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static Task OnAsyncMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - no param"); - return LambdaCommon.EndInvocationAsync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamSync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamSync.cs deleted file mode 100644 index 2b33656d6f3e..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamSync.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaNoParamSync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance) - { - Serverless.Debug("OnMethodBegin - no param"); - return LambdaCommon.StartInvocationWithoutEvent(RequestBuilder); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - no param"); - return LambdaCommon.EndInvocationSync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamVoid.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamVoid.cs deleted file mode 100644 index f9c2aa56fb70..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaNoParamVoid.cs +++ /dev/null @@ -1,46 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaNoParamVoid - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance) - { - Serverless.Debug("OnMethodBegin - no param"); - return LambdaCommon.StartInvocationWithoutEvent(RequestBuilder); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - internal static CallTargetReturn OnMethodEnd(TTarget instance, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - no param"); - return LambdaCommon.EndInvocationVoid(exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamAsync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamAsync.cs deleted file mode 100644 index 49bf9fbe4473..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamAsync.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; -using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaOneParamAsync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEventOrContent - /// Instance value, aka `this` of the instrumented method. - /// IncomingEventOrContext value - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg incomingEventOrContext) - { - Serverless.Debug("OnMethodBegin - one param"); - return LambdaCommon.StartInvocationOneParameter(RequestBuilder, incomingEventOrContext); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static Task OnAsyncMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - one param"); - return LambdaCommon.EndInvocationAsync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamSync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamSync.cs deleted file mode 100644 index 84895d5762c0..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamSync.cs +++ /dev/null @@ -1,52 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; - -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaOneParamSync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEventOrContent - /// Instance value, aka `this` of the instrumented method. - /// IncomingEventOrContext value - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg incomingEventOrContext) - { - Serverless.Debug("OnMethodBegin - one param"); - return LambdaCommon.StartInvocationOneParameter(RequestBuilder, incomingEventOrContext); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - one param"); - return LambdaCommon.EndInvocationSync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamVoid.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamVoid.cs deleted file mode 100644 index 43dac9b6d027..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaOneParamVoid.cs +++ /dev/null @@ -1,49 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; - -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaOneParamVoid - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEventOrContent - /// Instance value, aka `this` of the instrumented method. - /// IncomingEventOrContext value - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg incomingEventOrContext) - { - Serverless.Debug("OnMethodBegin - one param"); - return LambdaCommon.StartInvocationOneParameter(RequestBuilder, incomingEventOrContext); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - internal static CallTargetReturn OnMethodEnd(TTarget instance, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - one param"); - return LambdaCommon.EndInvocationVoid(exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaRequestBuilder.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaRequestBuilder.cs deleted file mode 100644 index 222b20b11162..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaRequestBuilder.cs +++ /dev/null @@ -1,64 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System.Globalization; -using System.Net; - -using Datadog.Trace.Agent.Transports; -using Datadog.Trace.Util; -#pragma warning disable CS0618 // WebRequest, HttpWebRequest, ServicePoint, and WebClient are obsolete. Use HttpClient instead. - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - internal class LambdaRequestBuilder : ILambdaExtensionRequest - { - private const string EndInvocationPath = "/lambda/end-invocation"; - private const string StartInvocationPath = "/lambda/start-invocation"; - private const string ExtensionUri = "http://127.0.0.1:8124"; - private const string ExtensionUriEnvName = "_DD_EXTENSION_ENDPOINT"; - - internal LambdaRequestBuilder() - { - Uri = EnvironmentHelpers.GetEnvironmentVariable(ExtensionUriEnvName) ?? ExtensionUri; - } - - internal string Uri { get; } - - WebRequest ILambdaExtensionRequest.GetStartInvocationRequest() - { - var request = WebRequest.Create(Uri + StartInvocationPath); - request.Method = "POST"; - request.Headers.Set(HttpHeaderNames.TracingEnabled, "false"); - request.ContentType = MimeTypes.Json; - return request; - } - - WebRequest ILambdaExtensionRequest.GetEndInvocationRequest(Scope scope, bool isError) - { - var request = WebRequest.Create(Uri + EndInvocationPath); - request.Method = "POST"; - request.Headers.Set(HttpHeaderNames.TracingEnabled, "false"); - - if (scope is { Span: var span }) - { - // TODO: add support for 128-bit trace ids in serverless - request.Headers.Set(HttpHeaderNames.TraceId, span.TraceId128.Lower.ToString(CultureInfo.InvariantCulture)); - request.Headers.Set(HttpHeaderNames.SpanId, span.SpanId.ToString(CultureInfo.InvariantCulture)); - - if (span.Context.TraceContext?.SamplingPriority is { } samplingPriority) - { - request.Headers.Set(HttpHeaderNames.SamplingPriority, samplingPriority.ToString()); - } - } - - if (isError) - { - request.Headers.Set(HttpHeaderNames.InvocationError, "true"); - } - - return request; - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsAsync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsAsync.cs deleted file mode 100644 index aca36d833317..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsAsync.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; -using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaTwoParamsAsync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEvent - /// Type of the context - /// Instance value, aka `this` of the instrumented method. - /// IncomingEvent value - /// Context value. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg1 incomingEvent, TArg2 context) - { - Serverless.Debug("OnMethodBeginOK - two params"); - return LambdaCommon.StartInvocationTwoParameters(RequestBuilder, incomingEvent, context); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static Task OnAsyncMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - two params"); - return LambdaCommon.EndInvocationAsync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsSync.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsSync.cs deleted file mode 100644 index e1e4e95606b4..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsSync.cs +++ /dev/null @@ -1,54 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; - -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaTwoParamsSync - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEvent - /// Type of the context - /// Instance value, aka `this` of the instrumented method. - /// IncomingEvent value - /// Context value. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg1 incomingEvent, TArg2 context) - { - Serverless.Debug("OnMethodBeginOK - two params"); - return LambdaCommon.StartInvocationTwoParameters(RequestBuilder, incomingEvent, context); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Type of the response, in an async scenario will be T of Task of T - /// Instance value, aka `this` of the instrumented method. - /// HttpResponse message instance - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - /// A response value - internal static CallTargetReturn OnMethodEnd(TTarget instance, TReturn returnValue, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - two params"); - return LambdaCommon.EndInvocationSync(returnValue, exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsVoid.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsVoid.cs deleted file mode 100644 index f887ee13607a..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/AWS/LambdaTwoParamsVoid.cs +++ /dev/null @@ -1,51 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.ComponentModel; - -using Datadog.Trace.ClrProfiler.CallTarget; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS -{ - /// - /// Lambda customer handler calltarget instrumentation - /// - [Browsable(false)] - [EditorBrowsable(EditorBrowsableState.Never)] - public class LambdaTwoParamsVoid - { - private static readonly ILambdaExtensionRequest RequestBuilder = new LambdaRequestBuilder(); - - /// - /// OnMethodBegin callback - /// - /// Type of the target - /// Type of the incomingEvent - /// Type of the context - /// Instance value, aka `this` of the instrumented method. - /// IncomingEvent value - /// Context value. - /// Calltarget state value - internal static CallTargetState OnMethodBegin(TTarget instance, TArg1 incomingEvent, TArg2 context) - { - Serverless.Debug("OnMethodBeginOK - two params"); - return LambdaCommon.StartInvocationTwoParameters(RequestBuilder, incomingEvent, context); - } - - /// - /// OnMethodEnd callback - /// - /// Type of the target - /// Instance value, aka `this` of the instrumented method. - /// Exception instance in case the original code threw an exception. - /// Calltarget state value - internal static CallTargetReturn OnMethodEnd(TTarget instance, Exception exception, in CallTargetState state) - { - Serverless.Debug("OnMethodEnd - two params"); - return LambdaCommon.EndInvocationVoid(exception, state.Scope, RequestBuilder); - } - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaHandler.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaHandler.cs deleted file mode 100644 index 27c56f2fd93c..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaHandler.cs +++ /dev/null @@ -1,179 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -#nullable enable - -using System; -using System.Reflection; -using Datadog.Trace.Util; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation; - -internal class LambdaHandler -{ - internal const string Separator = "::"; - private static readonly string[] Separators = { "::" }; - - internal LambdaHandler(string? handlerName) - { - if (handlerName is null) - { - ThrowHelper.ThrowArgumentNullException(nameof(handlerName)); - } - - var handlerTokens = handlerName.Split(Separators, StringSplitOptions.None); - if (handlerTokens.Length != 3) - { - ThrowHelper.ThrowArgumentException($"The handler name {handlerName} did not have the expected format A::B::C"); - } - - var assemblyToken = handlerTokens[0]; - var typeToken = handlerTokens[1]; - var methodName = handlerTokens[2]; - - var handlerType = Type.GetType($"{typeToken},{assemblyToken}"); - if (handlerType is null) - { - ThrowHelper.ThrowArgumentException($"Could not find handler type {handlerType}"); - } - - // Flattens hierarchy, because we need to potentially find an implementation on a base type - var handlerMethod = handlerType.GetMethod(methodName); - if (handlerMethod is null) - { - ThrowHelper.ThrowArgumentException($"Could not find handler method {handlerName} in type {handlerType}"); - } - - // Generic methods aren't supported in AWS Lambda - // https://docs.aws.amazon.com/lambda/latest/dg/csharp-handler.html#csharp-handler-restrictions - if (handlerMethod.IsGenericMethod || handlerMethod.IsGenericMethodDefinition) - { - ThrowHelper.ThrowArgumentException($"Unable to instrument generic method {handlerMethod.Name} declared on {handlerMethod.DeclaringType}"); - } - - var declaringType = handlerMethod.DeclaringType; - - // We should never be invoking generic _definitions_ (i.e. open generics) - // because the handlerType should always be a specialised type - if (declaringType?.IsGenericTypeDefinition == true) - { - ThrowHelper.ThrowArgumentException($"Unable to instrument generic method {handlerMethod.Name} declared on generic type definition {declaringType}"); - } - - if (declaringType is not null - && declaringType != handlerType - && declaringType.IsGenericType) - { - // Handler is declared on a base type, which is generic - // We need to instrument the method in the generic type, not the specialized version - var genericTypeDefinition = declaringType.GetGenericTypeDefinition(); - - // The handlerMethod _currently_ points to the specialised version of the method - // But we need to get the non-specialised version - // I can't find a way to get this directly from genericDefinition or handlerMethod, - // so we search for it directly instead - var genericMethod = genericTypeDefinition.GetMethod(handlerMethod.Name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Static); - if (genericMethod is null || !genericMethod.ContainsGenericParameters) - { - ThrowHelper.ThrowArgumentException($"Error retrieving handler method {handlerMethod.Name} from declaring type definition {genericTypeDefinition.FullName}"); - } - - handlerMethod = genericMethod; - FullType = genericTypeDefinition.FullName ?? typeToken; - Assembly = declaringType.Assembly.GetName().Name ?? assemblyToken; - } - else - { - // TODO: Check if lambda allows closing generics - // E.g. if a type is defined as - // public class MyFunctionHandlerClass - // { - // void Handler(T input) {} - // } - // Can I pass this in the handler? - // MyFunction::MyFunction.MyFunctionHandlerClass::Handler - // Assuming that's _not_ valid for now - - FullType = (declaringType ?? handlerType).FullName ?? typeToken; - - // If the handlerType == the declaring type, skip calling Assembly.GetName - // and use handler token directly, as we know it's the same - Assembly = handlerType == declaringType - ? assemblyToken - : declaringType?.Assembly.GetName().Name ?? assemblyToken; - } - - MethodName = handlerMethod.Name; - var methodParameters = handlerMethod.GetParameters(); - - var paramType = new string[methodParameters.Length + 1]; - paramType[0] = GetParameterTypeFullName(handlerMethod.ReturnType); - for (var i = 0; i < methodParameters.Length; i++) - { - paramType[i + 1] = GetParameterTypeFullName(methodParameters[i].ParameterType); // assumes it's not a generic type return etc - } - - ParamTypeArray = paramType; - } - - internal string[] ParamTypeArray { get; } - - internal string Assembly { get; } - - internal string FullType { get; } - - internal string MethodName { get; } - - private static string GetParameterTypeFullName(Type type) - { - // If the parameter is `T` or `TRequest` for example, then return `!0` or `!1` - // As we don't support instrumenting generic methods (because AWS doesn't) - // we don't need to worry about `!!0` or `!!1` - if (type.IsGenericParameter) - { - return $"!{type.GenericParameterPosition}"; - } - - // If the type is generic e.g. List - // - If the type is nested, or in the global namespace, don't include the namespace - // - Otherwise, do include the namespace - if (type.ContainsGenericParameters || type.IsGenericType) - { - return type is { IsNested: false, Namespace: { Length: > 0 } ns } - ? $"{ns}.{type.Name}[{GetGenericTypeArguments(type)}]" - : $"{type.Name}[{GetGenericTypeArguments(type)}]"; // global namespace - } - - // Not generic - // - Don't include namespace for nested types - // - Do include it for other types - return type.IsNested ? type.Name : type.ToString(); - } - - private static string GetGenericTypeArguments(Type type) - { - // This isn't ideal, as if we have nested type arguments we - // Get the SB twice and concatenate but it avoids annoying - // recursive complexity, and is an edge case, so I think it's fine - var sb = StringBuilderCache.Acquire(StringBuilderCache.MaxBuilderSize); - - var doneFirst = false; - foreach (var argument in type.GetGenericArguments()) - { - if (doneFirst) - { - sb.Append(','); - } - else - { - doneFirst = true; - } - - sb.Append(GetParameterTypeFullName(argument)); - } - - return StringBuilderCache.GetStringAndRelease(sb); - } -} diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaMetadata.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaMetadata.cs index e49d3de05701..beaa568870c8 100644 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaMetadata.cs +++ b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/LambdaMetadata.cs @@ -53,7 +53,7 @@ public static LambdaMetadata Create(string extensionPath = ExtensionFullPath) } var handlerName = EnvironmentHelpers.GetEnvironmentVariable(HandlerEnvVar); - var serviceName = handlerName?.IndexOf(LambdaHandler.Separator, StringComparison.Ordinal) switch + var serviceName = handlerName?.IndexOf("::", StringComparison.Ordinal) switch { null => null, // not provided 0 => null, // invalid handler name (no assembly) diff --git a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/Serverless.cs b/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/Serverless.cs deleted file mode 100644 index 1c971d2a94d2..000000000000 --- a/tracer/src/Datadog.Trace/ClrProfiler/ServerlessInstrumentation/Serverless.cs +++ /dev/null @@ -1,143 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using Datadog.Trace.Util; - -namespace Datadog.Trace.ClrProfiler.ServerlessInstrumentation -{ - internal static class Serverless - { - private const string DefinitionsId = "68224F20D001430F9400668DD25245BA"; - private const string LogLevelEnvName = "DD_LOG_LEVEL"; - - private static NativeCallTargetDefinition[] callTargetDefinitions = null; - - internal static void InitIfNeeded(LambdaMetadata metadata) - { - if (metadata is { IsRunningInLambda: true, HandlerName: var handlerName }) - { - if (string.IsNullOrEmpty(handlerName)) - { - Error("Error initializing serverless integration: handler name not found"); - return; - } - - Debug("Sending CallTarget serverless integration definitions to native library."); - var serverlessDefinitions = GetServerlessDefinitions(handlerName); - NativeMethods.InitializeProfiler(DefinitionsId, serverlessDefinitions); - - Debug("The profiler has been initialized with serverless definitions, count = " + serverlessDefinitions.Length); - } - } - - internal static string GetIntegrationType(string returnType, int paramCount) - { - var inputParamCount = paramCount - 1; // since the return type is in the array - if (returnType.Equals(ClrNames.Void)) - { - return GetVoidIntegrationTypeFromParamCount(inputParamCount); - } - - if (returnType.StartsWith(ClrNames.Task)) - { - return GetAsyncIntegrationTypeFromParamCount(inputParamCount); - } - - return GetSyncIntegrationTypeFromParamCount(inputParamCount); - } - - internal static string GetAsyncIntegrationTypeFromParamCount(int paramCount) - { - switch (paramCount) - { - case 0: - return typeof(AWS.LambdaNoParamAsync).FullName; - case 1: - return typeof(AWS.LambdaOneParamAsync).FullName; - case 2: - return typeof(AWS.LambdaTwoParamsAsync).FullName; - default: - throw new ArgumentOutOfRangeException("AWS Lambda handler number of params can only be 0, 1 or 2."); - } - } - - internal static string GetSyncIntegrationTypeFromParamCount(int paramCount) - { - switch (paramCount) - { - case 0: - return typeof(AWS.LambdaNoParamSync).FullName; - case 1: - return typeof(AWS.LambdaOneParamSync).FullName; - case 2: - return typeof(AWS.LambdaTwoParamsSync).FullName; - default: - throw new ArgumentOutOfRangeException("AWS Lambda handler number of params can only be 0, 1 or 2."); - } - } - - internal static string GetVoidIntegrationTypeFromParamCount(int paramCount) - { - switch (paramCount) - { - case 0: - return typeof(AWS.LambdaNoParamVoid).FullName; - case 1: - return typeof(AWS.LambdaOneParamVoid).FullName; - case 2: - return typeof(AWS.LambdaTwoParamsVoid).FullName; - default: - throw new ArgumentOutOfRangeException("AWS Lambda handler number of params can only be 0, 1 or 2."); - } - } - - internal static void Debug(string str) - { - if (EnvironmentHelpers.GetEnvironmentVariable(LogLevelEnvName)?.ToLower() == "debug") - { - Console.WriteLine("{0} {1}", DateTime.UtcNow.ToString("yyyy-MM-dd MM:mm:ss:fff"), str); - } - } - - internal static void Error(string message, Exception ex = null) - { - Console.WriteLine($"{DateTime.UtcNow:yyyy-MM-dd HH:mm:ss:fff} {message} {ex?.ToString().Replace("\n", "\\n")}"); - } - - private static void RunShutdown() - { - callTargetDefinitions = null; - } - - private static NativeCallTargetDefinition[] GetServerlessDefinitions(string handlerName) - { - try - { - if (callTargetDefinitions == null) - { - LambdaHandler handler = new LambdaHandler(handlerName); - var assemblyName = typeof(InstrumentationDefinitions).Assembly.FullName; - var paramCount = handler.ParamTypeArray.Length; - - var integrationType = GetIntegrationType(handler.ParamTypeArray[0], paramCount); - callTargetDefinitions = new NativeCallTargetDefinition[] - { - new(handler.Assembly, handler.FullType, handler.MethodName, handler.ParamTypeArray, 0, 0, 0, 65535, 65535, 65535, assemblyName, integrationType) - }; - - LifetimeManager.Instance.AddShutdownTask(RunShutdown); - } - - return callTargetDefinitions; - } - catch (Exception ex) - { - Error("Impossible to get Serverless Definitions", ex); - return Array.Empty(); - } - } - } -} diff --git a/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs b/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs index 9018dbfad71a..2cc0ad2d67cf 100644 --- a/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs +++ b/tracer/src/Datadog.Trace/Configuration/IntegrationId.cs @@ -40,6 +40,7 @@ internal enum IntegrationId AwsSdk, AwsSqs, AwsSns, + AwsLambda, ILogger, Aerospike, AzureFunctions, diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 097ce56647ae..454cc7138a23 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 53; + public const int Length = 54; /// /// Returns the string representation of the value. @@ -58,6 +58,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.AwsSdk => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), Datadog.Trace.Configuration.IntegrationId.AwsSqs => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), Datadog.Trace.Configuration.IntegrationId.AwsSns => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + Datadog.Trace.Configuration.IntegrationId.AwsLambda => nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), Datadog.Trace.Configuration.IntegrationId.ILogger => nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), Datadog.Trace.Configuration.IntegrationId.Aerospike => nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), Datadog.Trace.Configuration.IntegrationId.AzureFunctions => nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), @@ -124,6 +125,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.AwsSdk, Datadog.Trace.Configuration.IntegrationId.AwsSqs, Datadog.Trace.Configuration.IntegrationId.AwsSns, + Datadog.Trace.Configuration.IntegrationId.AwsLambda, Datadog.Trace.Configuration.IntegrationId.ILogger, Datadog.Trace.Configuration.IntegrationId.Aerospike, Datadog.Trace.Configuration.IntegrationId.AzureFunctions, @@ -190,6 +192,7 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs index a5e52c6e4014..da5de4c81888 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class CiVisibilityMetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs index e22763d9d43c..eb5154e1c0b6 100644 --- a/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net461/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class MetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 097ce56647ae..454cc7138a23 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 53; + public const int Length = 54; /// /// Returns the string representation of the value. @@ -58,6 +58,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.AwsSdk => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), Datadog.Trace.Configuration.IntegrationId.AwsSqs => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), Datadog.Trace.Configuration.IntegrationId.AwsSns => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + Datadog.Trace.Configuration.IntegrationId.AwsLambda => nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), Datadog.Trace.Configuration.IntegrationId.ILogger => nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), Datadog.Trace.Configuration.IntegrationId.Aerospike => nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), Datadog.Trace.Configuration.IntegrationId.AzureFunctions => nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), @@ -124,6 +125,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.AwsSdk, Datadog.Trace.Configuration.IntegrationId.AwsSqs, Datadog.Trace.Configuration.IntegrationId.AwsSns, + Datadog.Trace.Configuration.IntegrationId.AwsLambda, Datadog.Trace.Configuration.IntegrationId.ILogger, Datadog.Trace.Configuration.IntegrationId.Aerospike, Datadog.Trace.Configuration.IntegrationId.AzureFunctions, @@ -190,6 +192,7 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs index 3087714f9312..586acbd38ecd 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/InstrumentationDefinitionsGenerator/InstrumentationDefinitions.g.cs @@ -81,6 +81,9 @@ static InstrumentationDefinitions() new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("AWSSDK.Kinesis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Kinesis.AmazonKinesisClient"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("PutRecords"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("Amazon.Kinesis.Model.PutRecordsResponse", "Amazon.Kinesis.Model.PutRecordsRequest"), 2, 3, 0, 0, 3, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Kinesis.PutRecordsIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("AWSSDK.Kinesis"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Kinesis.AmazonKinesisClient"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("PutRecordsAsync"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[Amazon.Kinesis.Model.PutRecordsResponse]", "Amazon.Kinesis.Model.PutRecordsRequest", "System.Threading.CancellationToken"), 3, 3, 0, 0, 3, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Kinesis.PutRecordsAsyncIntegration"), 0, 1), + // AwsLambda + new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Lambda.RuntimeSupport"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Lambda.RuntimeSupport.HandlerWrapper"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("set_Handler"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Void", "Amazon.Lambda.RuntimeSupport.LambdaBootstrapHandler"), 2, 1, 4, 0, 1, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda.HandlerWrapperSetHandlerIntegration"), 0, 1), + // AwsSdk new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("AWSSDK.Core"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Runtime.Internal.RuntimePipeline"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("InvokeAsync"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("System.Threading.Tasks.Task`1[!0]", "Amazon.Runtime.IExecutionContext"), 2, 3, 0, 0, 3, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK.RuntimePipelineInvokeAsyncIntegration"), 0, 1), new (NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("AWSSDK.Core"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Amazon.Runtime.Internal.RuntimePipeline"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("InvokeSync"), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16StringArray("Amazon.Runtime.IResponseContext", "Amazon.Runtime.IExecutionContext"), 2, 3, 0, 0, 3, 65535, 65535, NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String(assemblyFullName), NativeCallTargetUnmanagedMemoryHelper.AllocateAndWriteUtf16String("Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK.RuntimePipelineInvokeSyncIntegration"), 0, 1), @@ -537,6 +540,8 @@ static InstrumentationDefinitions() or "Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Kinesis.PutRecordsIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Kinesis.PutRecordsAsyncIntegration" => Datadog.Trace.Configuration.IntegrationId.AwsKinesis, + "Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda.HandlerWrapperSetHandlerIntegration" + => Datadog.Trace.Configuration.IntegrationId.AwsLambda, "Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK.RuntimePipelineInvokeAsyncIntegration" or "Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.SDK.RuntimePipelineInvokeSyncIntegration" => Datadog.Trace.Configuration.IntegrationId.AwsSdk, diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs index a5e52c6e4014..da5de4c81888 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class CiVisibilityMetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs index e22763d9d43c..eb5154e1c0b6 100644 --- a/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/net6.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class MetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 097ce56647ae..454cc7138a23 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 53; + public const int Length = 54; /// /// Returns the string representation of the value. @@ -58,6 +58,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.AwsSdk => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), Datadog.Trace.Configuration.IntegrationId.AwsSqs => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), Datadog.Trace.Configuration.IntegrationId.AwsSns => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + Datadog.Trace.Configuration.IntegrationId.AwsLambda => nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), Datadog.Trace.Configuration.IntegrationId.ILogger => nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), Datadog.Trace.Configuration.IntegrationId.Aerospike => nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), Datadog.Trace.Configuration.IntegrationId.AzureFunctions => nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), @@ -124,6 +125,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.AwsSdk, Datadog.Trace.Configuration.IntegrationId.AwsSqs, Datadog.Trace.Configuration.IntegrationId.AwsSns, + Datadog.Trace.Configuration.IntegrationId.AwsLambda, Datadog.Trace.Configuration.IntegrationId.ILogger, Datadog.Trace.Configuration.IntegrationId.Aerospike, Datadog.Trace.Configuration.IntegrationId.AzureFunctions, @@ -190,6 +192,7 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs index a5e52c6e4014..da5de4c81888 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class CiVisibilityMetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs index e22763d9d43c..eb5154e1c0b6 100644 --- a/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netcoreapp3.1/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class MetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs index 097ce56647ae..454cc7138a23 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/EnumExtensionsGenerator/IntegrationIdExtensions_EnumExtensions.g.cs @@ -17,7 +17,7 @@ internal static partial class IntegrationIdExtensions /// The number of members in the enum. /// This is a non-distinct count of defined names. /// - public const int Length = 53; + public const int Length = 54; /// /// Returns the string representation of the value. @@ -58,6 +58,7 @@ public static string ToStringFast(this Datadog.Trace.Configuration.IntegrationId Datadog.Trace.Configuration.IntegrationId.AwsSdk => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), Datadog.Trace.Configuration.IntegrationId.AwsSqs => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), Datadog.Trace.Configuration.IntegrationId.AwsSns => nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + Datadog.Trace.Configuration.IntegrationId.AwsLambda => nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), Datadog.Trace.Configuration.IntegrationId.ILogger => nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), Datadog.Trace.Configuration.IntegrationId.Aerospike => nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), Datadog.Trace.Configuration.IntegrationId.AzureFunctions => nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), @@ -124,6 +125,7 @@ public static Datadog.Trace.Configuration.IntegrationId[] GetValues() Datadog.Trace.Configuration.IntegrationId.AwsSdk, Datadog.Trace.Configuration.IntegrationId.AwsSqs, Datadog.Trace.Configuration.IntegrationId.AwsSns, + Datadog.Trace.Configuration.IntegrationId.AwsLambda, Datadog.Trace.Configuration.IntegrationId.ILogger, Datadog.Trace.Configuration.IntegrationId.Aerospike, Datadog.Trace.Configuration.IntegrationId.AzureFunctions, @@ -190,6 +192,7 @@ public static string[] GetNames() nameof(Datadog.Trace.Configuration.IntegrationId.AwsSdk), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSqs), nameof(Datadog.Trace.Configuration.IntegrationId.AwsSns), + nameof(Datadog.Trace.Configuration.IntegrationId.AwsLambda), nameof(Datadog.Trace.Configuration.IntegrationId.ILogger), nameof(Datadog.Trace.Configuration.IntegrationId.Aerospike), nameof(Datadog.Trace.Configuration.IntegrationId.AzureFunctions), diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs index a5e52c6e4014..da5de4c81888 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/CiVisibilityMetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class CiVisibilityMetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs index e22763d9d43c..eb5154e1c0b6 100644 --- a/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs +++ b/tracer/src/Datadog.Trace/Generated/netstandard2.0/Datadog.Trace.SourceGenerators/TelemetryMetricGenerator/MetricsTelemetryCollector_DistributionShared.g.cs @@ -11,7 +11,7 @@ namespace Datadog.Trace.Telemetry; internal partial class MetricsTelemetryCollector { - private const int DistributionSharedLength = 14; + private const int DistributionSharedLength = 13; /// /// Creates the buffer for the values. @@ -26,7 +26,6 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() new(new[] { "component:traceattributes_pinvoke" }), new(new[] { "component:managed" }), new(new[] { "component:calltarget_defs_pinvoke" }), - new(new[] { "component:serverless" }), new(new[] { "component:calltarget_derived_defs_pinvoke" }), new(new[] { "component:calltarget_interface_defs_pinvoke" }), new(new[] { "component:discovery_service" }), @@ -42,7 +41,7 @@ private static AggregatedDistribution[] GetDistributionSharedBuffer() /// It is equal to the cardinality of the tag combinations (or 1 if there are no tags) /// private static int[] DistributionSharedEntryCounts { get; } - = new int[]{ 14, }; + = new int[]{ 13, }; public void RecordDistributionSharedInitTime(Datadog.Trace.Telemetry.Metrics.MetricTags.InitializationComponent tag, double value) { diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs index 81cd9a4597ad..cdcccdc55732 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/IntegrationIdExtensions.cs @@ -41,6 +41,7 @@ public static MetricTags.IntegrationName GetMetricTag(this IntegrationId integra IntegrationId.AwsSdk => MetricTags.IntegrationName.AwsSdk, IntegrationId.AwsSns => MetricTags.IntegrationName.AwsSns, IntegrationId.AwsSqs => MetricTags.IntegrationName.AwsSqs, + IntegrationId.AwsLambda => MetricTags.IntegrationName.AwsLambda, IntegrationId.ILogger => MetricTags.IntegrationName.ILogger, IntegrationId.Aerospike => MetricTags.IntegrationName.Aerospike, IntegrationId.AzureFunctions => MetricTags.IntegrationName.AzureFunctions, diff --git a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs index e3b1dcac7749..e18428f66d05 100644 --- a/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs +++ b/tracer/src/Datadog.Trace/Telemetry/Metrics/MetricTags.cs @@ -29,7 +29,6 @@ internal enum InitializationComponent [Description("component:traceattributes_pinvoke")] TraceAttributesPinvoke, [Description("component:managed")] Managed, [Description("component:calltarget_defs_pinvoke")] CallTargetDefsPinvoke, - [Description("component:serverless")] Serverless, [Description("component:calltarget_derived_defs_pinvoke")] CallTargetDerivedDefsPinvoke, [Description("component:calltarget_interface_defs_pinvoke")] CallTargetInterfaceDefsPinvoke, [Description("component:discovery_service")] DiscoveryService, diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/AwsLambdaTests.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/AwsLambdaTests.cs index f02a36ace4e9..9a663815cde3 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/AwsLambdaTests.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/AWS/AwsLambdaTests.cs @@ -54,7 +54,9 @@ public async Task SubmitsTraces() + 5 // base instrumentation + 6 // other parameter types + 3 // throwing (manual only) - + 3; // throwing with context + + 3 // throwing with context + + 8 // Generic types + + 1; // Toplevel Statement var expectedSpans = requests * 2; // we manually instrument each request too diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersions.g.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersions.g.cs index 92124f337784..245f6930bfaf 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersions.g.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersions.g.cs @@ -30,6 +30,8 @@ public class PackageVersions public static IEnumerable AwsKinesis => IsAllMinorPackageVersions ? PackageVersionsLatestMinors.AwsKinesis : PackageVersionsLatestSpecific.AwsKinesis; + public static IEnumerable AwsLambda => IsAllMinorPackageVersions ? PackageVersionsLatestMinors.AwsLambda : PackageVersionsLatestSpecific.AwsLambda; + public static IEnumerable AwsSqs => IsAllMinorPackageVersions ? PackageVersionsLatestMinors.AwsSqs : PackageVersionsLatestSpecific.AwsSqs; public static IEnumerable AwsSns => IsAllMinorPackageVersions ? PackageVersionsLatestMinors.AwsSns : PackageVersionsLatestSpecific.AwsSns; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMajors.g.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMajors.g.cs index d529a747aad5..da1c19b96dcd 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMajors.g.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMajors.g.cs @@ -78,6 +78,22 @@ public class PackageVersionsLatestMajors #if NET7_0 new object[] { "3.7.200.58" }, #endif +#endif + }; + + public static IEnumerable AwsLambda => + + new List + { +#if DEFAULT_SAMPLES + new object[] { string.Empty }, +#else +#if NET6_0 + new object[] { "1.9.0" }, +#endif +#if NET7_0 + new object[] { "1.9.0" }, +#endif #endif }; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMinors.g.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMinors.g.cs index 145fa696efa8..fc4051f1bb4b 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMinors.g.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestMinors.g.cs @@ -108,6 +108,32 @@ public class PackageVersionsLatestMinors new object[] { "3.5.0.79" }, new object[] { "3.7.200.58" }, #endif +#endif + }; + + public static IEnumerable AwsLambda => + + new List + { +#if DEFAULT_SAMPLES + new object[] { string.Empty }, +#else +#if NET6_0 + new object[] { "1.4.0" }, + new object[] { "1.5.0" }, + new object[] { "1.6.0" }, + new object[] { "1.7.0" }, + new object[] { "1.8.8" }, + new object[] { "1.9.0" }, +#endif +#if NET7_0 + new object[] { "1.4.0" }, + new object[] { "1.5.0" }, + new object[] { "1.6.0" }, + new object[] { "1.7.0" }, + new object[] { "1.8.8" }, + new object[] { "1.9.0" }, +#endif #endif }; diff --git a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestSpecific.g.cs b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestSpecific.g.cs index b53b0a3bb66b..1cc535de591a 100644 --- a/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestSpecific.g.cs +++ b/tracer/test/Datadog.Trace.ClrProfiler.IntegrationTests/PackageVersionsLatestSpecific.g.cs @@ -94,6 +94,22 @@ public class PackageVersionsLatestSpecific new object[] { "3.3.101.1" }, new object[] { "3.7.200.58" }, #endif +#endif + }; + + public static IEnumerable AwsLambda => + + new List + { +#if DEFAULT_SAMPLES + new object[] { string.Empty }, +#else +#if NET6_0 + new object[] { "1.8.8" }, +#endif +#if NET7_0 + new object[] { "1.8.8" }, +#endif #endif }; diff --git a/tracer/test/Datadog.Trace.Tests/LambdaCommonTests.cs b/tracer/test/Datadog.Trace.Tests/LambdaCommonTests.cs index 341b8a0d0ee0..c50ea096be7a 100644 --- a/tracer/test/Datadog.Trace.Tests/LambdaCommonTests.cs +++ b/tracer/test/Datadog.Trace.Tests/LambdaCommonTests.cs @@ -2,13 +2,12 @@ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // - +#if NET6_0_OR_GREATER using System; using System.Collections.Generic; using System.IO; using System.Net; -using System.Text; -using Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS; +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; using Datadog.Trace.TestHelpers; using FluentAssertions; @@ -163,7 +162,7 @@ public void TestSendEndInvocationFailure() [Fact] [Trait("Category", "ArmUnsupported")] - public void TestSendEndInvocationTrue() + public void TestSendEndInvocationSuccess() { var tracer = TracerHelper.Create(); var scope = LambdaCommon.CreatePlaceholderScope(tracer, "1234", "-1"); @@ -177,8 +176,11 @@ public void TestSendEndInvocationTrue() httpRequest.Setup(h => h.GetRequestStream()).Returns(responseStream.Object); _lambdaRequestMock.Setup(lr => lr.GetEndInvocationRequest(scope, true)).Returns(httpRequest.Object); - - LambdaCommon.SendEndInvocation(_lambdaRequestMock.Object, scope, true, "{}").Should().Be(true); + var output = new StringWriter(); + Console.SetOut(output); + LambdaCommon.SendEndInvocation(_lambdaRequestMock.Object, scope, true, "{}"); + httpRequest.Verify(r => r.GetResponse(), Times.Once); + Assert.Empty(output.ToString()); } [Fact] @@ -197,48 +199,12 @@ public void TestSendEndInvocationFalse() httpRequest.Setup(h => h.GetRequestStream()).Returns(responseStream.Object); _lambdaRequestMock.Setup(lr => lr.GetEndInvocationRequest(scope, true)).Returns(httpRequest.Object); - - LambdaCommon.SendEndInvocation(_lambdaRequestMock.Object, scope, true, "{}").Should().Be(false); - } - - [Fact] - public void SerializeObject_WithDictionary_ParsesCorrectlyToJsonString() - { - DateTime date = new(2023, 1, 7); - const string jsonString = @"{ ""general"": ""kenobi"" }"; - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); - Dictionary dictionary = new() - { - { "date", date }, - { "hello", "there" }, - { "memoryStream", memoryStream } - }; - - const string expectedValue = @"{""date"":1673049600.0,""hello"":""there"",""memoryStream"":""eyAiZ2VuZXJhbCI6ICJrZW5vYmkiIH0=""}"; - var result = LambdaCommon.SerializeObject(dictionary); - - result.Should().Be(expectedValue); - } - - [Fact] - public void SerializeObject_WithMemoryStream_ParsesCorrectlyToBase64String() - { - const string jsonString = @"{ ""hello"": ""there"" }"; - const string expectedValue = "\"eyAiaGVsbG8iOiAidGhlcmUiIH0=\""; - var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(jsonString)); - var result = LambdaCommon.SerializeObject(memoryStream); - - result.Should().Be(expectedValue); - } - - [Fact] - public void SerializeObject_WithDateTime_ParsesCorrectlyToUnixEpochSeconds() - { - DateTime date = new(2023, 1, 7); - const string expectedValue = "1673049600.0"; - var result = LambdaCommon.SerializeObject(date); - - result.Should().Be(expectedValue); + var output = new StringWriter(); + Console.SetOut(output); + LambdaCommon.SendEndInvocation(_lambdaRequestMock.Object, scope, true, "{}"); + httpRequest.Verify(r => r.GetResponse(), Times.Once); + Assert.Contains("Extension does not send a status 200 OK", output.ToString()); } } } +#endif diff --git a/tracer/test/Datadog.Trace.Tests/LambdaHandlerTests.cs b/tracer/test/Datadog.Trace.Tests/LambdaHandlerTests.cs deleted file mode 100644 index 3d20404e8082..000000000000 --- a/tracer/test/Datadog.Trace.Tests/LambdaHandlerTests.cs +++ /dev/null @@ -1,455 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.Collections.Generic; -using System.Threading.Tasks; -using Datadog.Trace.ClrProfiler; -using Datadog.Trace.ClrProfiler.ServerlessInstrumentation; -using Datadog.Trace.TestHelpers; -using FluentAssertions; -using Xunit; - -namespace Datadog.Trace.Tests -{ -#pragma warning disable SA1402 // File may only contain a single type - public class LambdaHandlerTests - { - [Fact] - public void LambdaHandlerGetters() - { - LambdaHandler handler = new LambdaHandler("mscorlib::System.Environment::ExpandEnvironmentVariables"); - handler.Assembly.Should().Be("mscorlib"); - handler.FullType.Should().Be("System.Environment"); - handler.MethodName.Should().Be("ExpandEnvironmentVariables"); - } - - [Fact] - public void LambdaHandlerParamTypeArray() - { - LambdaHandler handler = new LambdaHandler("mscorlib::System.Environment::ExpandEnvironmentVariables"); - handler.ParamTypeArray.Length.Should().Be(2); - handler.ParamTypeArray[0].Should().Be("System.String"); - handler.ParamTypeArray[1].Should().Be("System.String"); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::HandlerMethod", "Datadog.Trace.Tests.TestHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::HiddenBaseMethod", "Datadog.Trace.Tests.TestHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::OverridenBaseMethod", "Datadog.Trace.Tests.TestHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler2::AbstractBaseMethod", "Datadog.Trace.Tests.TestHandler2")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler3::AbstractBaseMethod", "Datadog.Trace.Tests.TestHandler3")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::BaseHandlerMethod", "Datadog.Trace.Tests.BaseHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::NonOverridenBaseMethod", "Datadog.Trace.Tests.BaseHandler")] - public void LambdaHandlerCanParseCustomType(string handlerVariable, string expectedType) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.FullType.Should().Be(expectedType); - handler.ParamTypeArray.Length.Should().Be(1); - handler.ParamTypeArray[0].Should().Be(ClrNames.Void); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler3::AbstractGenericBaseMethod1", "Datadog.Trace.Tests.TestHandler3", "AbstractGenericBaseMethod1")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler3::AbstractGenericBaseMethod2", "Datadog.Trace.Tests.TestHandler3", "AbstractGenericBaseMethod2")] - public void LambdaHandlerCanHandleClosedGenericTypes(string handlerVariable, string expectedType, string expectedMethod) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.Assembly.Should().Be("Datadog.Trace.Tests"); - handler.FullType.Should().Be(expectedType); - handler.MethodName.Should().Be(expectedMethod); - handler.ParamTypeArray.Length.Should().Be(2); - handler.ParamTypeArray[0].Should().Be(ClrNames.Int32); - handler.ParamTypeArray[1].Should().Be(ClrNames.Int32); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.ShadowTest::AbstractFunctionInGeneric", "Datadog.Trace.Tests.ShadowTest", "AbstractFunctionInGeneric", ClrNames.String, ClrNames.String)] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.ShadowTest::VirtualFunctionInGeneric", "Datadog.Trace.Tests.ShadowTest", "VirtualFunctionInGeneric", ClrNames.String, ClrNames.String)] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.ShadowTest::ShadowedFunctionInGeneric", "Datadog.Trace.Tests.ShadowTest", "ShadowedFunctionInGeneric", ClrNames.String, ClrNames.String)] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.ShadowTest+Nested::ShadowedFunctionInGeneric", "Datadog.Trace.Tests.ShadowTest+Nested", "ShadowedFunctionInGeneric", ClrNames.String, ClrNames.String)] - public void LambdaHandlerCanHandleShadowing(string handlerVariable, string expectedType, string expectedMethod, params string[] args) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.Assembly.Should().Be("Datadog.Trace.Tests"); - handler.FullType.Should().Be(expectedType); - handler.MethodName.Should().Be(expectedMethod); - handler.ParamTypeArray.Should().BeEquivalentTo(args, opts => opts.WithStrictOrdering()); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler4::GenericBaseMethod1", "Datadog.Trace.Tests.GenericBaseHandler`1", "GenericBaseMethod1", ClrNames.Void, "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler4::GenericBaseMethod2", "Datadog.Trace.Tests.GenericBaseHandler`1", "GenericBaseMethod2", "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod1", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod1", ClrNames.Void, "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod2", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod2", "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod3", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod3", ClrNames.Void, "!1")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod4", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod4", "!1")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod5", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod5", "!1", "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod6", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod6", ClrNames.Void, "!0", "!1")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler5::GenericBaseMethod7", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod7", "System.Threading.Tasks.Task`1[!0]", "System.Threading.Tasks.Task`1[!1]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler6::GenericBaseMethod5", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod5", "!1", "!0")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler6::GenericBaseMethod6", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod6", ClrNames.Void, "!0", "!1")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler6::GenericBaseMethod7", "Datadog.Trace.Tests.GenericBaseHandler2`2", "GenericBaseMethod7", "System.Threading.Tasks.Task`1[!0]", "System.Threading.Tasks.Task`1[!1]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler7+Nested::Handler", "Datadog.Trace.Tests.TrickyParamHandler+NestedGeneric`2", "Handler", "System.Threading.Tasks.Task`1[System.Tuple`2[!0,NestedGeneric`2[!0,!1]]]", "System.Tuple`2[!0,NestedGeneric`2[!0,!1]]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.FunctionImplementation::FunctionHandlerAsync", "Datadog.Trace.Tests.AbstractAspNetCoreFunction`2", "FunctionHandlerAsync", "System.Threading.Tasks.Task`1[!1]", "!0", "Datadog.Trace.Tests.ILambdaContext")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.DerivedImplementation::ComplexNestedGeneric", "Datadog.Trace.Tests.GenericBase`2", "ComplexNestedGeneric", "Datadog.Trace.Tests.GenericBase`2[Datadog.Trace.Tests.CustomInput,InnerGeneric`2[!0,!1]]", "!0", "InnerGeneric`2[!0,NestedInSameType`2[!0,!1,!0,System.Collections.Generic.Dictionary`2[System.String,DeepNested`1[!0,!1,!1]]]]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.DerivedImplementation::NonGenericFunction", "Datadog.Trace.Tests.GenericBase`2", "NonGenericFunction", ClrNames.Task, ClrNames.String, "Datadog.Trace.Tests.ILambdaContext")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.DerivedImplementation+NestedDerived::ComplexNestedGeneric", "Datadog.Trace.Tests.GenericBase`2", "ComplexNestedGeneric", "Datadog.Trace.Tests.GenericBase`2[Datadog.Trace.Tests.CustomInput,InnerGeneric`2[!0,!1]]", "!0", "InnerGeneric`2[!0,NestedInSameType`2[!0,!1,!0,System.Collections.Generic.Dictionary`2[System.String,DeepNested`1[!0,!1,!1]]]]")] - public void LambdaHandlerCanHandleOpenGenericTypes(string handlerVariable, string expectedType, string expectedMethod, params string[] args) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.Assembly.Should().Be("Datadog.Trace.Tests"); - handler.FullType.Should().Be(expectedType); - handler.MethodName.Should().Be(expectedMethod); - handler.ParamTypeArray.Should().BeEquivalentTo(args, opts => opts.WithStrictOrdering()); - } - - [Theory] - [InlineData("")] - [InlineData("::")] - [InlineData("A::B")] - [InlineData("A:::B")] - [InlineData("A::B::C::")] - [InlineData("A::B::C::D")] - public void LambdaHandlerThrowsWhenInvalidFormat(string handlerVariable) - { - Assert.Throws(() => new LambdaHandler(handlerVariable)); - } - - [Theory] - [InlineData("SomeType::Unknown::WhoKnows")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler::IdontExistAnywhere")] - [InlineData("SomeType::::WhoKnows")] - [InlineData("SomeType::::")] - public void LambdaHandlerThrowsWhenUnknownTypes(string handlerVariable) - { - Assert.Throws(() => new LambdaHandler(handlerVariable)); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler4::GenericBaseMethod3")] - public void LambdaHandlerThrowsWhenInstrumentingGenericMethods(string handlerVariable) - { - // We don't support this yet (we could, we just haven't done the work for it yet) - Assert.Throws(() => new LambdaHandler(handlerVariable)); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler+NestedHandler::HandlerMethod", "Datadog.Trace.Tests.TestHandler+NestedHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler+NestedHandler::HiddenBaseMethod", "Datadog.Trace.Tests.TestHandler+NestedHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler+NestedHandler::OverridenBaseMethod", "Datadog.Trace.Tests.TestHandler+NestedHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler+NestedHandler::BaseHandlerMethod", "Datadog.Trace.Tests.BaseHandler")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TestHandler+NestedHandler::NonOverridenBaseMethod", "Datadog.Trace.Tests.BaseHandler")] - public void LambdaHandlerCanHandleNestedTypes(string handlerVariable, string expectedType) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.Assembly.Should().Be("Datadog.Trace.Tests"); - handler.FullType.Should().Be(expectedType); - handler.ParamTypeArray.Length.Should().Be(1); - handler.ParamTypeArray[0].Should().Be(ClrNames.Void); - } - - [Fact] - public void LambdaHandlerCanParseTypesAcrossAssemblies() - { - var handlerName = "Datadog.Trace.Tests::Datadog.Trace.Tests.TestMockSpan::GetTag"; - LambdaHandler handler = new LambdaHandler(handlerName); - handler.Assembly.Should().Be("Datadog.Trace.TestHelpers"); - handler.FullType.Should().Be("Datadog.Trace.TestHelpers.MockSpan"); - handler.MethodName.Should().Be("GetTag"); - handler.ParamTypeArray.Length.Should().Be(2); - handler.ParamTypeArray[0].Should().Be(ClrNames.String); - handler.ParamTypeArray[1].Should().Be(ClrNames.String); - } - - [Theory] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::GenericArguments", "GenericArguments", "System.Collections.Generic.Dictionary`2[System.String,System.String]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::NestedClassArgument", "NestedClassArgument", "NestedClass")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::DoublyNestedClassArgument", "DoublyNestedClassArgument", "Inner")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::NestedStructArgument", "NestedStructArgument", "NestedStruct")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::NestedGenericArguments", "NestedGenericArguments", "NestedGeneric`2[System.String,System.String]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::DoublyNestedGenericArguments", "DoublyNestedGenericArguments", "InnerGeneric`2[System.String,System.String]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::RecursiveGenericArguments", "RecursiveGenericArguments", "System.Collections.Generic.Dictionary`2[System.String,System.Collections.Generic.Dictionary`2[System.String,System.String]]")] - [InlineData("Datadog.Trace.Tests::Datadog.Trace.Tests.TrickyParamHandler::NestedRecursiveGenericArguments", "NestedRecursiveGenericArguments", "NestedGeneric`2[System.String,NestedGeneric`2[System.String,System.Collections.Generic.Dictionary`2[System.String,System.String]]]")] - public void LambdaHandlerCanHandleTrickyArguments(string handlerVariable, string expectedMethod, string expectedArg) - { - LambdaHandler handler = new LambdaHandler(handlerVariable); - handler.Assembly.Should().Be("Datadog.Trace.Tests"); - handler.FullType.Should().Be("Datadog.Trace.Tests.TrickyParamHandler"); - handler.MethodName.Should().Be(expectedMethod); - handler.ParamTypeArray.Length.Should().Be(2); - handler.ParamTypeArray[0].Should().Be(ClrNames.Int32); - handler.ParamTypeArray[1].Should().Be(expectedArg); - } - } - - public class TestHandler : BaseHandler - { - public void HandlerMethod() - { - } - - public new void HiddenBaseMethod() - { - } - - public override void OverridenBaseMethod() - { - } - - public class NestedHandler : BaseHandler - { - public void HandlerMethod() - { - } - - public new void HiddenBaseMethod() - { - } - - public override void OverridenBaseMethod() - { - } - } - } - - public class TestHandler2 : AbstractBaseHandler - { - public override void AbstractBaseMethod() - { - } - } - - public class TestHandler3 : AbstractGenericBaseHandler - { - public override void AbstractBaseMethod() - { - } - - public override int AbstractGenericBaseMethod1(int value) => 1; - - public override int AbstractGenericBaseMethod2(int value) => 1; - } - - public class TestHandler4 : GenericBaseHandler - { - } - - public class TestHandler5 : GenericBaseHandler2 - { - } - - public class TestHandler6 : GenericBaseHandler2 - { - } - - public class TestHandler7 - { - public class Nested : TrickyParamHandler.NestedGeneric - { - } - } - - public class ShadowTest : GenericAbstractBase - { - public override string AbstractFunctionInGeneric(string arg) => arg; - - public override string VirtualFunctionInGeneric(string arg) => arg; - - public string ShadowedFunctionInGeneric(string arg) => arg; - - public class Nested : ShadowTest - { - public new string ShadowedFunctionInGeneric(string arg) => arg; - } - } - - public class BaseHandler - { - public void BaseHandlerMethod() - { - } - - public void HiddenBaseMethod() - { - } - - public virtual void NonOverridenBaseMethod() - { - } - - public virtual void OverridenBaseMethod() - { - } - } - - public abstract class AbstractBaseHandler - { - public abstract void AbstractBaseMethod(); - } - - public abstract class AbstractGenericBaseHandler - { - public abstract void AbstractBaseMethod(); - - public abstract int AbstractGenericBaseMethod1(T value); - - public abstract T AbstractGenericBaseMethod2(int value); - } - - public class AbstractAspNetCoreFunction - { - } - - public class AbstractAspNetCoreFunction : AbstractAspNetCoreFunction - { - public virtual async Task FunctionHandlerAsync(TREQUEST request, ILambdaContext lambdaContext) - { - return await Task.FromResult(default(TRESPONSE)); - } - } - - public class FunctionImplementation : AbstractAspNetCoreFunction - { - } - - public class GenericBaseHandler - { - public void GenericBaseMethod1(T value) - { - } - - public T GenericBaseMethod2() => default; - - public T2 GenericBaseMethod3() => default; - } - - public abstract class GenericAbstractBase - { - public abstract T AbstractFunctionInGeneric(T arg); - - public virtual T VirtualFunctionInGeneric(T arg) => arg; - - public T ShadowedGenericFunction(T arg) => arg; - } - - public class GenericBaseHandler2 - { - public void GenericBaseMethod1(T1 value) - { - } - - public T1 GenericBaseMethod2() => default; - - public void GenericBaseMethod3(T2 value) - { - } - - public T2 GenericBaseMethod4() => default; - - public T2 GenericBaseMethod5(T1 value) => default; - - public void GenericBaseMethod6(T1 val1, T2 val2) - { - } - - public Task GenericBaseMethod7(Task value) => Task.FromResult(default); - } - - public class TrickyParamHandler - { - public int GenericArguments(Dictionary arg1) => 0; - - public int NestedGenericArguments(NestedGeneric arg1) => 0; - - public int RecursiveGenericArguments(Dictionary> arg1) => 0; - - public int DoublyNestedGenericArguments(NestedClass.InnerGeneric arg1) => 0; - - public int NestedRecursiveGenericArguments(NestedGeneric>> arg1) => 0; - - public int NestedClassArgument(NestedClass arg1) => 0; - - public int DoublyNestedClassArgument(NestedClass.Inner arg1) => 0; - - public int NestedStructArgument(NestedStruct arg1) => 0; - - public struct NestedStruct - { - } - - public class NestedClass - { - public class Inner - { - } - - public class InnerGeneric : Dictionary - { - } - } - - public class NestedGeneric : Dictionary - { - public Task>> Handler(Tuple> key) => default; - } - } - - public class TestMockSpan : MockSpan - { - } - - public class ILambdaContext - { - } - - public class DerivedImplementation : GenericBase - { - public class NestedDerived : GenericBase - { - } - } - - public class Function - { - public class NestedClass - { - public class InnerGeneric : Dictionary - { - } - } - - public class NestedGeneric : Dictionary - { - } - } - - public abstract class GenericBase - { - public GenericBase> ComplexNestedGeneric( - TRequest request, - Function.NestedClass.InnerGeneric>>> context) - { - return default; - } - - public Task NonGenericFunction(string arg1, ILambdaContext arg2) => Task.CompletedTask; - - public class NestedInSameType : Dictionary - { - } - - public class Nested - { - public class DeepNested : HashSet - { - } - } - } - - public class CustomInput - { - } -} diff --git a/tracer/test/Datadog.Trace.Tests/LambdaRequestBuilderTests.cs b/tracer/test/Datadog.Trace.Tests/LambdaRequestBuilderTests.cs index 66c8dd8c0aa1..64a4d5fd74f0 100644 --- a/tracer/test/Datadog.Trace.Tests/LambdaRequestBuilderTests.cs +++ b/tracer/test/Datadog.Trace.Tests/LambdaRequestBuilderTests.cs @@ -2,18 +2,13 @@ // Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. // This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. // - -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; - -using Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS; +#if NET6_0_OR_GREATER +using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda; using Datadog.Trace.TestHelpers; using FluentAssertions; -using Moq; using Xunit; +using LambdaCommon = Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda.LambdaCommon; namespace Datadog.Trace.Tests { @@ -75,3 +70,4 @@ public void TestGetEndInvocationRequestWithoutScope() } } } +#endif diff --git a/tracer/test/Datadog.Trace.Tests/ServerlessTests.cs b/tracer/test/Datadog.Trace.Tests/ServerlessTests.cs deleted file mode 100644 index e2e78ffdfb67..000000000000 --- a/tracer/test/Datadog.Trace.Tests/ServerlessTests.cs +++ /dev/null @@ -1,208 +0,0 @@ -// -// Unless explicitly stated otherwise all files in this repository are licensed under the Apache 2 License. -// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc. -// - -using System; -using System.Collections.Generic; -using System.IO; - -using Datadog.Trace.ClrProfiler.ServerlessInstrumentation; -using FluentAssertions; -using Xunit; - -namespace Datadog.Trace.Tests -{ - [Collection(nameof(EnvironmentVariablesTestCollection))] - public class ServerlessTests : IDisposable - { - private const string FunctionNameEnvVar = LambdaMetadata.FunctionNameEnvVar; - private const string HandlerEnvVar = LambdaMetadata.HandlerEnvVar; - private readonly Dictionary _originalEnvVars; - - public ServerlessTests() - { - _originalEnvVars = new() - { - { FunctionNameEnvVar, Environment.GetEnvironmentVariable(FunctionNameEnvVar) }, - { HandlerEnvVar, Environment.GetEnvironmentVariable(HandlerEnvVar) }, - }; - } - - public void Dispose() - { - foreach (var originalEnvVar in _originalEnvVars) - { - Environment.SetEnvironmentVariable(originalEnvVar.Key, originalEnvVar.Value); - } - } - - [Fact] - public void IsRunningInLambdaFalseNoFileAndNoEnvironmentVariable() - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, string.Empty); - string path = Directory.GetCurrentDirectory() + "/invalid"; - var res = LambdaMetadata.Create(path); - res.IsRunningInLambda.Should().BeFalse(); - } - - [Fact] - public void IsRunningInLambdaFalseNoFileAndEnvironmentVariable() - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, "my-test-function"); - string path = Directory.GetCurrentDirectory() + "/invalid"; - var res = LambdaMetadata.Create(path); - res.IsRunningInLambda.Should().BeFalse(); - } - - [Fact] - public void IsRunningInLambdaFalseFileAndNoEnvironmentVariable() - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, string.Empty); - string currentDirectory = Directory.GetCurrentDirectory(); - string existingFile = Directory.GetFiles(currentDirectory)[0]; - var res = LambdaMetadata.Create(existingFile); - res.IsRunningInLambda.Should().BeFalse(); - } - - [Fact] - public void IsRunningInLambdaTrue() - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, "my-test-function"); - string currentDirectory = Directory.GetCurrentDirectory(); - string existingFile = Directory.GetFiles(currentDirectory)[0]; - var res = LambdaMetadata.Create(existingFile); - res.IsRunningInLambda.Should().BeTrue(); - res.FunctionName.Should().Be("my-test-function"); - } - - [Theory] - [InlineData(null, null)] - [InlineData("", null)] - [InlineData("SomeValue", "SomeValue")] - public void Extracts_Handler(string handler, string expectedHandler) - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, "my-test-function"); - Environment.SetEnvironmentVariable(HandlerEnvVar, handler); - string currentDirectory = Directory.GetCurrentDirectory(); - string existingFile = Directory.GetFiles(currentDirectory)[0]; - - var res = LambdaMetadata.Create(existingFile); - - res.IsRunningInLambda.Should().BeTrue(); - res.FunctionName.Should().Be("my-test-function"); - res.HandlerName.Should().Be(expectedHandler); - } - - [Theory] - [InlineData(null, null)] - [InlineData("", null)] - [InlineData("SomeValue", "SomeValue")] - [InlineData("::Invalid::Name", null)] - [InlineData("AssemblyName::Some::Value", "AssemblyName")] - [InlineData("AssemblyNameNotValidButOk::", "AssemblyNameNotValidButOk")] - public void Extracts_ServiceFromHandler(string handler, string expectedService) - { - Environment.SetEnvironmentVariable(FunctionNameEnvVar, "my-test-function"); - Environment.SetEnvironmentVariable(HandlerEnvVar, handler); - string currentDirectory = Directory.GetCurrentDirectory(); - string existingFile = Directory.GetFiles(currentDirectory)[0]; - - var res = LambdaMetadata.Create(existingFile); - - res.IsRunningInLambda.Should().BeTrue(); - res.FunctionName.Should().Be("my-test-function"); - res.ServiceName.Should().Be(expectedService); - } - - [Fact] - public void GetSyncIntegrationTypeFromParamCountZero() - { - Serverless.GetSyncIntegrationTypeFromParamCount(0).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamSync"); - } - - [Fact] - public void GetSyncIntegrationTypeFromParamCountOne() - { - Serverless.GetSyncIntegrationTypeFromParamCount(1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaOneParamSync"); - } - - [Fact] - public void GetSyncIntegrationTypeFromParamCountTwo() - { - Serverless.GetSyncIntegrationTypeFromParamCount(2).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaTwoParamsSync"); - } - - [Fact] - public void GetSyncIntegrationTypeFromParamCountMoreThanExpected() - { - Assert.Throws(() => Serverless.GetSyncIntegrationTypeFromParamCount(3)); - } - - [Fact] - public void GetAsyncIntegrationTypeFromParamCountZero() - { - Serverless.GetAsyncIntegrationTypeFromParamCount(0).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamAsync"); - } - - [Fact] - public void GetAsyncIntegrationTypeFromParamCountOne() - { - Serverless.GetAsyncIntegrationTypeFromParamCount(1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaOneParamAsync"); - } - - [Fact] - public void GetAsyncIntegrationTypeFromParamCountTwo() - { - Serverless.GetAsyncIntegrationTypeFromParamCount(2).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaTwoParamsAsync"); - } - - [Fact] - public void GetAsyncIntegrationTypeFromParamCountMoreThanExpected() - { - Assert.Throws(() => Serverless.GetAsyncIntegrationTypeFromParamCount(3)); - } - - [Fact] - public void GetVoidIntegrationTypeFromParamCountZero() - { - Serverless.GetVoidIntegrationTypeFromParamCount(0).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamVoid"); - } - - [Fact] - public void GetVoidIntegrationTypeFromParamCountOne() - { - Serverless.GetVoidIntegrationTypeFromParamCount(1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaOneParamVoid"); - } - - [Fact] - public void GetVoidIntegrationTypeFromParamCountTwo() - { - Serverless.GetVoidIntegrationTypeFromParamCount(2).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaTwoParamsVoid"); - } - - [Fact] - public void GetVoidIntegrationTypeFromParamCountMoreThanExpected() - { - Assert.Throws(() => Serverless.GetAsyncIntegrationTypeFromParamCount(3)); - } - - [Fact] - public void GetIntegrationTypeSync() - { - Serverless.GetIntegrationType("System.String", 1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamSync"); - } - - [Fact] - public void GetIntegrationTypeAsync() - { - Serverless.GetIntegrationType("System.Threading.Tasks.Task", 1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamAsync"); - } - - [Fact] - public void GetIntegrationTypeVoid() - { - Serverless.GetIntegrationType("System.Void", 1).Should().Be("Datadog.Trace.ClrProfiler.ServerlessInstrumentation.AWS.LambdaNoParamVoid"); - } - } -} diff --git a/tracer/test/Datadog.Trace.Tests/Telemetry/config_prefix_block_list.json b/tracer/test/Datadog.Trace.Tests/Telemetry/config_prefix_block_list.json index 33b6fd8d2e04..d59630c457e3 100644 --- a/tracer/test/Datadog.Trace.Tests/Telemetry/config_prefix_block_list.json +++ b/tracer/test/Datadog.Trace.Tests/Telemetry/config_prefix_block_list.json @@ -70,6 +70,8 @@ "DD_Kafka_", "DD_TRACE_CosmosDb_", "DD_CosmosDb_", + "DD_TRACE_AwsLambda_", + "DD_AwsLambda_", "DD_TRACE_AwsSdk_", "DD_AwsSdk_", "DD_TRACE_AwsSqs_", diff --git a/tracer/test/test-applications/integrations/Samples.AWS.Lambda/Program.cs b/tracer/test/test-applications/integrations/Samples.AWS.Lambda/Program.cs index b03d458e11a3..6a901a5af2db 100644 --- a/tracer/test/test-applications/integrations/Samples.AWS.Lambda/Program.cs +++ b/tracer/test/test-applications/integrations/Samples.AWS.Lambda/Program.cs @@ -118,6 +118,10 @@ private static async Task Main(string[] args) Thread.Sleep(1000); await Post(Environment.GetEnvironmentVariable("AWS_LAMBDA_ENDPOINT_GENERICBASE_COMPLEX_NESTED")); + // Toplevel Statements + Thread.Sleep(1000); + await Post(Environment.GetEnvironmentVariable("AWS_LAMBDA_ENDPOINT_TOPLEVEL_STATEMENT")); + static async Task Post(string url) { HttpClient client = new HttpClient(); diff --git a/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Function.cs b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Function.cs new file mode 100644 index 000000000000..91c815c313a6 --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Function.cs @@ -0,0 +1,39 @@ +using System.Net; +using Amazon.Lambda.Core; +using Amazon.Lambda.RuntimeSupport; +using Amazon.Lambda.Serialization.SystemTextJson; +using Samples; + +void MakeRequest(string url) +{ + Console.WriteLine("Calling url " + url); + var request = WebRequest.Create(url); + request.Credentials = CredentialCache.DefaultCredentials; + var response = (HttpWebResponse)request.GetResponse(); + using (var dataStream = response.GetResponseStream()) + { + var reader = new StreamReader(dataStream); + reader.ReadToEnd(); + } + + response.Close(); +} + +// The function handler that will be called for each Lambda event +var handler = (string input, ILambdaContext context) => +{ + using var scope = SampleHelpers.CreateScope("manual.ToplevelStatements"); + var host = Environment.GetEnvironmentVariable("DUMMY_API_HOST")!; + var url = $"{host}/function/ToplevelStatements"; + + MakeRequest(url); + return new { statusCode = 200, body = "ok!" }; +}; + + +// Build the Lambda runtime client passing in the handler to call for each +// event and the JSON serializer to use for translating Lambda JSON documents +// to .NET types. +await LambdaBootstrapBuilder.Create(handler, new DefaultLambdaJsonSerializer()) + .Build() + .RunAsync(); diff --git a/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Properties/launchSettings.json b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Properties/launchSettings.json new file mode 100644 index 000000000000..48e3e8cc3175 --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Properties/launchSettings.json @@ -0,0 +1,21 @@ +{ + "profiles": { + "Samples.Amazon.Lambda.RuntimeSupport": { + "commandName": "Project", + "environmentVariables": { + "COR_ENABLE_PROFILING": "1", + "COR_PROFILER": "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}", + "COR_PROFILER_PATH": "$(SolutionDir)shared\\bin\\monitoring-home\\win-$(Platform)\\Datadog.Trace.ClrProfiler.Native.dll", + + "CORECLR_ENABLE_PROFILING": "1", + "CORECLR_PROFILER": "{846F5F1C-F9AE-4B07-969E-05C26BC060D8}", + "CORECLR_PROFILER_PATH": "$(SolutionDir)shared\\bin\\monitoring-home\\win-$(Platform)\\Datadog.Trace.ClrProfiler.Native.dll", + + "DD_DOTNET_TRACER_HOME": "$(SolutionDir)shared\\bin\\monitoring-home", + "DD_VERSION": "1.0.0" + }, + + "nativeDebugging": false + } + } +} \ No newline at end of file diff --git a/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Samples.Amazon.Lambda.RuntimeSupport.csproj b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Samples.Amazon.Lambda.RuntimeSupport.csproj new file mode 100644 index 000000000000..64d70a3fe38b --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/Samples.Amazon.Lambda.RuntimeSupport.csproj @@ -0,0 +1,25 @@ + + + Exe + net6.0;net7.0 + enable + true + Lambda + + true + + + 1.8.7 + All + + false + false + + + + + + + + + \ No newline at end of file diff --git a/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/serverless.lambda.dockerfile b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/serverless.lambda.dockerfile new file mode 100644 index 000000000000..5c5904251235 --- /dev/null +++ b/tracer/test/test-applications/integrations/Samples.Amazon.Lambda.RuntimeSupport/serverless.lambda.dockerfile @@ -0,0 +1,31 @@ +ARG lambdaBaseImage +FROM $lambdaBaseImage + +# Create log path +RUN mkdir -p /var/log/datadog/dotnet && \ + chmod a+rwx /var/log/datadog/dotnet + +# Add Tracer +COPY ./bin/artifacts/monitoring-home /opt/datadog + +ARG framework + +# Add Tests +COPY ./bin/Release/$framework/*.dll /var/task/ +COPY ./bin/Release/$framework/*.deps.json /var/task/ +COPY ./bin/Release/$framework/*.runtimeconfig.json /var/task/ + +ENV DD_LOG_LEVEL="DEBUG" +ENV DD_TRACE_ENABLED=true +ENV DD_DOTNET_TRACER_HOME="/opt/datadog" +# The serverless artifacts used in this test don't include the hard links at the root folder +# so link to the arch-specific version instead +ENV _DD_EXTENSION_PATH="/opt/datadog/linux-x64/Datadog.Trace.ClrProfiler.Native.so" + +ENV CORECLR_ENABLE_PROFILING=1 +ENV CORECLR_PROFILER="{846F5F1C-F9AE-4B07-969E-05C26BC060D8}" +ENV CORECLR_PROFILER_PATH="/opt/datadog/linux-x64/Datadog.Trace.ClrProfiler.Native.so" + +# See https://github.com/dotnet/runtime/issues/77973 +ENV DD_INTERNAL_WORKAROUND_77973_ENABLED=1 +ENV AWS_LAMBDA_FUNCTION_NAME="my-test-function" \ No newline at end of file