tracestate: Allow duplicate keys but rewrite them#1183
tracestate: Allow duplicate keys but rewrite them#1183marclop merged 4 commits intoelastic:masterfrom marclop:b/fix-tracestate-duplicate-key-handling
Conversation
Changes the validation logic to allow duplicate keys to be present in tracestate entries, modifying the `NewTraceState` constructor to rewrite the duplicate keys according to the new W3C spec. Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
💚 Build Succeeded
Expand to view the summary
Build stats
Test stats 🧪
🤖 GitHub commentsTo re-run your PR in the CI, just comment with:
|
tracecontext.go
Outdated
| var out TraceState | ||
| var last *TraceStateEntry | ||
| var modified []TraceStateEntry | ||
| recorded := make(map[string]uint8) |
There was a problem hiding this comment.
This could also be named seen or observed, I think it works either way but I'm happy to rename it.
There was a problem hiding this comment.
doesn't make a big difference to me, happy with whichever color you choose for the bikeshed :)
stuartnelson3
left a comment
There was a problem hiding this comment.
couple small comments, but nothing that requires a re-review
tracecontext.go
Outdated
| var out TraceState | ||
| var last *TraceStateEntry | ||
| var modified []TraceStateEntry | ||
| recorded := make(map[string]uint8) |
There was a problem hiding this comment.
doesn't make a big difference to me, happy with whichever color you choose for the bikeshed :)
tracecontext.go
Outdated
| } | ||
| // After we've ranged over the whole entry slice, any duplicates present | ||
| // must be written first in a last to first order, thus we range the slice | ||
| // backwards. |
There was a problem hiding this comment.
Ah hah, the order is why modified is a slice and not a map?
tracecontext.go
Outdated
| if count > 1 { | ||
| for i, m := range modified { | ||
| if m.Key == e.Key { | ||
| modified[i] = e |
There was a problem hiding this comment.
Once we've found a matching key, we could continue, right? Since we're only wanting to record the latest entry e for a specific key e.Key?
There was a problem hiding this comment.
yeah we could if we kept the implementation as is, I'm going to simplify it and change it to only act on the 'es' vendor key which is the only one we care about, it'll also eliminate allocations :)
tracecontext.go
Outdated
| recorded[e.Key]++ | ||
| } | ||
| // After we've ranged over the whole entry slice, any duplicates present | ||
| // must be written first in a last to first order, thus we range the slice |
There was a problem hiding this comment.
nit: must be written in a last to first order, I think it makes the comment a bit simpler since we're already saying last and first
Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
tracecontext.go
Outdated
| var out TraceState | ||
| var last *TraceStateEntry | ||
| var recorded uint8 | ||
| // Range over the entries and find duplicate `es` vendor keys. When 'es' |
There was a problem hiding this comment.
I'm finding this method quite difficult to follow now. Would this alternative work?
var haveElastic bool
var last *TraceState
for _, e := range entries {
if e.Key == elasticTracestateVendorKey {
if haveElastic {
// Discard duplicate "es" entries; keep the last entry's value.
out.head.value = e.value
continue
}
haveElastic = true
e.next = last
last = nil // cause elastic to be moved to head
}
e := e // copy
if last == nil {
out.head = &e
} else {
last.next = &e
}
last = &e
}
if haveElastic {
out.parseElasticTracestateError = out.parseElasticTracestate(out.head)
}There was a problem hiding this comment.
BTW we didn't previously move the elastic entry to the head because IIANM that's only expected when mutating tracestate.
There was a problem hiding this comment.
I mostly kept the suggestion intact, but had to make some changes in 9270b6a to not lose any entries that were found previous to the es key.
Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
Changes the validation logic to allow duplicate keys to be present in tracestate entries, modifying the `NewTraceState` constructor to rewrite the duplicate `es` keys according to the new W3C spec, but leaving 3rd party duplicates untouched. Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com>
* CI: use apm-integration-testing/7.x for v1 Use apm-integration-testing 7.x branch for testing apm-agent-go v1. We'll update apm-integration-testing's main branch to test v2. * deps: Pin `olivere/elastic` dependency (#1178) To version `v7.0.29` for pre module Go versions. Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com> * tracestate: Allow duplicate keys but rewrite them (#1183) Changes the validation logic to allow duplicate keys to be present in tracestate entries, modifying the `NewTraceState` constructor to rewrite the duplicate `es` keys according to the new W3C spec, but leaving 3rd party duplicates untouched. Signed-off-by: Marc Lopez Rubio <marc5.12@outlook.com> Co-authored-by: Marc Lopez Rubio <marc5.12@outlook.com>
|
Verified using go.elastic.co/apm/v2 v2.0.0-20220209134054-640a916049c9 (current main), along with apmhttp/v2. To get apmhttp/v2 to work, I had to add a replace stanza:
I compared the v2 behaviour against the latest v1 agent.
|
Description
Changes the validation logic to allow duplicate keys to be present in
tracestate entries, modifying the
NewTraceStateconstructor to rewritethe duplicate
eskeys according to the new W3C spec, but leaving 3rdparty duplicates untouched.
https://w3c.github.io/trace-context/#combined-header-value
Related issues
Closes #1182