Skip to content

Commit

Permalink
Allow multiple Inst or resource for export
Browse files Browse the repository at this point in the history
* Currently if 2 tracer providers or 2 tracers are exporting, there is a
  first one in batch wins condition for exporting spans
* This change moves encoding the body into its own function, and adds
  unittests for spans from different tracers and from different trace
  providers to ensure resource and il parts of the otlp export are set
  properly
  • Loading branch information
rdooley committed Mar 13, 2024
1 parent 6e44fe8 commit e6711bc
Show file tree
Hide file tree
Showing 2 changed files with 125 additions and 3 deletions.
51 changes: 48 additions & 3 deletions lib/opentelemetry/trace/exporter/otlp.lua
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ local function call_collector(exporter, pb_encoded_body)
return false, res_error or "unknown"
end

function _M.export_spans(self, spans)
function _M.encode_spans(self, spans)
assert(spans[1])

local body = {
Expand All @@ -96,12 +96,57 @@ function _M.export_spans(self, spans)
}
}
}
local tracers = {}
local providers = {}
tracers[spans[1].tracer] = 1
providers[spans[1].tracer.provider] = 1
for _, span in ipairs(spans) do
local rs_idx = providers[span.tracer.provider]
local ils_idx = tracers[span.tracer]
if not rs_idx then
rs_idx = #body.resource_spans + 1
ils_idx = 1
providers[span.tracer.provider] = rs_idx
tracers[span.tracer] = ils_idx
table.insert(
body.resource_spans,
{
resource = {
attributes = span.tracer.provider.resource.attrs,
dropped_attributes_count = 0,
},
instrumentation_library_spans = {
{
instrumentation_library = {
name = span.tracer.il.name,
version = span.tracer.il.version,
},
spans = {}
},
},
})
elseif not ils_idx then
ils_idx = #body.resource_spans[rs_idx].instrumentation_library_spans + 1
tracers[span.tracer] = ils_idx
table.insert(
body.resource_spans[rs_idx].instrumentation_library_spans,
{
instrumentation_library = {
name = span.tracer.il.name,
version = span.tracer.il.version,
},
spans = {}
})
end
table.insert(
body.resource_spans[1].instrumentation_library_spans[1].spans,
body.resource_spans[rs_idx].instrumentation_library_spans[ils_idx].spans,
encoder.for_otlp(span))
end
return call_collector(self, pb.encode(body))
return body
end

function _M.export_spans(self, spans)
return call_collector(self, pb.encode(self:encode_spans(spans)))
end

function _M.shutdown(self)
Expand Down
77 changes: 77 additions & 0 deletions spec/trace/exporter/otlp_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,85 @@ local exporter = require "opentelemetry.trace.exporter.otlp"
local client = require "opentelemetry.trace.exporter.http_client"
local context = require "opentelemetry.context"
local tp = Global.get_tracer_provider()
local tracer_provider_new = require("opentelemetry.trace.tracer_provider").new
local tracer = tp:tracer("test")

describe("encode_spans", function()
it("one resource span and one ils for one span", function()
local span
local ctx = context.new()
ctx, span = tracer:start(ctx, "test span")
span:finish()
local cb = exporter.new(nil)
local encoded = cb:encode_spans({span, other_spans})
-- One resource, one il, one span
assert(#encoded.resource_spans == 1)
local resource = encoded.resource_spans[1]
assert(#resource.instrumentation_library_spans == 1)
assert(#resource.instrumentation_library_spans[1].spans == 1)
end)

it("one resource span and one ils for multiple span same tracer", function()
local span
local ctx = context.new()
local spans = {}
for i=10,1,-1 do
ctx, span = tracer:start(ctx, "test span" .. i)
span:finish()
table.insert(spans, span)
end
local cb = exporter.new(nil)
local encoded = cb:encode_spans(spans)
-- One resource, one il, 10 spans
assert(#encoded.resource_spans == 1)
local resource = encoded.resource_spans[1]
assert(#resource.instrumentation_library_spans == 1)
assert(#resource.instrumentation_library_spans[1].spans == 10)
end)

it("one resource span and two ils for spans from distinct tracers", function()
local span
local ctx = context.new()
local spans = {}
ctx, span = tracer:start(ctx, "test span")
span:finish()
table.insert(spans, span)
local other_tracer = tp:tracer("exam")
ctx, other_span = other_tracer:start(ctx, "exam span")
table.insert(spans, other_span)
local cb = exporter.new(nil)
local encoded = cb:encode_spans(spans)
-- One resource, two il, 1 span each
assert(#encoded.resource_spans == 1)
local resource = encoded.resource_spans[1]
assert(#resource.instrumentation_library_spans == 2)
assert(#resource.instrumentation_library_spans[1].spans == 1)
assert(#resource.instrumentation_library_spans[2].spans == 1)
end)
it("distinct trace providers provide distinct resources", function()
local span
local ctx = context.new()
local spans = {}
ctx, span = tracer:start(ctx, "test span")
span:finish()
table.insert(spans, span)
local op = tracer_provider_new(nil, nil)
local other_tracer = op:tracer("exam")
ctx, other_span = other_tracer:start(ctx, "exam span")
table.insert(spans, other_span)
local cb = exporter.new(nil)
local encoded = cb:encode_spans(spans)
-- two resources with one il, 1 span each
assert(#encoded.resource_spans == 2)
local resource = encoded.resource_spans[1]
assert(#resource.instrumentation_library_spans == 1)
assert(#resource.instrumentation_library_spans[1].spans == 1)
resource = encoded.resource_spans[2]
assert(#resource.instrumentation_library_spans == 1)
assert(#resource.instrumentation_library_spans[1].spans == 1)
end)
end)

describe("export_spans", function()
it("invokes do_request when there are no failures", function()
local span
Expand Down

0 comments on commit e6711bc

Please sign in to comment.