From 080ed80864619b330d7ab2af9d5a6c4008a34bbb Mon Sep 17 00:00:00 2001 From: antonfirsov Date: Mon, 22 Apr 2024 15:28:40 +0200 Subject: [PATCH 1/3] implement Activity.AddLink --- ...em.Diagnostics.DiagnosticSourceActivity.cs | 1 + .../src/System/Diagnostics/Activity.cs | 15 +++++++++++ .../tests/ActivityTests.cs | 25 +++++++++++++++++++ 3 files changed, 41 insertions(+) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs index 7cb90d245dcf93..c38dfeecad8c63 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/ref/System.Diagnostics.DiagnosticSourceActivity.cs @@ -50,6 +50,7 @@ public string? Id public string? TraceStateString { get { throw null; } set { } } public System.Diagnostics.Activity AddBaggage(string key, string? value) { throw null; } public System.Diagnostics.Activity AddEvent(System.Diagnostics.ActivityEvent e) { throw null; } + public System.Diagnostics.Activity AddLink(System.Diagnostics.ActivityLink link) { throw null; } public System.Diagnostics.Activity AddTag(string key, string? value) { throw null; } public System.Diagnostics.Activity AddTag(string key, object? value) { throw null; } public System.Diagnostics.Activity SetTag(string key, object? value) { throw null; } diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index 0605251a93b7a7..614e8033c68678 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -517,6 +517,21 @@ public Activity AddEvent(ActivityEvent e) return this; } + /// + /// Add an to the list. + /// + /// The to add. + /// for convenient chaining. + public Activity AddLink(ActivityLink link) + { + if (_links != null || Interlocked.CompareExchange(ref _links, new DiagLinkedList(link), null) != null) + { + _links.Add(link); + } + + return this; + } + /// /// Update the Activity to have baggage with an additional 'key' and value 'value'. /// This shows up in the enumeration as well as the diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs index ae3c138e369714..10c2be0888a3b5 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs @@ -1597,6 +1597,31 @@ public void TestEvent() Assert.Equal(0, activity.Events.ElementAt(1).Tags.Count()); } + [Fact] + public void AddLinkTest() + { + ActivityContext c1 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + ActivityContext c2 = new ActivityContext(ActivityTraceId.CreateRandom(), ActivitySpanId.CreateRandom(), ActivityTraceFlags.None); + + ActivityLink l1 = new ActivityLink(c1); + ActivityLink l2 = new ActivityLink(c2, new ActivityTagsCollection() + { + new KeyValuePair("foo", 99) + }); + + Activity activity = new Activity("LinkTest"); + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + Assert.True(ReferenceEquals(activity, activity.AddLink(l2))); + + ActivityLink[] links = activity.Links.ToArray(); + Assert.Equal(2, links.Length); + Assert.Equal(c1, links[0].Context); + Assert.Equal(c2, links[1].Context); + KeyValuePair tag = links[1].Tags.Single(); + Assert.Equal("foo", tag.Key); + Assert.Equal(99, tag.Value); + } + [Fact] public void TestIsAllDataRequested() { From b367037c92a916bab076127e8fad3c1df78a3d0e Mon Sep 17 00:00:00 2001 From: antonfirsov Date: Wed, 24 Apr 2024 22:31:56 +0200 Subject: [PATCH 2/3] extend tests --- .../tests/ActivityTests.cs | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs index 10c2be0888a3b5..00cb26017a3846 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/tests/ActivityTests.cs @@ -1613,10 +1613,14 @@ public void AddLinkTest() Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); Assert.True(ReferenceEquals(activity, activity.AddLink(l2))); + // Add a duplicate of l1. The implementation doesn't check for duplicates. + Assert.True(ReferenceEquals(activity, activity.AddLink(l1))); + ActivityLink[] links = activity.Links.ToArray(); - Assert.Equal(2, links.Length); + Assert.Equal(3, links.Length); Assert.Equal(c1, links[0].Context); Assert.Equal(c2, links[1].Context); + Assert.Equal(c1, links[2].Context); KeyValuePair tag = links[1].Tags.Single(); Assert.Equal("foo", tag.Key); Assert.Equal(99, tag.Value); @@ -2188,12 +2192,14 @@ public void EnumerateLinksTest() var context1 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); var context2 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); + var context3 = new ActivityContext(ActivityTraceId.CreateRandom(), default, ActivityTraceFlags.None); a = source.CreateActivity( name: "Root", kind: ActivityKind.Internal, parentContext: default, links: new[] { new ActivityLink(context1), new ActivityLink(context2) }); + a.AddLink(new ActivityLink(context3)); Assert.NotNull(a); @@ -2207,6 +2213,9 @@ public void EnumerateLinksTest() Assert.True(enumerator.MoveNext()); Assert.Equal(context2.TraceId, enumerator.Current.Context.TraceId); values.Add(enumerator.Current); + Assert.True(enumerator.MoveNext()); + Assert.Equal(context3.TraceId, enumerator.Current.Context.TraceId); + values.Add(enumerator.Current); Assert.False(enumerator.MoveNext()); Assert.Equal(a.Links, values); From f17a83e604df5f3328867ff96be881baa494c56b Mon Sep 17 00:00:00 2001 From: antonfirsov Date: Wed, 24 Apr 2024 22:35:25 +0200 Subject: [PATCH 3/3] Add remarks to docs required by https://github.com/open-telemetry/opentelemetry-specification/blob/main/specification/trace/api.md#link --- .../src/System/Diagnostics/Activity.cs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs index 614e8033c68678..3a332ec4f13239 100644 --- a/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs +++ b/src/libraries/System.Diagnostics.DiagnosticSource/src/System/Diagnostics/Activity.cs @@ -522,6 +522,10 @@ public Activity AddEvent(ActivityEvent e) /// /// The to add. /// for convenient chaining. + /// + /// For contexts that are available during span creation, adding links at span creation is preferred to calling later, + /// because head sampling decisions can only consider information present during span creation. + /// public Activity AddLink(ActivityLink link) { if (_links != null || Interlocked.CompareExchange(ref _links, new DiagLinkedList(link), null) != null)