-
Notifications
You must be signed in to change notification settings - Fork 145
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
[tracer] add support for match sampling rules by resource and tags #5013
Merged
Merged
Changes from all commits
Commits
Show all changes
27 commits
Select commit
Hold shift + click to select a range
29b78d0
convert glob to regex if needed
lucaspimentel dc059c3
add new json properties
lucaspimentel 34c45a7
add unit tests
lucaspimentel 49929e3
match by resource name
lucaspimentel 20fdf85
fix compiler errors in unit tests
lucaspimentel 6b747d0
deserialize tag regexes
lucaspimentel e1c1989
fix compiler errors in unit tests
lucaspimentel dc2509b
refactor things and support matching new fields in SpanSamplingRule
lucaspimentel 44fbaa3
rewrite without the null coalescing
lucaspimentel 0e03620
implement matching on tags
lucaspimentel 167df72
refactor MatchTags()
lucaspimentel 692eae1
refactor common code into SamplingRuleHelper
lucaspimentel 6dbd80b
fix compiler errors in unit tests
lucaspimentel 3303557
inline variable into condition
lucaspimentel b9336ac
fix tests
lucaspimentel c8a8c74
use Dictionary for tag patterns
lucaspimentel 4ba7cda
add tests for matching on tags
lucaspimentel d43c031
build tag regex list in RegexBuilder.Build()
lucaspimentel 2200314
TEMP
lucaspimentel c21454d
move more common sampling code into SamplingRuleHelper
lucaspimentel 4f4cd6b
fix unit tests by setting the span's resource name
lucaspimentel 971e800
if a tag regex is null (not specified), it always matches
lucaspimentel b36675b
annotate nullability
lucaspimentel 1128802
more refactoring
lucaspimentel 1108504
reformat test
lucaspimentel c5653da
add tags to test spans
lucaspimentel 52aa432
fix test that matches rules by tags
lucaspimentel File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
131 changes: 131 additions & 0 deletions
131
tracer/src/Datadog.Trace/Sampling/SamplingRuleHelper.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
// <copyright file="SamplingRuleHelper.cs" company="Datadog"> | ||
// 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. | ||
// </copyright> | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Globalization; | ||
using System.Runtime.CompilerServices; | ||
using Datadog.Trace.Logging; | ||
|
||
#if NETCOREAPP3_1_OR_GREATER | ||
using Datadog.Trace.Vendors.IndieSystem.Text.RegularExpressions; | ||
#else | ||
using System.Text.RegularExpressions; | ||
#endif | ||
|
||
namespace Datadog.Trace.Sampling; | ||
|
||
#nullable enable | ||
|
||
internal static class SamplingRuleHelper | ||
{ | ||
private static readonly IDatadogLogger Log = DatadogLogging.GetLoggerFor(typeof(SamplingRuleHelper)); | ||
|
||
public static bool IsMatch( | ||
Span span, | ||
Regex? serviceNameRegex, | ||
Regex? operationNameRegex, | ||
Regex? resourceNameRegex, | ||
List<KeyValuePair<string, Regex?>>? tagRegexes, | ||
out bool timedOut) | ||
{ | ||
timedOut = false; | ||
|
||
if (span == null!) | ||
{ | ||
return false; | ||
} | ||
|
||
try | ||
{ | ||
// if a regex is null (not specified), it always matches. | ||
// stop as soon as we find a non-match. | ||
return IsMatch(serviceNameRegex, span.ServiceName) && | ||
IsMatch(operationNameRegex, span.OperationName) && | ||
IsMatch(resourceNameRegex, span.ResourceName) && | ||
MatchSpanByTags(span, tagRegexes); | ||
} | ||
catch (RegexMatchTimeoutException e) | ||
{ | ||
// flag rule so we don't try to use one of its regexes again | ||
timedOut = true; | ||
|
||
Log.Error( | ||
e, | ||
"""Regex timed out when trying to match value "{Input}" against pattern "{Pattern}".""", | ||
e.Input, | ||
e.Pattern); | ||
|
||
return false; | ||
} | ||
} | ||
|
||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
private static bool IsMatch(Regex? regex, string? input) | ||
{ | ||
if (regex is null) | ||
{ | ||
// if a regex is null (not specified), it always matches. | ||
return true; | ||
} | ||
|
||
if (input is null) | ||
{ | ||
return false; | ||
} | ||
|
||
return regex.Match(input).Success; | ||
} | ||
|
||
private static bool MatchSpanByTags(Span span, List<KeyValuePair<string, Regex?>>? tagRegexes) | ||
{ | ||
if (tagRegexes is null || tagRegexes.Count == 0) | ||
{ | ||
// if a regex is null (not specified), it always matches. | ||
return true; | ||
} | ||
|
||
foreach (var pair in tagRegexes) | ||
{ | ||
var tagName = pair.Key; | ||
var tagRegex = pair.Value; | ||
|
||
if (tagRegex is null) | ||
{ | ||
// if a regex is null (not specified), it always matches. | ||
continue; | ||
} | ||
|
||
var tagValue = GetSpanTag(span, tagName); | ||
|
||
if (tagValue is null || !tagRegex.Match(tagValue).Success) | ||
{ | ||
// stop as soon as we find a tag that isn't set or doesn't match | ||
return false; | ||
} | ||
} | ||
|
||
// all specified tags exist and matched | ||
return true; | ||
} | ||
|
||
private static string? GetSpanTag(Span span, string tagName) | ||
{ | ||
if (span.GetTag(tagName) is { } tagValue) | ||
{ | ||
return tagValue; | ||
} | ||
|
||
// if the string tag doesn't exist, try to get it as a numeric tag... | ||
if (span.GetMetric(tagName) is not { } numericTagValue) | ||
{ | ||
return null; | ||
} | ||
|
||
// ...but only if it is an integer | ||
var intValue = (int)numericTagValue; | ||
return Math.Abs(intValue - numericTagValue) < 0.0001 ? intValue.ToString(CultureInfo.InvariantCulture) : null; | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
How come we have to test the absolute value? Is a simple int conversion insufficient?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I want to determine if the tag value is an integer, but it is stored as a
double
. If you convert it toint
and try to compare them withintValue == doubleValue
, Rider recommends usingMath.Abs(value1 - value2) < tolerance)
instead.https://www.jetbrains.com/help/rider/CompareOfFloatsByEqualityOperator.html