Skip to content

chore: Tracing Sanitize SegmentName to avoid unsupported characters #741

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
24 changes: 24 additions & 0 deletions libraries/src/AWS.Lambda.Powertools.Tracing/Internal/Helpers.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
using System;
using System.Text.RegularExpressions;

namespace AWS.Lambda.Powertools.Tracing.Internal;

/// <summary>
/// Helper class
/// </summary>
public static class Helpers
{
/// <summary>
/// Sanitize a string by removing any characters that are not alphanumeric, whitespace, or one of the following: _ . : / % & # = + - @

Check warning on line 12 in libraries/src/AWS.Lambda.Powertools.Tracing/Internal/Helpers.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'

Check warning on line 12 in libraries/src/AWS.Lambda.Powertools.Tracing/Internal/Helpers.cs

View workflow job for this annotation

GitHub Actions / build

XML comment has badly formed XML -- 'Whitespace is not allowed at this location.'
/// </summary>
/// <param name="input"></param>
/// <returns></returns>
public static string SanitizeString(string input)
{
// Define a regular expression pattern to match allowed characters
var pattern = @"[^a-zA-Z0-9\s_\.\:/%&#=+\-@]";

// Replace any character that does not match the pattern with an empty string, with a timeout
return Regex.Replace(input, pattern, string.Empty, RegexOptions.None, TimeSpan.FromMilliseconds(100));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,9 @@ public XRayRecorder(IAWSXRayRecorder awsxRayRecorder, IPowertoolsConfigurations
public void BeginSubsegment(string name)
{
if (_isLambda)
_awsxRayRecorder.BeginSubsegment(name);
{
_awsxRayRecorder.BeginSubsegment(Helpers.SanitizeString(name));
}
}

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@

using System;
using AspectInjector.Broker;
using AWS.Lambda.Powertools.Common;
using AWS.Lambda.Powertools.Tracing.Internal;

namespace AWS.Lambda.Powertools.Tracing;
Expand Down Expand Up @@ -114,8 +113,10 @@ public class TracingAttribute : Attribute
/// <summary>
/// Set custom segment name for the operation.
/// The default is '## {MethodName}'.
///
/// The logical name of the service that handled the request, up to 200 characters.
/// Names can contain Unicode letters, numbers, and whitespace, and the following symbols: \_, ., :, /, %, &amp;, #, =, +, \\, -, @
/// </summary>
/// <value>The name of the segment.</value>
public string SegmentName { get; set; } = "";

/// <summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,18 @@ public void HandleWithSegmentName()

}

[Tracing(SegmentName = "## <<Main>$>g__Handler|0_0")]
public void HandleWithInvalidSegmentName()
{
MethodWithInvalidSegmentName();
}

[Tracing(SegmentName = "Inval$#id | <Segment>")]
private void MethodWithInvalidSegmentName()
{

}

[Tracing(Namespace = "Namespace Defined")]
public void HandleWithNamespace()
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -256,6 +256,28 @@ public void OnEntry_WhenSegmentNameHasValue_BeginSubsegmentWithValue()
Assert.Single(segment.Subsegments);
Assert.Equal("SegmentName", subSegment.Name);
}

[Fact]
public void OnEntry_WhenSegmentName_Is_Unsupported()
{
// Arrange
Environment.SetEnvironmentVariable("LAMBDA_TASK_ROOT", "AWS");
Environment.SetEnvironmentVariable("POWERTOOLS_SERVICE_NAME", "POWERTOOLS");

// Act
var segment = AWSXRayRecorder.Instance.TraceContext.GetEntity();
_handler.HandleWithInvalidSegmentName();
var subSegment = segment.Subsegments[0];
var childSegment = subSegment.Subsegments[0];

// Assert
Assert.True(segment.IsSubsegmentsAdded);
Assert.True(subSegment.IsSubsegmentsAdded);
Assert.Single(segment.Subsegments);
Assert.Single(subSegment.Subsegments);
Assert.Equal("## Maing__Handler0_0", subSegment.Name);
Assert.Equal("Inval#id Segment", childSegment.Name);
}

[Fact]
public void OnEntry_WhenNamespaceIsNull_SetNamespaceWithService()
Expand Down
Loading