-
Notifications
You must be signed in to change notification settings - Fork 442
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
Span links improvements and bug fix #3123
base: main
Are you sure you want to change the base?
Conversation
Datadog ReportBranch report: ✅ 0 Failed, 5225 Passed, 73 Skipped, 2m 9.58s Total Time |
f7a9058
to
a455896
Compare
if len(s.SpanLinks) == 0 { | ||
return | ||
} | ||
spanLinkBytes, err := json.Marshal(s.SpanLinks) |
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.
A little concerned about performance, but not sure if there's any other way to do this. We have to serialize the links into a JSON string such as "[{\"trace_id\":0,\"trace_id_high\":0,\"span_id\":0,\"attributes\":{\"link.kind\":\"span-pointer\",\"ptr.dir\":\"d\",\"ptr.hash\":\"eb29cb7d923f904f02bd8b3d85e228ed\",\"ptr.kind\":\"aws.s3.object\"},\"tracestate\":\"\",\"flags\":0}]"
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.
You could always add a benchmark for that
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.
It's actually must faster than I expected
cpu: Apple M3 Max
BenchmarkSerializeSpanLinksInMeta
BenchmarkSerializeSpanLinksInMeta-16 1253884 964.4 ns/op
a455896
to
b081005
Compare
AddSpanLinks
method; serialize span links in meta; fix bug with missing fields in span links…tion works properly
b081005
to
72d9dbe
Compare
72d9dbe
to
e1c23c8
Compare
BenchmarksBenchmark execution time: 2025-02-03 15:39:15 Comparing candidate commit 43e6edc in PR branch Found 0 performance improvements and 2 performance regressions! Performance is the same for 57 metrics, 0 unstable metrics. scenario:BenchmarkSetTagMetric-24
scenario:BenchmarkSetTagString-24
|
ddtrace/ddtrace.go
Outdated
@@ -79,6 +79,9 @@ type Span interface { | |||
// item should propagate to all descendant spans, both in- and cross-process. | |||
SetBaggageItem(key, val string) | |||
|
|||
// AddSpanLinks appends the given links to the span's span links. | |||
AddSpanLinks(spanLinks ...SpanLink) |
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.
A few notes:
- We already have support for adding span links to a span when you are starting it; do you need this new API because you need to add span links to a span that has already been started? If so, what is the motivation for that? If not, can you use the existing API?
- Adding a new method to the existing Span interface is a breaking change. The alternative approach is to introduce a new interface with the new method (with the old interface embedded). You can see what we do for adding spanlinks to the span context here: https://github.com/DataDog/dd-trace-go/pull/2973/files
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.
- Yes, I do need to add span links to a span that's already started. In my case, I will need to get some values from an S3/Dynamo response before adding span links, which occurs right before the span is finished.
- Out of curiosity, why is this a breaking change? Done in 66d3a67, is that what you were looking for?
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.
Public interfaces are considered "contracts" in Golang. Modifying them is "breaking contract" because that means every type which expects to satisfy this interface must now be updated -- this can impact customer code.
… to the existing span interface (breaking change)
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.
Looking good, just please add tests (no matter how trivial) to indicate how this API should be used!
This comment was marked as resolved.
This comment was marked as resolved.
@@ -514,6 +543,8 @@ func (s *span) Finish(opts ...ddtrace.FinishOption) { | |||
} | |||
} | |||
|
|||
s.serializeSpanLinksInMeta() |
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.
Can you state explicitly why you were not able to rely on json.Marshal and we have to call this custom serializer? You may be correct, I just want to make sure I'm following
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.
The serializeSpanLinksInMeta
func does use json.Marshal
; I just extracted the method for easier refactoring in the future. We could remove the serializeSpanLinksInMeta()
function and put the logic directly in Finish()
, wdyt?
if len(s.SpanLinks) == 0 { | ||
return | ||
} | ||
spanLinkBytes, err := json.Marshal(s.SpanLinks) |
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.
You could always add a benchmark for that
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.
LGTM. Just make sure to:
- update the PR title to contain the package you've changed, ddtrace/tracer. See https://github.com/DataDog/dd-trace-go/blob/main/CONTRIBUTING.md#contributing
- update the PR description to reflect your new method name,
AddSpanLink
(instead ofAddSpanLinks
😉 )
What does this PR do?
AddSpanLinks
methodSpan[span_links]
. This PR serializes span links in the span meta, underSpan[meta][_dd.span_links]
.span_links.msgp.go
previously results in errors.omitempty
tag from the all fields in theSpanLink
struct.Motivation
These improvements and bug fix are prerequisites for a new feature I'm working on called 'span pointers', and they will be generally useful to other people in the future. Span pointers will be implemented in a future PR, but I did a similar PR in Java.
Implements the
AddSpanLinks
method. Although it's only used once right now, I will be using this in my future 'span pointers' PR.Span links should also be serialized in
Meta[_dd.span_links]
. See this article. This aligns span links logic with other tracers, and some logic in the agent/frontend expect links to be under the meta.Regenerating
span_links.msgp.go
right now results in errors (due to recent additions to theddtrace.go
file), so I moved the span links struct to a separate file to resolve this.(Bug fix) Removes the
omitempty
from all fields in theSpanLink
struct. Even though these fields are optional, they should still have values of 0 or empty string when serialized by msgp. This is because libdatadog requires these fields to exist when deserializing the span links. The serverless agent uses libdatadog, and this is causing an error and causing any span with span links to be dropped by the serverless agent. This is how span links are serialized in all other tracers, so it's best to just modify dd-trace-go to align with them.Testing
Added unit tests.
Manual testing shows that the links are serialized correctly in the meta.
Manual testing also showed that spans with span links are not dropped anymore by Bottlecap, the serverless agent. The S3 request span is now visible, but was dropped previously.
Reviewer's Checklist
v2-dev
branch and reviewed by @DataDog/apm-go.Unsure? Have a question? Request a review!