Skip to content

Commit 43053b4

Browse files
shreyamalpanichojomok
authored andcommitted
[serverless] encode lambda error.msg and error.type (#6438)
## Summary of changes Encodes `error.msg` and `error.type` like the previously encoded `error.stack`. ![image](https://github.com/user-attachments/assets/9bf0becf-7960-4106-9b74-132e99f83755) Related extension changes: DataDog/datadog-agent#32231 DataDog/datadog-lambda-extension#500 ## Reason for change Prevents the tracer from throwing an exception due to non-ASCII characters in these header values. [[SLES-2001] .NET Datadog Tracer throws exception from AWS Lambda Function](https://datadoghq.atlassian.net/browse/SLES-2001) [[SVLS-6041] Having non-ascii characters in a stack trace causes an exception within the tracer.](https://datadoghq.atlassian.net/browse/SVLS-6041) ## Implementation details Encodes the string values to UTF-8 bytes and then to a Base64 string. ## Test coverage Updated tests to check for encoded values. ## Other details <!-- Fixes #{issue} --> <!-- ⚠️ Note: where possible, please obtain 2 approvals prior to merging. Unless CODEOWNERS specifies otherwise, for external teams it is typically best to have one review from a team member, and one review from apm-dotnet. Trivial changes do not require 2 reviews. --> [SLES-2001]: https://datadoghq.atlassian.net/browse/SLES-2001?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ [SVLS-6041]: https://datadoghq.atlassian.net/browse/SVLS-6041?atlOrigin=eyJpIjoiNWRkNTljNzYxNjVmNDY3MDlhMDU5Y2ZhYzA5YTRkZjUiLCJwIjoiZ2l0aHViLWNvbS1KU1cifQ
1 parent 1b9d131 commit 43053b4

File tree

3 files changed

+44
-8
lines changed

3 files changed

+44
-8
lines changed

tracer/src/Datadog.Trace/ClrProfiler/AutoInstrumentation/AWS/Lambda/LambdaRequestBuilder.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ WebRequest ILambdaExtensionRequest.GetEndInvocationRequest(Scope scope, bool isE
5353
var errorMessage = span.GetTag("error.msg");
5454
if (errorMessage != null)
5555
{
56-
request.Headers.Set(HttpHeaderNames.InvocationErrorMsg, errorMessage);
56+
var encodedErrMessage = System.Text.Encoding.UTF8.GetBytes(errorMessage);
57+
request.Headers.Set(HttpHeaderNames.InvocationErrorMsg, Convert.ToBase64String(encodedErrMessage));
5758
}
5859

5960
var errorType = span.GetTag("error.type");
6061
if (errorType != null)
6162
{
62-
request.Headers.Set(HttpHeaderNames.InvocationErrorType, errorType);
63+
var encodedErrType = System.Text.Encoding.UTF8.GetBytes(errorType);
64+
request.Headers.Set(HttpHeaderNames.InvocationErrorType, Convert.ToBase64String(encodedErrType));
6365
}
6466

6567
var errorStack = span.GetTag("error.stack");

tracer/test/Datadog.Trace.TestHelpers/MockLambdaExtension.cs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,11 @@ protected virtual void HandleHttpRequest(HttpListenerContext ctx)
133133
string? errorMsg = headers.Get("x-datadog-invocation-error-msg") ?? null;
134134
string? errorType = headers.Get("x-datadog-invocation-error-type") ?? null;
135135
string? errorStack = headers.Get("x-datadog-invocation-error-stack") ?? null;
136+
137+
errorMsg = DecodeBase64(errorMsg);
138+
errorType = DecodeBase64(errorType);
139+
errorStack = DecodeBase64(errorStack);
140+
136141
var invocation = new EndExtensionRequest(headers, body, traceId, spanId, samplingPriority, isError, errorMsg, errorType, errorStack);
137142

138143
EndInvocations.Push(invocation);
@@ -147,6 +152,26 @@ protected virtual void HandleHttpRequest(HttpListenerContext ctx)
147152
ctx.Response.Close();
148153
}
149154

155+
private static string? DecodeBase64(string? input)
156+
{
157+
if (input == null)
158+
{
159+
return input;
160+
}
161+
162+
try
163+
{
164+
// Try to decode the string as base64
165+
byte[] decodedBytes = Convert.FromBase64String(input);
166+
return System.Text.Encoding.UTF8.GetString(decodedBytes);
167+
}
168+
catch (FormatException)
169+
{
170+
// If it is not a valid base64 string, return original input
171+
return input;
172+
}
173+
}
174+
150175
private void HandleHttpRequests()
151176
{
152177
while (_listener.IsListening)

tracer/test/Datadog.Trace.Tests/LambdaRequestBuilderTests.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// This product includes software developed at Datadog (https://www.datadoghq.com/). Copyright 2017 Datadog, Inc.
44
// </copyright>
55
#if NET6_0_OR_GREATER
6+
using System;
67
using System.Net;
78
using System.Threading.Tasks;
89
using Datadog.Trace.ClrProfiler.AutoInstrumentation.AWS.Lambda;
@@ -84,16 +85,24 @@ public async Task TestGetEndInvocationRequestWithErrorTags()
8485
await using var tracer = TracerHelper.CreateWithFakeAgent();
8586
var headers = new WebHeaderCollection().Wrap();
8687
var scope = LambdaCommon.CreatePlaceholderScope(tracer, headers);
87-
scope.Span.SetTag("error.msg", "Exception");
88-
scope.Span.SetTag("error.type", "Exception");
89-
scope.Span.SetTag("error.stack", "everything is " + System.Environment.NewLine + "fine");
88+
89+
var errorMsg = "Exception";
90+
var errorType = "Exception";
91+
var errorStack = "everything is " + System.Environment.NewLine + "fine";
92+
scope.Span.SetTag("error.msg", errorMsg);
93+
scope.Span.SetTag("error.type", errorType);
94+
scope.Span.SetTag("error.stack", errorStack);
95+
96+
var expectedErrorMsg = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(errorMsg));
97+
var expectedErrorType = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(errorType));
98+
var expectedErrorStack = Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(errorStack));
9099

91100
ILambdaExtensionRequest requestBuilder = new LambdaRequestBuilder();
92101
var request = requestBuilder.GetEndInvocationRequest(scope, true);
93102
request.Headers.Get("x-datadog-invocation-error").Should().NotBeNull();
94-
request.Headers.Get("x-datadog-invocation-error-msg").Should().Be("Exception");
95-
request.Headers.Get("x-datadog-invocation-error-type").Should().Be("Exception");
96-
request.Headers.Get("x-datadog-invocation-error-stack").Should().NotBeNull();
103+
request.Headers.Get("x-datadog-invocation-error-msg").Should().Be(expectedErrorMsg);
104+
request.Headers.Get("x-datadog-invocation-error-type").Should().Be(expectedErrorType);
105+
request.Headers.Get("x-datadog-invocation-error-stack").Should().Be(expectedErrorStack);
97106
request.Headers.Get("x-datadog-tracing-enabled").Should().Be("false");
98107
request.Headers.Get("x-datadog-sampling-priority").Should().Be("1");
99108
request.Headers.Get("x-datadog-trace-id").Should().NotBeNull();

0 commit comments

Comments
 (0)