From 4292c462219e8c19bd17dba9695db444f4b57e9f Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 14:49:25 -0500 Subject: [PATCH 01/16] Push SentryTransaction extras into the Contexts.Trace.Data element --- src/Sentry/Protocol/Trace.cs | 18 ++++++++++++++++-- src/Sentry/SentryTransaction.cs | 11 ++--------- 2 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/Sentry/Protocol/Trace.cs b/src/Sentry/Protocol/Trace.cs index 289b2a4b08..e96d647094 100644 --- a/src/Sentry/Protocol/Trace.cs +++ b/src/Sentry/Protocol/Trace.cs @@ -7,7 +7,7 @@ namespace Sentry.Protocol; /// /// Trace context data. /// -public class Trace : ITraceContext, ISentryJsonSerializable, ICloneable, IUpdatable +public class Trace : ITraceContext, IHasExtra, ISentryJsonSerializable, ICloneable, IUpdatable { /// /// Tells Sentry which type of context this is. @@ -103,6 +103,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteString("origin", Origin ?? Internal.OriginHelper.Manual); writer.WriteStringIfNotWhiteSpace("description", Description); writer.WriteStringIfNotWhiteSpace("status", Status?.ToString().ToSnakeCase()); + writer.WriteDictionaryIfNotEmpty("data", _extra, logger); writer.WriteEndObject(); } @@ -120,6 +121,7 @@ public static Trace FromJson(JsonElement json) var description = json.GetPropertyOrNull("description")?.GetString(); var status = json.GetPropertyOrNull("status")?.GetString()?.Replace("_", "").ParseEnum(); var isSampled = json.GetPropertyOrNull("sampled")?.GetBoolean(); + var extra = json.GetPropertyOrNull("data")?.GetDictionaryOrNull() ?? new(); return new Trace { @@ -130,7 +132,19 @@ public static Trace FromJson(JsonElement json) Origin = origin, Description = description, Status = status, - IsSampled = isSampled + IsSampled = isSampled, + _extra = extra }; } + + + // not readonly for serialization + private Dictionary _extra = new(); + + /// + public IReadOnlyDictionary Extra => _extra; + + /// + public void SetExtra(string key, object? value) + => _extra[key] = value; } diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index b69acd3f52..1f067003b6 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -179,11 +179,9 @@ public IReadOnlyList Fingerprint /// public IReadOnlyCollection Breadcrumbs => _breadcrumbs; - // Not readonly because of deserialization - private Dictionary _extra = new(); /// - public IReadOnlyDictionary Extra => _extra; + public IReadOnlyDictionary Extra => Contexts.Trace.Extra; // Not readonly because of deserialization private Dictionary _tags = new(); @@ -270,7 +268,6 @@ public SentryTransaction(ITransactionTracer tracer) Sdk = tracer.Sdk; Fingerprint = tracer.Fingerprint; _breadcrumbs = tracer.Breadcrumbs.ToList(); - _extra = tracer.Extra.ToDict(); _tags = tracer.Tags.ToDict(); _spans = FromTracerSpans(tracer); @@ -340,7 +337,7 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) => /// public void SetExtra(string key, object? value) => - _extra[key] = value; + Contexts.Trace.SetExtra(key, value); /// public void SetTag(string key, string value) => @@ -401,7 +398,6 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteSerializable("sdk", Sdk, logger); writer.WriteStringArrayIfNotEmpty("fingerprint", _fingerprint); writer.WriteArrayIfNotEmpty("breadcrumbs", _breadcrumbs, logger); - writer.WriteDictionaryIfNotEmpty("extra", _extra, logger); writer.WriteStringDictionaryIfNotEmpty("tags", _tags!); writer.WriteArrayIfNotEmpty("spans", _spans, logger); writer.WriteDictionaryIfNotEmpty("measurements", _measurements, logger); @@ -434,8 +430,6 @@ public static SentryTransaction FromJson(JsonElement json) .EnumerateArray().Select(j => j.GetString()!).ToArray(); var breadcrumbs = json.GetPropertyOrNull("breadcrumbs")? .EnumerateArray().Select(Breadcrumb.FromJson).ToList() ?? new(); - var extra = json.GetPropertyOrNull("extra")? - .GetDictionaryOrNull() ?? new(); var tags = json.GetPropertyOrNull("tags")? .GetStringDictionaryOrNull()?.WhereNotNullValue().ToDict() ?? new(); var measurements = json.GetPropertyOrNull("measurements")? @@ -459,7 +453,6 @@ public static SentryTransaction FromJson(JsonElement json) Sdk = sdk, _fingerprint = fingerprint, _breadcrumbs = breadcrumbs, - _extra = extra, _tags = tags, _measurements = measurements, _spans = spans From 253239fce5ef401f9589318548ac455ac4279082 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 15:09:29 -0500 Subject: [PATCH 02/16] Update SerializationTests.verify.cs --- .../Sentry.Tests/SerializationTests.verify.cs | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/test/Sentry.Tests/SerializationTests.verify.cs b/test/Sentry.Tests/SerializationTests.verify.cs index 86a671cb3c..d67e1f7d4d 100644 --- a/test/Sentry.Tests/SerializationTests.verify.cs +++ b/test/Sentry.Tests/SerializationTests.verify.cs @@ -13,6 +13,27 @@ public SerializationTests(ITestOutputHelper output) _testOutputLogger = new TestOutputDiagnosticLogger(output); } + [Fact] + public void Test() + { + // TODO: verify assert this once I've got span extra/data + var hub = Substitute.For(); + var context = new TransactionContext("name", "operation", new SentryTraceHeader(SentryId.Empty, SpanId.Empty, false)); + var transactionTracer = new TransactionTracer(hub, context); + var span = transactionTracer.StartChild("childop"); + span.SetExtra("span1", "value1"); + + + var transaction = new SentryTransaction("name", "operation") + { + IsSampled = false + }; + transaction.SetExtra("transaction1", "transaction_value"); + + var json = transaction.ToJsonString(); + _testOutputLogger.LogDebug(json); + } + [Theory] [MemberData(nameof(GetData))] public async Task Serialization(string name, object target) From 9d517872a63c6c58881b51263ff43acfc9899f76 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 15:44:29 -0500 Subject: [PATCH 03/16] Update serialization tests --- ...tionTests.verify.cs => SerializationTests.cs} | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) rename test/Sentry.Tests/{SerializationTests.verify.cs => SerializationTests.cs} (90%) diff --git a/test/Sentry.Tests/SerializationTests.verify.cs b/test/Sentry.Tests/SerializationTests.cs similarity index 90% rename from test/Sentry.Tests/SerializationTests.verify.cs rename to test/Sentry.Tests/SerializationTests.cs index d67e1f7d4d..1e6cbcee13 100644 --- a/test/Sentry.Tests/SerializationTests.verify.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -14,24 +14,28 @@ public SerializationTests(ITestOutputHelper output) } [Fact] - public void Test() + public void Serialization_TransactionAndSpanData() { - // TODO: verify assert this once I've got span extra/data var hub = Substitute.For(); var context = new TransactionContext("name", "operation", new SentryTraceHeader(SentryId.Empty, SpanId.Empty, false)); var transactionTracer = new TransactionTracer(hub, context); var span = transactionTracer.StartChild("childop"); span.SetExtra("span1", "value1"); - - var transaction = new SentryTransaction("name", "operation") + var transaction = new SentryTransaction(transactionTracer) { IsSampled = false }; transaction.SetExtra("transaction1", "transaction_value"); - var json = transaction.ToJsonString(); - _testOutputLogger.LogDebug(json); + var json = transaction.ToJsonString(_testOutputLogger); + + var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); + var el = JsonElement.ParseValue(ref reader); + var backTransaction = SentryTransaction.FromJson(el); + + backTransaction.Spans.First().Extra["span1"].Should().Be("value1", "Span value missing"); + backTransaction.Contexts.Trace.Extra["transaction1"].Should().Be("transaction_value", "Transaction value missing"); } [Theory] From 58e4a1e170c4e19521051e5c527c1273bb87542b Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 15:54:54 -0500 Subject: [PATCH 04/16] Update tests --- ...zation_TransactionAndSpanData.verified.txt | 44 +++++++++++++++++++ test/Sentry.Tests/SerializationTests.cs | 5 ++- 2 files changed, 47 insertions(+), 2 deletions(-) create mode 100644 test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt diff --git a/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt b/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt new file mode 100644 index 0000000000..8678e11e63 --- /dev/null +++ b/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt @@ -0,0 +1,44 @@ +{ + EventId: {}, + SpanId: {}, + ParentSpanId: {}, + Name: name, + Platform: csharp, + StartTimestamp: DateTimeOffset_1, + Operation: operation, + Description: , + IsSampled: false, + SampleRate: 0.0, + Request: {}, + Contexts: { + trace: { + SpanId: {}, + ParentSpanId: {}, + Operation: operation, + Description: , + IsSampled: false, + Extra: { + transaction1: transaction_value + } + } + }, + User: {}, + Sdk: {}, + Extra: { + transaction1: transaction_value + }, + Spans: [ + { + SpanId: {}, + ParentSpanId: {}, + StartTimestamp: DateTimeOffset_2, + IsFinished: false, + Operation: childop, + IsSampled: false, + Extra: { + span1: value1 + } + } + ], + IsFinished: false +} \ No newline at end of file diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index 1e6cbcee13..04996b5e3a 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -14,7 +14,7 @@ public SerializationTests(ITestOutputHelper output) } [Fact] - public void Serialization_TransactionAndSpanData() + public async Task Serialization_TransactionAndSpanData() { var hub = Substitute.For(); var context = new TransactionContext("name", "operation", new SentryTraceHeader(SentryId.Empty, SpanId.Empty, false)); @@ -27,9 +27,10 @@ public void Serialization_TransactionAndSpanData() IsSampled = false }; transaction.SetExtra("transaction1", "transaction_value"); + await Verify(transaction); + // verify deserialization var json = transaction.ToJsonString(_testOutputLogger); - var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); var el = JsonElement.ParseValue(ref reader); var backTransaction = SentryTransaction.FromJson(el); From 590a182a380269e1ffcac19a2e1319fec0f7587c Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 18:01:56 -0500 Subject: [PATCH 05/16] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 4fec059921..c4332c287a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,7 @@ ### Fixes +- Emit transaction.data inside contexts.trace.data ([#3936](https://github.com/getsentry/sentry-dotnet/pull/3936)) - Prevent Native EXC_BAD_ACCESS signal errors from being captured when managed NullRefrenceExceptions occur ([#3909](https://github.com/getsentry/sentry-dotnet/pull/3909)) - Fixed duplicate SentryMauiEventProcessors ([#3905](https://github.com/getsentry/sentry-dotnet/pull/3905)) - Fixed invalid string.Format index in Debug logs for the DiagnosticSource integration ([#3923](https://github.com/getsentry/sentry-dotnet/pull/3923)) From d50a2dd31767d6b1ff99812f38b8a914eab40d1d Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 3 Feb 2025 18:06:45 -0500 Subject: [PATCH 06/16] Update CHANGELOG.md --- CHANGELOG.md | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c4332c287a..4378c5a4d5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,11 @@ # Changelog +## Unreleased + +### Fixes + +- Emit transaction.data inside contexts.trace.data ([#3936](https://github.com/getsentry/sentry-dotnet/pull/3936)) + ## 5.1.0 ### Significant change in behavior @@ -13,7 +19,6 @@ ### Fixes -- Emit transaction.data inside contexts.trace.data ([#3936](https://github.com/getsentry/sentry-dotnet/pull/3936)) - Prevent Native EXC_BAD_ACCESS signal errors from being captured when managed NullRefrenceExceptions occur ([#3909](https://github.com/getsentry/sentry-dotnet/pull/3909)) - Fixed duplicate SentryMauiEventProcessors ([#3905](https://github.com/getsentry/sentry-dotnet/pull/3905)) - Fixed invalid string.Format index in Debug logs for the DiagnosticSource integration ([#3923](https://github.com/getsentry/sentry-dotnet/pull/3923)) From 19bbb62be99225dad478ae77999037213594f563 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Tue, 4 Feb 2025 10:19:35 -0500 Subject: [PATCH 07/16] Switch serialization test to use json path tests instead of verify --- ...zation_TransactionAndSpanData.verified.txt | 44 ------- test/Sentry.Tests/SerializationTests.cs | 118 +++--------------- .../Sentry.Tests/SerializationTests.verify.cs | 103 +++++++++++++++ 3 files changed, 119 insertions(+), 146 deletions(-) delete mode 100644 test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt create mode 100644 test/Sentry.Tests/SerializationTests.verify.cs diff --git a/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt b/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt deleted file mode 100644 index 8678e11e63..0000000000 --- a/test/Sentry.Tests/SerializationTests.Serialization_TransactionAndSpanData.verified.txt +++ /dev/null @@ -1,44 +0,0 @@ -{ - EventId: {}, - SpanId: {}, - ParentSpanId: {}, - Name: name, - Platform: csharp, - StartTimestamp: DateTimeOffset_1, - Operation: operation, - Description: , - IsSampled: false, - SampleRate: 0.0, - Request: {}, - Contexts: { - trace: { - SpanId: {}, - ParentSpanId: {}, - Operation: operation, - Description: , - IsSampled: false, - Extra: { - transaction1: transaction_value - } - } - }, - User: {}, - Sdk: {}, - Extra: { - transaction1: transaction_value - }, - Spans: [ - { - SpanId: {}, - ParentSpanId: {}, - StartTimestamp: DateTimeOffset_2, - IsFinished: false, - Operation: childop, - IsSampled: false, - Extra: { - span1: value1 - } - } - ], - IsFinished: false -} \ No newline at end of file diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index 04996b5e3a..cce7483d56 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -1,10 +1,8 @@ -#if NET7_0_OR_GREATER -using System.Text.Json.Serialization.Metadata; -#endif +using System.Text.Json.Nodes; namespace Sentry.Tests; -public class SerializationTests +public partial class SerializationTests { private readonly IDiagnosticLogger _testOutputLogger; @@ -14,7 +12,7 @@ public SerializationTests(ITestOutputHelper output) } [Fact] - public async Task Serialization_TransactionAndSpanData() + public void Serialization_TransactionAndSpanData() { var hub = Substitute.For(); var context = new TransactionContext("name", "operation", new SentryTraceHeader(SentryId.Empty, SpanId.Empty, false)); @@ -27,10 +25,21 @@ public async Task Serialization_TransactionAndSpanData() IsSampled = false }; transaction.SetExtra("transaction1", "transaction_value"); - await Verify(transaction); + var json = transaction.ToJsonString(_testOutputLogger); + _testOutputLogger.LogDebug(json); + + var node = JsonNode.Parse(json); + var dataNode = node?["contexts"]?["trace"]?["data"]?["transaction1"]?.GetValue(); + dataNode.Should().NotBeNull("contexts.trace.data.transaction1 not found"); + dataNode.Should().Be("transaction_value"); + + var spansNode = node?["spans"]?.AsArray(); + spansNode.Should().NotBeNull("spans not found"); + var spanDataNode = spansNode!.FirstOrDefault()?["data"]?["span1"]?.GetValue(); + spanDataNode.Should().NotBeNull("spans.data not found"); + spanDataNode.Should().Be("value1"); // verify deserialization - var json = transaction.ToJsonString(_testOutputLogger); var reader = new Utf8JsonReader(Encoding.UTF8.GetBytes(json)); var el = JsonElement.ParseValue(ref reader); var backTransaction = SentryTransaction.FromJson(el); @@ -38,99 +47,4 @@ public async Task Serialization_TransactionAndSpanData() backTransaction.Spans.First().Extra["span1"].Should().Be("value1", "Span value missing"); backTransaction.Contexts.Trace.Extra["transaction1"].Should().Be("transaction_value", "Transaction value missing"); } - - [Theory] - [MemberData(nameof(GetData))] - public async Task Serialization(string name, object target) - { - var json = target.ToJsonString(_testOutputLogger); - await Verify(json).UseParameters(name); - } - -#if NET7_0_OR_GREATER - internal class NestedStringClass { public string Value { get; set; } } - internal class NestedIntClass { public int Value { get; set; } } - internal class NestedNIntClass { public nint Value { get; set; } } - internal class NestedNuIntClass { public nuint Value { get; set; } } - internal class NestedIntPtrClass { public IntPtr Value { get; set; } } - internal class NestedNullableIntPtrClass { public IntPtr? Value { get; set; } } - internal class NestedUIntPtrClass { public UIntPtr Value { get; set; } } - internal class NestedNullableUIntPtrClass { public UIntPtr? Value { get; set; } } - - public static IEnumerable GetData() - { - yield return new object[] { "string", "string value" }; - yield return new object[] { "int", 5 }; - - JsonExtensions.ResetSerializerOptions(); - JsonExtensions.AddJsonSerializerContext(options => new SerializationTestsJsonContext(options)); - yield return new object[] { "nested string", new NestedStringClass { Value = "string value" } }; - yield return new object[] { "nested int", new NestedIntClass { Value = 5 } }; - yield return new object[] { "nested nint", new NestedNIntClass { Value = 5 } }; - yield return new object[] { "nested nuint", new NestedNuIntClass { Value = 5 } }; - yield return new object[] { "nested IntPtr", new NestedIntPtrClass { Value = (IntPtr)3 } }; - yield return new object[] { "nested nullable IntPtr", new NestedNullableIntPtrClass { Value = (IntPtr?)3 } }; - yield return new object[] { "nested UIntPtr", new NestedUIntPtrClass { Value = (UIntPtr)3 } }; - yield return new object[] { "nested nullable UIntPtr", new NestedNullableUIntPtrClass { Value = (UIntPtr?)3 } }; - - JsonExtensions.ResetSerializerOptions(); - JsonExtensions.AddJsonConverter(new CustomObjectConverter()); - JsonExtensions.AddJsonSerializerContext(options => new SerializationTestsJsonContext(options)); - yield return new object[] { "custom object with value", new CustomObject("test") }; - yield return new object[] { "custom object with null", new CustomObject(null) }; - } -#else - public static IEnumerable GetData() - { - yield return new object[] {"string", "string value"}; - yield return new object[] {"nested string", new {Value = "string value"}}; - yield return new object[] {"int", 5}; - yield return new object[] {"nested int", new {Value = 5}}; - yield return new object[] {"nested nint", new {Value = (nint)5}}; - yield return new object[] {"nested nuint", new {Value = (nuint)5}}; - yield return new object[] {"nested IntPtr", new {Value = (IntPtr)3}}; - yield return new object[] {"nested nullable IntPtr", new {Value = (IntPtr?)3}}; - yield return new object[] {"nested UIntPtr", new {Value = (UIntPtr)3}}; - yield return new object[] {"nested nullable UIntPtr", new {Value = (IntPtr?)3}}; - - JsonExtensions.ResetSerializerOptions(); - JsonExtensions.AddJsonConverter(new CustomObjectConverter()); - yield return new object[] {"custom object with value", new CustomObject("test")}; - yield return new object[] {"custom object with null", new CustomObject(null)}; - } -#endif - - public class CustomObject - { - public CustomObject(string value) - { - Value = value; - } - - internal string Value { get; } - } - - public class CustomObjectConverter : JsonConverter - { - public override CustomObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) - => new(reader.GetString()); - - public override void Write(Utf8JsonWriter writer, CustomObject value, JsonSerializerOptions options) - => writer.WriteStringValue(value.Value); - } -} - -#if NET7_0_OR_GREATER -[JsonSerializable(typeof(SerializationTests.CustomObject))] -[JsonSerializable(typeof(SerializationTests.NestedStringClass))] -[JsonSerializable(typeof(SerializationTests.NestedIntClass))] -[JsonSerializable(typeof(SerializationTests.NestedNIntClass))] -[JsonSerializable(typeof(SerializationTests.NestedNuIntClass))] -[JsonSerializable(typeof(SerializationTests.NestedIntPtrClass))] -[JsonSerializable(typeof(SerializationTests.NestedNullableIntPtrClass))] -[JsonSerializable(typeof(SerializationTests.NestedUIntPtrClass))] -[JsonSerializable(typeof(SerializationTests.NestedNullableUIntPtrClass))] -internal partial class SerializationTestsJsonContext : JsonSerializerContext -{ } -#endif diff --git a/test/Sentry.Tests/SerializationTests.verify.cs b/test/Sentry.Tests/SerializationTests.verify.cs new file mode 100644 index 0000000000..65b08857fa --- /dev/null +++ b/test/Sentry.Tests/SerializationTests.verify.cs @@ -0,0 +1,103 @@ +#if NET7_0_OR_GREATER +using System.Text.Json.Serialization.Metadata; +#endif + +namespace Sentry.Tests; + +public partial class SerializationTests +{ + [Theory] + [MemberData(nameof(GetData))] + public async Task Serialization(string name, object target) + { + var json = target.ToJsonString(_testOutputLogger); + await Verify(json).UseParameters(name); + } + +#if NET7_0_OR_GREATER + internal class NestedStringClass { public string Value { get; set; } } + internal class NestedIntClass { public int Value { get; set; } } + internal class NestedNIntClass { public nint Value { get; set; } } + internal class NestedNuIntClass { public nuint Value { get; set; } } + internal class NestedIntPtrClass { public IntPtr Value { get; set; } } + internal class NestedNullableIntPtrClass { public IntPtr? Value { get; set; } } + internal class NestedUIntPtrClass { public UIntPtr Value { get; set; } } + internal class NestedNullableUIntPtrClass { public UIntPtr? Value { get; set; } } + + public static IEnumerable GetData() + { + yield return new object[] { "string", "string value" }; + yield return new object[] { "int", 5 }; + + JsonExtensions.ResetSerializerOptions(); + JsonExtensions.AddJsonSerializerContext(options => new SerializationTestsJsonContext(options)); + yield return new object[] { "nested string", new NestedStringClass { Value = "string value" } }; + yield return new object[] { "nested int", new NestedIntClass { Value = 5 } }; + yield return new object[] { "nested nint", new NestedNIntClass { Value = 5 } }; + yield return new object[] { "nested nuint", new NestedNuIntClass { Value = 5 } }; + yield return new object[] { "nested IntPtr", new NestedIntPtrClass { Value = (IntPtr)3 } }; + yield return new object[] { "nested nullable IntPtr", new NestedNullableIntPtrClass { Value = (IntPtr?)3 } }; + yield return new object[] { "nested UIntPtr", new NestedUIntPtrClass { Value = (UIntPtr)3 } }; + yield return new object[] { "nested nullable UIntPtr", new NestedNullableUIntPtrClass { Value = (UIntPtr?)3 } }; + + JsonExtensions.ResetSerializerOptions(); + JsonExtensions.AddJsonConverter(new CustomObjectConverter()); + JsonExtensions.AddJsonSerializerContext(options => new SerializationTestsJsonContext(options)); + yield return new object[] { "custom object with value", new CustomObject("test") }; + yield return new object[] { "custom object with null", new CustomObject(null) }; + } +#else + public static IEnumerable GetData() + { + yield return new object[] {"string", "string value"}; + yield return new object[] {"nested string", new {Value = "string value"}}; + yield return new object[] {"int", 5}; + yield return new object[] {"nested int", new {Value = 5}}; + yield return new object[] {"nested nint", new {Value = (nint)5}}; + yield return new object[] {"nested nuint", new {Value = (nuint)5}}; + yield return new object[] {"nested IntPtr", new {Value = (IntPtr)3}}; + yield return new object[] {"nested nullable IntPtr", new {Value = (IntPtr?)3}}; + yield return new object[] {"nested UIntPtr", new {Value = (UIntPtr)3}}; + yield return new object[] {"nested nullable UIntPtr", new {Value = (IntPtr?)3}}; + + JsonExtensions.ResetSerializerOptions(); + JsonExtensions.AddJsonConverter(new CustomObjectConverter()); + yield return new object[] {"custom object with value", new CustomObject("test")}; + yield return new object[] {"custom object with null", new CustomObject(null)}; + } +#endif + + public class CustomObject + { + public CustomObject(string value) + { + Value = value; + } + + internal string Value { get; } + } + + public class CustomObjectConverter : JsonConverter + { + public override CustomObject Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + => new(reader.GetString()); + + public override void Write(Utf8JsonWriter writer, CustomObject value, JsonSerializerOptions options) + => writer.WriteStringValue(value.Value); + } +} + +#if NET7_0_OR_GREATER +[JsonSerializable(typeof(SerializationTests.CustomObject))] +[JsonSerializable(typeof(SerializationTests.NestedStringClass))] +[JsonSerializable(typeof(SerializationTests.NestedIntClass))] +[JsonSerializable(typeof(SerializationTests.NestedNIntClass))] +[JsonSerializable(typeof(SerializationTests.NestedNuIntClass))] +[JsonSerializable(typeof(SerializationTests.NestedIntPtrClass))] +[JsonSerializable(typeof(SerializationTests.NestedNullableIntPtrClass))] +[JsonSerializable(typeof(SerializationTests.NestedUIntPtrClass))] +[JsonSerializable(typeof(SerializationTests.NestedNullableUIntPtrClass))] +internal partial class SerializationTestsJsonContext : JsonSerializerContext +{ +} +#endif From b39666853d22de4e8fe8d76d0935ab5d9b397efd Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 6 Feb 2025 13:49:20 -0500 Subject: [PATCH 08/16] Revert "Push SentryTransaction extras into the Contexts.Trace.Data element" This reverts commit 4292c462219e8c19bd17dba9695db444f4b57e9f. --- src/Sentry/Protocol/Trace.cs | 18 ++---------------- src/Sentry/SentryTransaction.cs | 11 +++++++++-- 2 files changed, 11 insertions(+), 18 deletions(-) diff --git a/src/Sentry/Protocol/Trace.cs b/src/Sentry/Protocol/Trace.cs index e96d647094..289b2a4b08 100644 --- a/src/Sentry/Protocol/Trace.cs +++ b/src/Sentry/Protocol/Trace.cs @@ -7,7 +7,7 @@ namespace Sentry.Protocol; /// /// Trace context data. /// -public class Trace : ITraceContext, IHasExtra, ISentryJsonSerializable, ICloneable, IUpdatable +public class Trace : ITraceContext, ISentryJsonSerializable, ICloneable, IUpdatable { /// /// Tells Sentry which type of context this is. @@ -103,7 +103,6 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteString("origin", Origin ?? Internal.OriginHelper.Manual); writer.WriteStringIfNotWhiteSpace("description", Description); writer.WriteStringIfNotWhiteSpace("status", Status?.ToString().ToSnakeCase()); - writer.WriteDictionaryIfNotEmpty("data", _extra, logger); writer.WriteEndObject(); } @@ -121,7 +120,6 @@ public static Trace FromJson(JsonElement json) var description = json.GetPropertyOrNull("description")?.GetString(); var status = json.GetPropertyOrNull("status")?.GetString()?.Replace("_", "").ParseEnum(); var isSampled = json.GetPropertyOrNull("sampled")?.GetBoolean(); - var extra = json.GetPropertyOrNull("data")?.GetDictionaryOrNull() ?? new(); return new Trace { @@ -132,19 +130,7 @@ public static Trace FromJson(JsonElement json) Origin = origin, Description = description, Status = status, - IsSampled = isSampled, - _extra = extra + IsSampled = isSampled }; } - - - // not readonly for serialization - private Dictionary _extra = new(); - - /// - public IReadOnlyDictionary Extra => _extra; - - /// - public void SetExtra(string key, object? value) - => _extra[key] = value; } diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index 1f067003b6..b69acd3f52 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -179,9 +179,11 @@ public IReadOnlyList Fingerprint /// public IReadOnlyCollection Breadcrumbs => _breadcrumbs; + // Not readonly because of deserialization + private Dictionary _extra = new(); /// - public IReadOnlyDictionary Extra => Contexts.Trace.Extra; + public IReadOnlyDictionary Extra => _extra; // Not readonly because of deserialization private Dictionary _tags = new(); @@ -268,6 +270,7 @@ public SentryTransaction(ITransactionTracer tracer) Sdk = tracer.Sdk; Fingerprint = tracer.Fingerprint; _breadcrumbs = tracer.Breadcrumbs.ToList(); + _extra = tracer.Extra.ToDict(); _tags = tracer.Tags.ToDict(); _spans = FromTracerSpans(tracer); @@ -337,7 +340,7 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) => /// public void SetExtra(string key, object? value) => - Contexts.Trace.SetExtra(key, value); + _extra[key] = value; /// public void SetTag(string key, string value) => @@ -398,6 +401,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteSerializable("sdk", Sdk, logger); writer.WriteStringArrayIfNotEmpty("fingerprint", _fingerprint); writer.WriteArrayIfNotEmpty("breadcrumbs", _breadcrumbs, logger); + writer.WriteDictionaryIfNotEmpty("extra", _extra, logger); writer.WriteStringDictionaryIfNotEmpty("tags", _tags!); writer.WriteArrayIfNotEmpty("spans", _spans, logger); writer.WriteDictionaryIfNotEmpty("measurements", _measurements, logger); @@ -430,6 +434,8 @@ public static SentryTransaction FromJson(JsonElement json) .EnumerateArray().Select(j => j.GetString()!).ToArray(); var breadcrumbs = json.GetPropertyOrNull("breadcrumbs")? .EnumerateArray().Select(Breadcrumb.FromJson).ToList() ?? new(); + var extra = json.GetPropertyOrNull("extra")? + .GetDictionaryOrNull() ?? new(); var tags = json.GetPropertyOrNull("tags")? .GetStringDictionaryOrNull()?.WhereNotNullValue().ToDict() ?? new(); var measurements = json.GetPropertyOrNull("measurements")? @@ -453,6 +459,7 @@ public static SentryTransaction FromJson(JsonElement json) Sdk = sdk, _fingerprint = fingerprint, _breadcrumbs = breadcrumbs, + _extra = extra, _tags = tags, _measurements = measurements, _spans = spans From eda625a36696264bd6751ada2003c061d22dc847 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Thu, 6 Feb 2025 13:59:01 -0500 Subject: [PATCH 09/16] Trace should not use interface, just set implementation methods. SentryTransaction has SetExtra marked as obsolete --- src/Sentry/Protocol/Trace.cs | 23 +++++++++++++++++++++-- src/Sentry/SentryTransaction.cs | 1 + test/Sentry.Tests/SerializationTests.cs | 4 ++-- 3 files changed, 24 insertions(+), 4 deletions(-) diff --git a/src/Sentry/Protocol/Trace.cs b/src/Sentry/Protocol/Trace.cs index 289b2a4b08..8878aab170 100644 --- a/src/Sentry/Protocol/Trace.cs +++ b/src/Sentry/Protocol/Trace.cs @@ -50,6 +50,21 @@ internal set /// public bool? IsSampled { get; internal set; } + private Dictionary _data = new(); + + /// + /// Get the metadata + /// + public IReadOnlyDictionary Data => _data; + + /// + /// Adds metadata to the trace + /// + /// + /// + public void SetData(string key, object? value) + => _data[key] = value; + /// /// Clones this instance. /// @@ -63,7 +78,8 @@ internal set Operation = Operation, Origin = Origin, Status = Status, - IsSampled = IsSampled + IsSampled = IsSampled, + _data = _data.ToDict() }; /// @@ -103,6 +119,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteString("origin", Origin ?? Internal.OriginHelper.Manual); writer.WriteStringIfNotWhiteSpace("description", Description); writer.WriteStringIfNotWhiteSpace("status", Status?.ToString().ToSnakeCase()); + writer.WriteDictionaryIfNotEmpty("data", _data, logger); writer.WriteEndObject(); } @@ -120,6 +137,7 @@ public static Trace FromJson(JsonElement json) var description = json.GetPropertyOrNull("description")?.GetString(); var status = json.GetPropertyOrNull("status")?.GetString()?.Replace("_", "").ParseEnum(); var isSampled = json.GetPropertyOrNull("sampled")?.GetBoolean(); + var data = json.GetPropertyOrNull("data")?.GetDictionaryOrNull() ?? new(); return new Trace { @@ -130,7 +148,8 @@ public static Trace FromJson(JsonElement json) Origin = origin, Description = description, Status = status, - IsSampled = isSampled + IsSampled = isSampled, + _data = data }; } } diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index b69acd3f52..3cb2908ce0 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -339,6 +339,7 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) => _breadcrumbs.Add(breadcrumb); /// + [Obsolete("Add metadata to Contexts.Trace.SetData")] public void SetExtra(string key, object? value) => _extra[key] = value; diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index cce7483d56..d2baa1023b 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -24,7 +24,7 @@ public void Serialization_TransactionAndSpanData() { IsSampled = false }; - transaction.SetExtra("transaction1", "transaction_value"); + transaction.Contexts.Trace.SetData("transaction1", "transaction_value"); var json = transaction.ToJsonString(_testOutputLogger); _testOutputLogger.LogDebug(json); @@ -45,6 +45,6 @@ public void Serialization_TransactionAndSpanData() var backTransaction = SentryTransaction.FromJson(el); backTransaction.Spans.First().Extra["span1"].Should().Be("value1", "Span value missing"); - backTransaction.Contexts.Trace.Extra["transaction1"].Should().Be("transaction_value", "Transaction value missing"); + backTransaction.Contexts.Trace.Data["transaction1"].Should().Be("transaction_value", "Transaction value missing"); } } From c480bec2c45a9f4f8aeb6aff64dec4755fb9719e Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 10 Feb 2025 12:48:35 -0500 Subject: [PATCH 10/16] Marking SetExtra/Extra as obsolete - Add SetData/Data but reroute it to contexts.trace.SetData/Data --- src/Sentry/SentryTransaction.cs | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index 3cb2908ce0..8a423eacd7 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -179,12 +179,6 @@ public IReadOnlyList Fingerprint /// public IReadOnlyCollection Breadcrumbs => _breadcrumbs; - // Not readonly because of deserialization - private Dictionary _extra = new(); - - /// - public IReadOnlyDictionary Extra => _extra; - // Not readonly because of deserialization private Dictionary _tags = new(); @@ -270,7 +264,6 @@ public SentryTransaction(ITransactionTracer tracer) Sdk = tracer.Sdk; Fingerprint = tracer.Fingerprint; _breadcrumbs = tracer.Breadcrumbs.ToList(); - _extra = tracer.Extra.ToDict(); _tags = tracer.Tags.ToDict(); _spans = FromTracerSpans(tracer); @@ -339,9 +332,17 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) => _breadcrumbs.Add(breadcrumb); /// - [Obsolete("Add metadata to Contexts.Trace.SetData")] + [Obsolete("Use Data property instead.")] + public IReadOnlyDictionary Extra => _contexts.Trace.Data; + + /// + [Obsolete("Use SetData")] public void SetExtra(string key, object? value) => - _extra[key] = value; + SetData(key, value); + + /// + public void SetData(string key, object value) => + _contexts.Trace.SetData(key, value); /// public void SetTag(string key, string value) => From b8f34d1a1970c2d0df2ef88a888fb60c3f7e937f Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 10 Feb 2025 13:15:58 -0500 Subject: [PATCH 11/16] Cleanup --- src/Sentry/SentryTransaction.cs | 4 +--- src/Sentry/SpanTracer.cs | 14 +++++++++++--- test/Sentry.Tests/SerializationTests.cs | 12 ++++++------ 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index 8a423eacd7..cf99bc98aa 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -341,7 +341,7 @@ public void SetExtra(string key, object? value) => SetData(key, value); /// - public void SetData(string key, object value) => + public void SetData(string key, object? value) => _contexts.Trace.SetData(key, value); /// @@ -403,7 +403,6 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteSerializable("sdk", Sdk, logger); writer.WriteStringArrayIfNotEmpty("fingerprint", _fingerprint); writer.WriteArrayIfNotEmpty("breadcrumbs", _breadcrumbs, logger); - writer.WriteDictionaryIfNotEmpty("extra", _extra, logger); writer.WriteStringDictionaryIfNotEmpty("tags", _tags!); writer.WriteArrayIfNotEmpty("spans", _spans, logger); writer.WriteDictionaryIfNotEmpty("measurements", _measurements, logger); @@ -461,7 +460,6 @@ public static SentryTransaction FromJson(JsonElement json) Sdk = sdk, _fingerprint = fingerprint, _breadcrumbs = breadcrumbs, - _extra = extra, _tags = tags, _measurements = measurements, _spans = spans diff --git a/src/Sentry/SpanTracer.cs b/src/Sentry/SpanTracer.cs index 9dbbbc4b96..499492145d 100644 --- a/src/Sentry/SpanTracer.cs +++ b/src/Sentry/SpanTracer.cs @@ -82,13 +82,21 @@ public void SetTag(string key, string value) => public void UnsetTag(string key) => (InternalTags ??= new ConcurrentDictionary()).TryRemove(key, out _); - private readonly ConcurrentDictionary _data = new(); + private Dictionary? _data; /// - public IReadOnlyDictionary Extra => _data; + public IReadOnlyDictionary Data => + _data ??= new Dictionary(); /// - public void SetExtra(string key, object? value) => _data[key] = value; + public void SetData(string key, object? value) => + (_data ??= new Dictionary())[key] = value; + + /// + public IReadOnlyDictionary Extra => Data; + + /// + public void SetExtra(string key, object? value) => SetData(key, value); internal Func? IsFiltered { get; set; } diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index d2baa1023b..d135bcc8d8 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -18,13 +18,13 @@ public void Serialization_TransactionAndSpanData() var context = new TransactionContext("name", "operation", new SentryTraceHeader(SentryId.Empty, SpanId.Empty, false)); var transactionTracer = new TransactionTracer(hub, context); var span = transactionTracer.StartChild("childop"); - span.SetExtra("span1", "value1"); + span.SetData("span1", "value1"); - var transaction = new SentryTransaction(transactionTracer) - { - IsSampled = false - }; - transaction.Contexts.Trace.SetData("transaction1", "transaction_value"); + var transaction = new SentryTransaction(transactionTracer) + { + IsSampled = false + }; + transaction.SetData("transaction1", "transaction_value"); var json = transaction.ToJsonString(_testOutputLogger); _testOutputLogger.LogDebug(json); From 5c549241c55419a01950921c8b27731a70d1b0f8 Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Mon, 10 Feb 2025 13:49:14 -0500 Subject: [PATCH 12/16] Move data for ISpan - add new interface to prevent mass deprecation on IHasExtras --- src/Sentry/IHasData.cs | 17 +++++++++++++ src/Sentry/ISpanData.cs | 2 +- src/Sentry/Internal/NoOpSpan.cs | 5 ++++ src/Sentry/SentrySpan.cs | 25 +++++++++++++------ src/Sentry/SentryTransaction.cs | 5 +++- src/Sentry/TransactionTracer.cs | 15 ++++++++--- .../Protocol/SentryTransactionTests.cs | 2 +- test/Sentry.Tests/SerializationTests.cs | 2 +- 8 files changed, 59 insertions(+), 14 deletions(-) create mode 100644 src/Sentry/IHasData.cs diff --git a/src/Sentry/IHasData.cs b/src/Sentry/IHasData.cs new file mode 100644 index 0000000000..980f403731 --- /dev/null +++ b/src/Sentry/IHasData.cs @@ -0,0 +1,17 @@ +namespace Sentry; + +/// +/// Implemented by objects that contain a map of untyped additional metadata. +/// +public interface IHasData +{ + /// + /// An arbitrary mapping of additional metadata to store with the event. + /// + IReadOnlyDictionary Data { get; } + + /// + /// Sets an extra. + /// + void SetData(string key, object? value); +} diff --git a/src/Sentry/ISpanData.cs b/src/Sentry/ISpanData.cs index 373ff75c34..3a475102b8 100644 --- a/src/Sentry/ISpanData.cs +++ b/src/Sentry/ISpanData.cs @@ -5,7 +5,7 @@ namespace Sentry; /// /// Immutable data belonging to a span. /// -public interface ISpanData : ITraceContext, IHasTags, IHasExtra +public interface ISpanData : ITraceContext, IHasData, IHasTags, IHasExtra { /// /// Start timestamp. diff --git a/src/Sentry/Internal/NoOpSpan.cs b/src/Sentry/Internal/NoOpSpan.cs index babecc4a4d..f6e49e5a2c 100644 --- a/src/Sentry/Internal/NoOpSpan.cs +++ b/src/Sentry/Internal/NoOpSpan.cs @@ -19,6 +19,7 @@ protected NoOpSpan() public bool? IsSampled => default; public IReadOnlyDictionary Tags => ImmutableDictionary.Empty; public IReadOnlyDictionary Extra => ImmutableDictionary.Empty; + public IReadOnlyDictionary Data => ImmutableDictionary.Empty; public DateTimeOffset StartTimestamp => default; public DateTimeOffset? EndTimestamp => default; public bool IsFinished => default; @@ -71,6 +72,10 @@ public void SetExtra(string key, object? value) { } + public void SetData(string key, object? value) + { + } + public SentryTraceHeader GetTraceHeader() => SentryTraceHeader.Empty; public IReadOnlyDictionary Measurements => ImmutableDictionary.Empty; diff --git a/src/Sentry/SentrySpan.cs b/src/Sentry/SentrySpan.cs index 9031556c7d..e94ca99074 100644 --- a/src/Sentry/SentrySpan.cs +++ b/src/Sentry/SentrySpan.cs @@ -66,15 +66,26 @@ public void UnsetTag(string key) => (_tags ??= new Dictionary()).Remove(key); // Aka 'data' - private Dictionary? _extra; private readonly MetricsSummary? _metricsSummary; + + private Dictionary? _data; + + /// + public IReadOnlyDictionary Data => + _data ??= new Dictionary(); + + /// + public void SetData(string key, object? value) => + (_data ??= new Dictionary())[key] = value; + /// - public IReadOnlyDictionary Extra => _extra ??= new Dictionary(); + [Obsolete("Use SetData")] + public IReadOnlyDictionary Extra => Data; /// - public void SetExtra(string key, object? value) => - (_extra ??= new Dictionary())[key] = value; + [Obsolete("Use Data")] + public void SetExtra(string key, object? value) => SetData(key, value); /// /// Initializes an instance of . @@ -100,7 +111,7 @@ public SentrySpan(ISpan tracer) Description = tracer.Description; Status = tracer.Status; IsSampled = tracer.IsSampled; - _extra = tracer.Extra.ToDict(); + _data = tracer.Data.ToDict(); if (tracer is SpanTracer spanTracer) { @@ -138,7 +149,7 @@ public void WriteTo(Utf8JsonWriter writer, IDiagnosticLogger? logger) writer.WriteString("start_timestamp", StartTimestamp); writer.WriteStringIfNotNull("timestamp", EndTimestamp); writer.WriteStringDictionaryIfNotEmpty("tags", _tags!); - writer.WriteDictionaryIfNotEmpty("data", _extra!, logger); + writer.WriteDictionaryIfNotEmpty("data", _data!, logger); writer.WriteDictionaryIfNotEmpty("measurements", _measurements, logger); writer.WriteSerializableIfNotNull("_metrics_summary", _metricsSummary, logger); @@ -173,7 +184,7 @@ public static SentrySpan FromJson(JsonElement json) Status = status, IsSampled = isSampled, _tags = tags!, - _extra = data!, + _data = data!, _measurements = measurements, }; } diff --git a/src/Sentry/SentryTransaction.cs b/src/Sentry/SentryTransaction.cs index cf99bc98aa..386891ec01 100644 --- a/src/Sentry/SentryTransaction.cs +++ b/src/Sentry/SentryTransaction.cs @@ -332,7 +332,10 @@ public void AddBreadcrumb(Breadcrumb breadcrumb) => _breadcrumbs.Add(breadcrumb); /// - [Obsolete("Use Data property instead.")] + public IReadOnlyDictionary Data => _contexts.Trace.Data; + + /// + [Obsolete("Use Data")] public IReadOnlyDictionary Extra => _contexts.Trace.Data; /// diff --git a/src/Sentry/TransactionTracer.cs b/src/Sentry/TransactionTracer.cs index 69376ad71f..e8059a2d00 100644 --- a/src/Sentry/TransactionTracer.cs +++ b/src/Sentry/TransactionTracer.cs @@ -157,10 +157,15 @@ public IReadOnlyList Fingerprint /// public IReadOnlyCollection Breadcrumbs => _breadcrumbs; - private readonly ConcurrentDictionary _extra = new(); + private readonly ConcurrentDictionary _data = new(); /// - public IReadOnlyDictionary Extra => _extra; + [Obsolete("Use Data")] + public IReadOnlyDictionary Extra => _data; + + /// + public IReadOnlyDictionary Data => _data; + private readonly ConcurrentDictionary _tags = new(); @@ -270,7 +275,11 @@ internal TransactionTracer(IHub hub, ITransactionContext context, TimeSpan? idle public void AddBreadcrumb(Breadcrumb breadcrumb) => _breadcrumbs.Add(breadcrumb); /// - public void SetExtra(string key, object? value) => _extra[key] = value; + [Obsolete("Use SetData")] + public void SetExtra(string key, object? value) => _data[key] = value; + + /// + public void SetData(string key, object? value) => _data[key] = value; /// public void SetTag(string key, string value) => _tags[key] = value; diff --git a/test/Sentry.Tests/Protocol/SentryTransactionTests.cs b/test/Sentry.Tests/Protocol/SentryTransactionTests.cs index 597e275c15..4e0872ada1 100644 --- a/test/Sentry.Tests/Protocol/SentryTransactionTests.cs +++ b/test/Sentry.Tests/Protocol/SentryTransactionTests.cs @@ -207,7 +207,7 @@ public void SerializeObject_AllPropertiesSetToNonDefault_SerializesValidObject() "category", BreadcrumbLevel.Warning)); - transaction.SetExtra("extra_key", "extra_value"); + transaction.SetData("extra_key", "extra_value"); transaction.Fingerprint = new[] { "fingerprint" }; transaction.SetTag("tag_key", "tag_value"); transaction.SetMeasurement("measurement_1", 111); diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index d135bcc8d8..30643a97f3 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -44,7 +44,7 @@ public void Serialization_TransactionAndSpanData() var el = JsonElement.ParseValue(ref reader); var backTransaction = SentryTransaction.FromJson(el); - backTransaction.Spans.First().Extra["span1"].Should().Be("value1", "Span value missing"); + backTransaction.Spans.First().Data["span1"].Should().Be("value1", "Span value missing"); backTransaction.Contexts.Trace.Data["transaction1"].Should().Be("transaction_value", "Transaction value missing"); } } From 330223d81ef580df80cc484e8b2242de2891d11f Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Wed, 12 Feb 2025 09:27:46 -0500 Subject: [PATCH 13/16] Restore concurrent dictionary on SpanTracer --- src/Sentry/SpanTracer.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Sentry/SpanTracer.cs b/src/Sentry/SpanTracer.cs index 499492145d..cb8d6c3707 100644 --- a/src/Sentry/SpanTracer.cs +++ b/src/Sentry/SpanTracer.cs @@ -82,15 +82,15 @@ public void SetTag(string key, string value) => public void UnsetTag(string key) => (InternalTags ??= new ConcurrentDictionary()).TryRemove(key, out _); - private Dictionary? _data; + private ConcurrentDictionary? _data; /// public IReadOnlyDictionary Data => - _data ??= new Dictionary(); + _data ??= new ConcurrentDictionary(); /// public void SetData(string key, object? value) => - (_data ??= new Dictionary())[key] = value; + (_data ??= new ConcurrentDictionary())[key] = value; /// public IReadOnlyDictionary Extra => Data; From c7cdedf973d2b06a07172062ca8dac82d5ab860a Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Wed, 12 Feb 2025 14:45:00 +0000 Subject: [PATCH 14/16] Format code --- test/Sentry.Tests/SerializationTests.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/Sentry.Tests/SerializationTests.cs b/test/Sentry.Tests/SerializationTests.cs index 30643a97f3..51a57bdd34 100644 --- a/test/Sentry.Tests/SerializationTests.cs +++ b/test/Sentry.Tests/SerializationTests.cs @@ -20,10 +20,10 @@ public void Serialization_TransactionAndSpanData() var span = transactionTracer.StartChild("childop"); span.SetData("span1", "value1"); - var transaction = new SentryTransaction(transactionTracer) - { - IsSampled = false - }; + var transaction = new SentryTransaction(transactionTracer) + { + IsSampled = false + }; transaction.SetData("transaction1", "transaction_value"); var json = transaction.ToJsonString(_testOutputLogger); _testOutputLogger.LogDebug(json); From 64913017a9095829ca6da6c4605307b35461557a Mon Sep 17 00:00:00 2001 From: Allan Ritchie Date: Wed, 12 Feb 2025 13:59:44 -0500 Subject: [PATCH 15/16] Fix threadsafe fail to resolve unit test fail --- src/Sentry/SpanTracer.cs | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/Sentry/SpanTracer.cs b/src/Sentry/SpanTracer.cs index cb8d6c3707..495f45b6af 100644 --- a/src/Sentry/SpanTracer.cs +++ b/src/Sentry/SpanTracer.cs @@ -82,15 +82,14 @@ public void SetTag(string key, string value) => public void UnsetTag(string key) => (InternalTags ??= new ConcurrentDictionary()).TryRemove(key, out _); - private ConcurrentDictionary? _data; + readonly ConcurrentDictionary _data = new(); /// - public IReadOnlyDictionary Data => - _data ??= new ConcurrentDictionary(); + public IReadOnlyDictionary Data => _data; /// public void SetData(string key, object? value) => - (_data ??= new ConcurrentDictionary())[key] = value; + _data[key] = value; /// public IReadOnlyDictionary Extra => Data; From 69b74f657d6c2bf996a95d5e93f2462753bf35de Mon Sep 17 00:00:00 2001 From: Sentry Github Bot Date: Wed, 12 Feb 2025 19:14:24 +0000 Subject: [PATCH 16/16] Format code --- src/Sentry/SpanTracer.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Sentry/SpanTracer.cs b/src/Sentry/SpanTracer.cs index 495f45b6af..ed51d48eaa 100644 --- a/src/Sentry/SpanTracer.cs +++ b/src/Sentry/SpanTracer.cs @@ -82,7 +82,7 @@ public void SetTag(string key, string value) => public void UnsetTag(string key) => (InternalTags ??= new ConcurrentDictionary()).TryRemove(key, out _); - readonly ConcurrentDictionary _data = new(); + private readonly ConcurrentDictionary _data = new(); /// public IReadOnlyDictionary Data => _data;