@@ -48,6 +48,7 @@ local pairs = pairs
4848local ipairs = ipairs
4949local unpack = unpack
5050local string_format = string.format
51+ local update_time = ngx .update_time
5152
5253local lrucache = core .lrucache .new ({
5354 type = ' plugin' , count = 128 , ttl = 24 * 60 * 60 ,
@@ -327,10 +328,17 @@ function _M.rewrite(conf, api_ctx)
327328
328329 local attributes = {
329330 attr .string (" net.host.name" , vars .host ),
331+ -- deprecated attributes
330332 attr .string (" http.method" , vars .method ),
331333 attr .string (" http.scheme" , vars .scheme ),
332334 attr .string (" http.target" , vars .request_uri ),
333335 attr .string (" http.user_agent" , vars .http_user_agent ),
336+
337+ -- new attributes
338+ attr .string (" http.request.method" , vars .method ),
339+ attr .string (" url.scheme" , vars .scheme ),
340+ attr .string (" uri.path" , vars .uri ),
341+ attr .string (" user_agent.original" , vars .http_user_agent ),
334342 }
335343
336344 if api_ctx .curr_req_matched then
@@ -376,48 +384,96 @@ function _M.rewrite(conf, api_ctx)
376384 ngx_var .opentelemetry_span_id = span_context .span_id
377385 end
378386
387+ if not ctx :span ():is_recording () and ngx .ctx .tracing then
388+ ngx .ctx .tracing .skip = true
389+ end
390+
379391 api_ctx .otel_context_token = ctx :attach ()
380392
381393 -- inject trace context into the headers of upstream HTTP request
382394 trace_context_propagator :inject (ctx , ngx .req )
383395end
384396
385397
386- function _M .delayed_body_filter (conf , api_ctx )
387- if api_ctx .otel_context_token and ngx .arg [2 ] then
388- local ctx = context :current ()
389- ctx :detach (api_ctx .otel_context_token )
390- api_ctx .otel_context_token = nil
398+ local function create_child_span (tracer , parent_span_ctx , spans , span )
399+ if not span or span .finished then
400+ return
401+ end
402+ span .finished = true
403+ local new_span_ctx , new_span = tracer :start (parent_span_ctx , span .name ,
404+ {
405+ kind = span .kind ,
406+ attributes = span .attributes ,
407+ })
408+ new_span .start_time = span .start_time
409+
410+ for _ , idx in ipairs (span .child_ids or {}) do
411+ create_child_span (tracer , new_span_ctx , spans , spans [idx ])
412+ end
413+ if span .status then
414+ new_span :set_status (span .status .code , span .status .message )
415+ end
416+ new_span :finish (span .end_time )
417+ end
391418
392- -- get span from current context
393- local span = ctx :span ()
394- local upstream_status = core .response .get_upstream_status (api_ctx )
395- if upstream_status and upstream_status >= 500 then
396- span :set_status (span_status .ERROR ,
397- " upstream response status: " .. upstream_status )
398- end
399419
400- span :set_attributes (attr .int (" http.status_code" , upstream_status ))
420+ local function inject_core_spans (root_span_ctx , api_ctx , conf )
421+ local tracing = api_ctx .ngx_ctx .tracing
422+ if not tracing then
423+ return
424+ end
401425
402- span :finish ()
426+ local span = root_span_ctx :span ()
427+
428+ local metadata = plugin .plugin_metadata (plugin_name )
429+ local plugin_info = metadata .value
430+ if span and not span :is_recording () then
431+ return
432+ end
433+ local inject_conf = {
434+ sampler = {
435+ name = " always_on" ,
436+ options = conf .sampler .options
437+ },
438+ additional_attributes = conf .additional_attributes ,
439+ additional_header_prefix_attributes = conf .additional_header_prefix_attributes
440+ }
441+ local tracer , err = core .lrucache .plugin_ctx (lrucache , api_ctx , nil ,
442+ create_tracer_obj , inject_conf , plugin_info )
443+ if not tracer then
444+ core .log .error (" failed to fetch tracer object: " , err )
445+ return
446+ end
447+
448+ if # tracing .spans == 0 then
449+ return
450+ end
451+ span .start_time = tracing .spans [1 ].start_time
452+ local root_span = tracing .root_span
453+ local spans = tracing .spans
454+ for _ , idx in ipairs (root_span .child_ids or {}) do
455+ create_child_span (tracer , root_span_ctx , spans , spans [idx ])
403456 end
404457end
405458
406459
407- -- body_filter maybe not called because of empty http body response
408- -- so we need to check if the span has finished in log phase
409460function _M .log (conf , api_ctx )
410461 if api_ctx .otel_context_token then
411462 -- ctx:detach() is not necessary, because of ctx is stored in ngx.ctx
412463 local upstream_status = core .response .get_upstream_status (api_ctx )
413464
414465 -- get span from current context
415- local span = context :current ():span ()
466+ local ctx = context :current ()
467+ local span = ctx :span ()
416468 if upstream_status and upstream_status >= 500 then
417469 span :set_status (span_status .ERROR ,
418470 " upstream response status: " .. upstream_status )
419471 end
420472
473+ inject_core_spans (ctx , api_ctx , conf )
474+ span :set_attributes (attr .int (" http.status_code" , upstream_status ),
475+ attr .int (" http.response.status_code" , upstream_status ))
476+ update_time ()
421477 span :finish ()
422478 end
423479end
0 commit comments