-
-
Notifications
You must be signed in to change notification settings - Fork 241
Support Dynamic Sampling #1953
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
Support Dynamic Sampling #1953
Changes from all commits
Commits
Show all changes
30 commits
Select commit
Hold shift + click to select a range
8db993e
Update existing text unrelated to dynamic sampling
mattjohnsonpint ab7ad3d
Add baggage header and DSC
mattjohnsonpint c42d148
Update tracing middleware for ASP.NET Core
mattjohnsonpint 532b720
Update tests
mattjohnsonpint 3a7595b
Update verify tests for Windows build
mattjohnsonpint 9ad0fe1
mark verify tests
mattjohnsonpint 8585888
Update CHANGELOG.md
mattjohnsonpint 5bd3504
Apply baggage headers
mattjohnsonpint 39fc013
Simplify baggage header
mattjohnsonpint 382da98
More baggage header tests
mattjohnsonpint 3b84f03
More baggage and DSC
mattjohnsonpint 7d2594d
Don't make DSC public
mattjohnsonpint fa363f8
Refactor
mattjohnsonpint 5c9300c
DSC tests
mattjohnsonpint 9b42274
Add ASP.NET support
mattjohnsonpint 0f457b2
Add baggage propagation test
mattjohnsonpint 2188438
DSC end-to-end test
mattjohnsonpint 09c86fb
Merge branch 'main' into dynamic-sampling
mattjohnsonpint abe26e5
Add some logging
mattjohnsonpint 34ddb3c
misc
mattjohnsonpint 34f997d
Get logger once in static initialization
mattjohnsonpint cec6271
Add extension method for getting options
mattjohnsonpint 60287d4
Add TracePropogationTargets
mattjohnsonpint 3a7e919
Update API verifications
mattjohnsonpint 9bf673b
Refactor and add tests
mattjohnsonpint 9940846
Add tests
mattjohnsonpint 77812f4
Add tests
mattjohnsonpint c7e92ad
Support setting option via json config file
mattjohnsonpint 3409cdf
Update API verifications
mattjohnsonpint 6474ccc
Update TracePropagationTargets implementation
mattjohnsonpint 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 hidden or 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 hidden or 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 hidden or 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 hidden or 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,150 @@ | ||
| using System; | ||
| using System.Collections.Generic; | ||
| using System.Linq; | ||
| using Sentry.Extensibility; | ||
| using Sentry.Internal.Extensions; | ||
|
|
||
| namespace Sentry | ||
| { | ||
| /// <summary> | ||
| /// Baggage Header for dynamic sampling. | ||
| /// </summary> | ||
| /// <seealso href="https://develop.sentry.dev/sdk/performance/dynamic-sampling-context"/> | ||
| /// <seealso href="https://www.w3.org/TR/baggage"/> | ||
| internal class BaggageHeader | ||
| { | ||
| internal const string HttpHeaderName = "baggage"; | ||
| internal const string SentryKeyPrefix = "sentry-"; | ||
|
|
||
| internal static IDiagnosticLogger? Logger { get; set; } = SentrySdk.CurrentOptions?.DiagnosticLogger; | ||
|
|
||
| // https://www.w3.org/TR/baggage/#baggage-string | ||
| // "Uniqueness of keys between multiple list-members in a baggage-string is not guaranteed." | ||
| // "The order of duplicate entries SHOULD be preserved when mutating the list." | ||
|
|
||
| public IReadOnlyList<KeyValuePair<string, string>> Members { get; } | ||
|
|
||
| private BaggageHeader(IEnumerable<KeyValuePair<string, string>> members) => | ||
| Members = members.ToList(); | ||
|
|
||
| // We can safely return a dictionary of Sentry members, as we are in control over the keys added. | ||
| // Just to be safe though, we'll group by key and only take the first of each one. | ||
| public IReadOnlyDictionary<string, string> GetSentryMembers() => | ||
|
mattjohnsonpint marked this conversation as resolved.
|
||
| Members | ||
| .Where(kvp => kvp.Key.StartsWith(SentryKeyPrefix)) | ||
| .GroupBy(kvp => kvp.Key, kvp => kvp.Value) | ||
| .ToDictionary( | ||
| #if NETCOREAPP || NETSTANDARD2_1 | ||
| g => g.Key[SentryKeyPrefix.Length..], | ||
| #else | ||
| g => g.Key.Substring(SentryKeyPrefix.Length), | ||
| #endif | ||
| g => g.First()); | ||
|
|
||
| /// <summary> | ||
| /// Creates the baggage header string based on the members of this instance. | ||
| /// </summary> | ||
| /// <returns>The baggage header string.</returns> | ||
| public override string ToString() | ||
|
mattjohnsonpint marked this conversation as resolved.
|
||
| { | ||
| // The keys do not require special encoding. The values are percent-encoded. | ||
| // The results should not be sorted, as the baggage spec says original ordering should be preserved. | ||
| var members = Members.Select(x => $"{x.Key}={Uri.EscapeDataString(x.Value)}"); | ||
|
|
||
| // Whitespace after delimiter is optional by the spec, but typical by convention. | ||
| return string.Join(", ", members); | ||
| } | ||
|
|
||
| /// <summary> | ||
| /// Parses a baggage header string. | ||
| /// </summary> | ||
| /// <param name="baggage">The string to parse.</param> | ||
| /// <param name="onlySentry"> | ||
| /// When <c>false</c>, the resulting object includes all list members present in the baggage header string. | ||
| /// When <c>true</c>, the resulting object includes only members prefixed with <c>"sentry-"</c>. | ||
| /// </param> | ||
| /// <returns> | ||
| /// An object representing the members baggage header, or <c>null</c> if there are no members parsed. | ||
| /// </returns> | ||
| public static BaggageHeader? TryParse(string baggage, bool onlySentry = false) | ||
| { | ||
| // Example from W3C baggage spec: | ||
| // "key1=value1;property1;property2, key2 = value2, key3=value3; propertyKey=propertyValue" | ||
|
|
||
| var items = baggage.Split(',', StringSplitOptions.RemoveEmptyEntries); | ||
| var members = new List<KeyValuePair<string, string>>(items.Length); | ||
|
|
||
| foreach (var item in items) | ||
| { | ||
| // Per baggage spec, the value may contain = characters, so limit the split to 2 parts. | ||
| var parts = item.Split('=', 2); | ||
| if (parts.Length != 2) | ||
| { | ||
| Logger?.LogWarning( | ||
| "The baggage header has an item without a '=' separator, and it will be discarded. " + | ||
| "The item is: \"{0}\"", item); | ||
| continue; | ||
| } | ||
|
|
||
| var key = parts[0].Trim(); | ||
| if (key.Length == 0) | ||
| { | ||
| Logger?.LogWarning( | ||
| "The baggage header has an item with an empty key, and it will be discarded. " + | ||
| "The item is: \"{0}\"", item); | ||
| continue; | ||
| } | ||
|
|
||
| var value = parts[1].Trim(); | ||
| if (value.Length == 0) | ||
| { | ||
| Logger?.LogWarning( | ||
| "The baggage header has an item with an empty value, and it will be discarded. " + | ||
| "The item is: \"{0}\"", item); | ||
| continue; | ||
| } | ||
|
|
||
| if (!onlySentry || key.StartsWith(SentryKeyPrefix)) | ||
| { | ||
| // Values are percent-encoded. Decode them before storing. | ||
| members.Add(key, Uri.UnescapeDataString(value)); | ||
| } | ||
| } | ||
|
|
||
| return members.Count == 0 ? null : new BaggageHeader(members); | ||
| } | ||
|
|
||
| public static BaggageHeader Create( | ||
| IEnumerable<KeyValuePair<string, string>> items, | ||
| bool useSentryPrefix = false) | ||
| { | ||
| var members = items.Where(member => IsValidKey(member.Key)); | ||
|
|
||
| if (useSentryPrefix) | ||
| { | ||
| members = members.Select(kvp => new KeyValuePair<string, string>(SentryKeyPrefix + kvp.Key, kvp.Value)); | ||
| } | ||
|
|
||
| return new BaggageHeader(members); | ||
| } | ||
|
|
||
| public static BaggageHeader Merge(IEnumerable<BaggageHeader> baggageHeaders) => | ||
| new(baggageHeaders.SelectMany(x => x.Members)); | ||
|
|
||
| private static bool IsValidKey(string key) | ||
| { | ||
| if (key.Length == 0) | ||
| { | ||
| return false; | ||
| } | ||
|
|
||
| // The rules are the same as for HTTP headers. | ||
| // TODO: Is this public somewhere in .NET we can just call? | ||
|
mattjohnsonpint marked this conversation as resolved.
|
||
| // https://www.w3.org/TR/baggage/#key | ||
| // https://www.rfc-editor.org/rfc/rfc7230#section-3.2.6 | ||
| // https://source.dot.net/#System.Net.Http/System/Net/Http/HttpRuleParser.cs,21 | ||
| const string delimiters = @"""(),/:;<=>?@[\]{}"; | ||
| return key.All(c => c >= 33 && c != 127 && !delimiters.Contains(c)); | ||
| } | ||
| } | ||
| } | ||
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.
Uh oh!
There was an error while loading. Please reload this page.