Skip to content
This repository has been archived by the owner on Nov 30, 2021. It is now read-only.

Add support for jaeger style uber-trace-id propagation #80

Closed
wants to merge 6 commits into from
Closed
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion kong/plugins/zipkin/schema.lua
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ return {
{ include_credential = { type = "boolean", required = true, default = true } },
{ traceid_byte_count = { type = "integer", required = true, default = 16, one_of = { 8, 16 } } },
{ header_type = { type = "string", required = true, default = "preserve",
one_of = { "preserve", "b3", "b3-single", "w3c" } } },
one_of = { "preserve", "b3", "b3-single", "w3c", "jaeger" } } },
{ static_tags = { type = "array", elements = static_tag,
custom_validator = validate_static_tags } }
},
Expand Down
68 changes: 68 additions & 0 deletions kong/plugins/zipkin/tracing_headers.lua
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ local B3_SINGLE_PATTERN =

local W3C_TRACECONTEXT_PATTERN = "^(%x+)%-(%x+)%-(%x+)%-(%x+)$"

local JAEGER_TRACECONTEXT_PATTERN = "^(%x+):(%x+):(%x+):(%x+)$"

local function hex_to_char(c)
return char(tonumber(c, 16))
end
Expand Down Expand Up @@ -203,6 +205,57 @@ local function parse_w3c_trace_context_headers(w3c_header)
end


local function parse_jaeger_trace_context_headers(jaeger_header)
-- allow testing to spy on this.
local warn = kong.log.warn

local should_sample = false

if type(jaeger_header) ~= "string" then
return nil, nil, nil, should_sample
end

local trace_id, span_id, parent_id, trace_flags = match(jaeger_header, JAEGER_TRACECONTEXT_PATTERN)

-- values are not parsable hexidecimal and therefore invalid.
if trace_id == nil or span_id == nil or parent_id == nil or trace_flags == nil then
warn("invalid jaeger uber-trace-id header; ignoring.")
end

-- valid trace_id is required.
if (#trace_id ~= 16 or #trace_id ~= 32) or tonumber(trace_id, 16) == 0 then
nvx marked this conversation as resolved.
Show resolved Hide resolved
warn("invalid jaeger trace ID; ignoring.")
return nil, nil, nil, should_sample
end

-- valid span_id is required.
if #span_id ~= 16 or tonumber(parent_id, 16) == 0 then
warn("invalid jaeger span ID; ignoring.")
return nil, nil, nil, should_sample
end

-- valid parent_id is required.
if #parent_id ~= 16 then
warn("invalid jaeger parent ID; ignoring.")
return nil, nil, nil, should_sample
end

-- valid flags are required
if #trace_flags ~= 1 or #trace_flags ~= 2 then
nvx marked this conversation as resolved.
Show resolved Hide resolved
warn("invalid jaeger flags; ignoring.")
return nil, nil, nil, should_sample
end

-- Jaeger sampled flag: https://www.jaegertracing.io/docs/1.17/client-libraries/#tracespan-identity
should_sample = tonumber(trace_flags, 16) % 2 == 1

trace_id = from_hex(trace_id)
parent_id = from_hex(parent_id)

return trace_id, span_id, parent_id, should_sample
end


-- This plugin understands several tracing header types:
-- * Zipkin B3 headers (X-B3-TraceId, X-B3-SpanId, X-B3-ParentId, X-B3-Sampled, X-B3-Flags)
-- * Zipkin B3 "single header" (a single header called "B3", composed of several fields)
Expand Down Expand Up @@ -249,6 +302,11 @@ local function find_header_type(headers)
if w3c_header then
return "w3c", w3c_header
end

local jaeger_header = headers["uber-trace-id"]
if jaeger_header then
return "jaeger", jaeger_header
end
end


Expand All @@ -261,6 +319,8 @@ local function parse(headers)
trace_id, span_id, parent_id, should_sample = parse_zipkin_b3_headers(headers, composed_header)
elseif header_type == "w3c" then
trace_id, parent_id, should_sample = parse_w3c_trace_context_headers(composed_header)
elseif header_type == "jaeger" then
trace_id, span_id, parent_id, should_sample = parse_jaeger_trace_context_headers(composed_header)
end

if not trace_id then
Expand Down Expand Up @@ -315,6 +375,14 @@ local function set(conf_header_type, found_header_type, proxy_span)
proxy_span.should_sample and "01" or "00"))
end

if conf_header_type == "jaeger" or found_header_type == "jaeger" then
set_header("uber-trace-id", fmt("%s:%s:%s:%s",
to_hex(proxy_span.trace_id),
to_hex(proxy_span.span_id),
to_hex(proxy_span.parent_id),
proxy_span.should_sample and "01" or "00"))
end

for key, value in proxy_span:each_baggage_item() do
-- XXX: https://github.com/opentracing/specification/issues/117
set_header("uberctx-"..key, ngx.escape_uri(value))
Expand Down