Skip to content

Commit 5e3cf88

Browse files
Merge pull request #422 from solarwinds/NH-78538
Add missing SW key propagation
2 parents cadbcd6 + c2a0d7c commit 5e3cf88

File tree

3 files changed

+114
-0
lines changed

3 files changed

+114
-0
lines changed

.yarn/versions/d01421ba.yml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
releases:
2+
solarwinds-apm: minor
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
/*
2+
Copyright 2023-2024 SolarWinds Worldwide, LLC.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import {
18+
type Context,
19+
createTraceState,
20+
type SpanContext,
21+
type TextMapSetter,
22+
trace,
23+
} from "@opentelemetry/api"
24+
import { W3CTraceContextPropagator } from "@opentelemetry/core"
25+
26+
const TRACE_STATE_KEY = "tracestate"
27+
28+
export function swValue(context: SpanContext): string {
29+
return `${context.spanId}-${context.traceFlags.toString(16).padStart(2, "0")}`
30+
}
31+
32+
export class TraceContextPropagator extends W3CTraceContextPropagator {
33+
override inject(
34+
context: Context,
35+
carrier: unknown,
36+
setter: TextMapSetter,
37+
): void {
38+
super.inject(context, carrier, {
39+
set: (carrier, key, value) => {
40+
if (key !== TRACE_STATE_KEY) {
41+
setter.set(carrier, key, value)
42+
}
43+
},
44+
})
45+
46+
const span = trace.getSpanContext(context)
47+
if (span) {
48+
const traceState = (span.traceState ?? createTraceState())
49+
.set("sw", swValue(span))
50+
.serialize()
51+
setter.set(carrier, TRACE_STATE_KEY, traceState)
52+
}
53+
}
54+
}
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
/*
2+
Copyright 2023-2024 SolarWinds Worldwide, LLC.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
import {
18+
createTraceState,
19+
defaultTextMapSetter,
20+
ROOT_CONTEXT,
21+
trace,
22+
TraceFlags,
23+
} from "@opentelemetry/api"
24+
import { describe, expect, it } from "@solarwinds-apm/test"
25+
26+
import { TraceContextPropagator } from "../../src/propagation/trace-context.js"
27+
28+
describe("TraceContextPropagator", () => {
29+
const propagator = new TraceContextPropagator()
30+
31+
it("inserts sw key in empty trace state", () => {
32+
const headers: Partial<Record<string, string>> = {}
33+
const context = trace.setSpanContext(ROOT_CONTEXT, {
34+
spanId: "0123456789abcdef",
35+
traceId: "0123456789abcdef0123456789abcdef",
36+
traceFlags: TraceFlags.SAMPLED,
37+
})
38+
39+
propagator.inject(context, headers, defaultTextMapSetter)
40+
expect(headers.tracestate).to.equal("sw=0123456789abcdef-01")
41+
})
42+
43+
it("inserts sw key in existing trace state", () => {
44+
const headers: Partial<Record<string, string>> = {}
45+
const context = trace.setSpanContext(ROOT_CONTEXT, {
46+
spanId: "0123456789abcdef",
47+
traceId: "0123456789abcdef0123456789abcdef",
48+
traceFlags: TraceFlags.SAMPLED,
49+
traceState: createTraceState().set("foo", "bar"),
50+
})
51+
52+
propagator.inject(context, headers, defaultTextMapSetter)
53+
expect(headers.tracestate).to.be.oneOf([
54+
"sw=0123456789abcdef-01,foo=bar",
55+
"foo=bar,sw=0123456789abcdef-01",
56+
])
57+
})
58+
})

0 commit comments

Comments
 (0)