Skip to content

Commit

Permalink
fix(tracing): set parent span correctly (#11786)
Browse files Browse the repository at this point in the history
when the `balancer` instrumentation was enabled, the parent span
was set incorrectly on traces, this fix addresses the problem by
setting the parent span correctly on the root (`kong`) span when
there is an incoming tracing header.

(cherry picked from commit 72580d5)
  • Loading branch information
samugi committed Oct 25, 2023
1 parent 1a012f3 commit 1ecda60
Show file tree
Hide file tree
Showing 4 changed files with 39 additions and 8 deletions.
3 changes: 3 additions & 0 deletions changelog/unreleased/kong/fix-opentelemetry-parent-id.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
message: "**Opentelemetry**: fix an issue that resulted in traces with invalid parent IDs when `balancer` instrumentation was enabled"
type: bugfix
scope: Plugin
8 changes: 5 additions & 3 deletions kong/plugins/opentelemetry/handler.lua
Original file line number Diff line number Diff line change
Expand Up @@ -115,16 +115,18 @@ function OpenTelemetryHandler:access(conf)
-- overwrite trace id
-- as we are in a chain of existing trace
if trace_id then
-- to propagate the correct trace ID we have to set it here
-- before passing this span to propagation.set()
injected_parent_span.trace_id = trace_id
kong.ctx.plugin.trace_id = trace_id
end

-- overwrite parent span's parent_id
-- overwrite root span's parent_id
if span_id then
injected_parent_span.parent_id = span_id
root_span.parent_id = span_id

elseif parent_id then
injected_parent_span.parent_id = parent_id
root_span.parent_id = parent_id
end

propagation_set(conf.header_type, header_type, injected_parent_span, "w3c")
Expand Down
32 changes: 29 additions & 3 deletions spec/03-plugins/37-opentelemetry/03-propagation_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,30 @@ local function assert_has_span(name, spans)
return span
end

local function get_span_by_id(spans, id)
for _, span in ipairs(spans) do
if span.span_id == id then
return span
end
end
end

local function assert_correct_trace_hierarchy(spans, incoming_span_id)
for _, span in ipairs(spans) do
if span.name == "kong" then
-- if there is an incoming span id, it should be the parent of the root span
if incoming_span_id then
assert.equals(incoming_span_id, span.parent_id)
end

else
-- all other spans in this trace should have a local span as parent
assert.not_equals(incoming_span_id, span.parent_id)
assert.is_truthy(get_span_by_id(spans, span.parent_id))
end
end
end

for _, strategy in helpers.each_strategy() do
describe("propagation tests #" .. strategy, function()
local service
Expand Down Expand Up @@ -321,7 +345,7 @@ describe("propagation tests #" .. strategy, function()
end)
end)

for _, instrumentation in ipairs({ "request", "request,balancer" }) do
for _, instrumentation in ipairs({ "request", "request,balancer", "all" }) do
describe("propagation tests with enabled " .. instrumentation .. " instrumentation (issue #11294) #" .. strategy, function()
local service, route
local proxy_client
Expand Down Expand Up @@ -370,12 +394,12 @@ describe("propagation tests with enabled " .. instrumentation .. " instrumentati

it("sets the outgoint parent span's ID correctly", function()
local trace_id = gen_trace_id()
local span_id = gen_span_id()
local incoming_span_id = gen_span_id()
local thread = helpers.tcp_server(TCP_PORT)

local r = proxy_client:get("/", {
headers = {
traceparent = fmt("00-%s-%s-01", trace_id, span_id),
traceparent = fmt("00-%s-%s-01", trace_id, incoming_span_id),
host = "http-route"
},
})
Expand All @@ -398,6 +422,8 @@ describe("propagation tests with enabled " .. instrumentation .. " instrumentati

local json = cjson.decode(body)
assert.matches("00%-" .. trace_id .. "%-" .. parent_span.span_id .. "%-01", json.headers.traceparent)

assert_correct_trace_hierarchy(spans, incoming_span_id)
end)
end)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ function _M:access(conf)
end

if span_id then
injected_parent_span.parent_id = span_id
root_span.parent_id = span_id

elseif parent_id then
injected_parent_span.parent_id = parent_id
root_span.parent_id = parent_id
end

local type = header_type and "preserve" or "w3c"
Expand Down

0 comments on commit 1ecda60

Please sign in to comment.