-
Notifications
You must be signed in to change notification settings - Fork 4.7k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
152 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
-- Module for parsing Zipkin span tags introduced by requests with a special header | ||
-- by default the header is called Zipkin-Tags | ||
-- | ||
-- For example, the following http request header: | ||
-- | ||
-- Zipkin-Tags: foo=bar; baz=qux | ||
-- | ||
-- Will add two tags to the request span in Zipkin | ||
|
||
|
||
local split = require "kong.tools.utils".split | ||
|
||
local match = string.match | ||
|
||
local request_tags = {} | ||
|
||
|
||
-- note that and errors is an output value; we do this instead of | ||
-- a return in order to be more efficient (allocate less tables) | ||
local function parse_tags(tags_string, dest, errors) | ||
local items = split(tags_string, ";") | ||
local item | ||
|
||
for i = 1, #items do | ||
item = items[i] | ||
if item ~= "" then | ||
local name, value = match(item, "^%s*(%S+)%s*=%s*(.*%S)%s*$") | ||
if name then | ||
dest[name] = value | ||
|
||
else | ||
errors[#errors + 1] = item | ||
end | ||
end | ||
end | ||
end | ||
|
||
|
||
-- parses req_headers into extra zipkin tags | ||
-- returns tags, err | ||
-- note that both tags and err can be non-nil when the request could parse some tags but rejects others | ||
-- tag can be nil when tags_header is nil. That is not an error (err will be empty) | ||
function request_tags.parse(tags_header) | ||
if not tags_header then | ||
return nil, nil | ||
end | ||
|
||
local t = type(tags_header) | ||
local tags, errors = {}, {} | ||
|
||
-- "normal" requests are strings | ||
if t == "string" then | ||
parse_tags(tags_header, tags, errors) | ||
|
||
-- requests where the tags_header_name header is used more than once get an array | ||
-- | ||
-- example - a request with the headers: | ||
-- zipkin-tags: foo=bar | ||
-- zipkin-tags: baz=qux | ||
-- | ||
-- will get such array. We have to transform that into { foo=bar, baz=qux } | ||
elseif t == "table" then | ||
for i = 1, #tags_header do | ||
parse_tags(tags_header[i], tags, errors) | ||
end | ||
|
||
else | ||
return nil, | ||
string.format("unexpected tags_header type: %s (%s)", | ||
tostring(tags_header), t) | ||
end | ||
|
||
if next(errors) then | ||
errors = "Could not parse the following Zipkin tags: " .. table.concat(errors, ", ") | ||
else | ||
errors = nil | ||
end | ||
|
||
return tags, errors | ||
end | ||
|
||
return request_tags |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,46 @@ | ||
local parse = require("kong.plugins.zipkin.request_tags").parse | ||
|
||
describe("request_tags", function() | ||
describe("parse", function() | ||
it("parses simple case, swallowing spaces", function() | ||
assert.same({ foo = "bar" }, parse("foo=bar")) | ||
assert.same({ foo = "bar" }, parse("foo= bar")) | ||
assert.same({ foo = "bar" }, parse("foo =bar")) | ||
assert.same({ foo = "bar" }, parse("foo = bar")) | ||
assert.same({ foo = "bar" }, parse(" foo = bar")) | ||
assert.same({ foo = "bar" }, parse("foo = bar ")) | ||
assert.same({ foo = "bar" }, parse(" foo = bar ")) | ||
end) | ||
it("rejects invalid tags, keeping valid ones", function() | ||
local tags, err = parse("foobar;foo=;=bar;keep=true;=") | ||
assert.same(tags, {keep = "true"}) | ||
assert.equals("Could not parse the following Zipkin tags: foobar, foo=, =bar, =", err) | ||
end) | ||
it("allows spaces on values, but not on keys", function() | ||
assert.same({ foo = "bar baz" }, parse("foo=bar baz")) | ||
local tags, err = parse("foo bar=baz") | ||
assert.same(tags, {}) | ||
assert.equals("Could not parse the following Zipkin tags: foo bar=baz", err) | ||
end) | ||
it("parses multiple tags separated by semicolons, swallowing spaces", function() | ||
assert.same({ foo = "bar", baz = "qux" }, parse("foo=bar;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse("foo =bar;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse("foo= bar;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse(" foo=bar ;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse("foo = bar ;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse(" foo = bar ;baz=qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse(" foo = bar ;baz =qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse(" foo = bar ;baz = qux")) | ||
assert.same({ foo = "bar", baz = "qux" }, parse(" foo = bar ;baz = qux")) | ||
end) | ||
it("swallows empty tags between semicolons silently", function() | ||
local tags, err = parse(";;foo=bar;;;;baz=qux;;") | ||
assert.same({ foo = "bar", baz = "qux" }, tags) | ||
assert.is_nil(err) | ||
end) | ||
it("parses multiple tags separated by semicolons, in an array", function() | ||
assert.same({ foo = "bar", baz = "qux", quux = "quuz" }, | ||
parse({"foo=bar;baz=qux", "quux=quuz"})) | ||
end) | ||
end) | ||
end) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters