@@ -222,6 +222,8 @@ module TraceContext = struct
222222
223223 let empty = {traceparent= None ; baggage= None }
224224
225+ let depth_key = " span.depth"
226+
225227 let with_traceparent traceparent ctx = {ctx with traceparent}
226228
227229 let with_baggage baggage ctx = {ctx with baggage}
@@ -230,6 +232,20 @@ module TraceContext = struct
230232
231233 let baggage_of ctx = ctx.baggage
232234
235+ let baggage_depth_of ctx =
236+ Option. bind (baggage_of ctx) (List. assoc_opt depth_key)
237+ |> Option. value ~default: " 1"
238+ |> int_of_string
239+
240+ let update_with_baggage k v ctx =
241+ let new_baggage =
242+ baggage_of ctx
243+ |> Option. value ~default: []
244+ |> List. remove_assoc k
245+ |> List. cons (k, v)
246+ in
247+ with_baggage (Some new_baggage) ctx
248+
233249 let parse input =
234250 let open Astring.String in
235251 let trim_pair (key , value ) = (trim key, trim value) in
@@ -322,22 +338,36 @@ module Span = struct
322338
323339 let start ?(attributes = Attributes. empty)
324340 ?(trace_context : TraceContext.t option ) ~name ~parent ~span_kind () =
325- let trace_id, extra_context =
341+ let trace_id, extra_context, depth =
326342 match parent with
327343 | None ->
328- (Trace_id. make () , TraceContext. empty)
344+ (Trace_id. make () , TraceContext. empty, 1 )
329345 | Some span_parent ->
330- (span_parent.context.trace_id, span_parent.context.trace_context)
346+ ( span_parent.context.trace_id
347+ , span_parent.context.trace_context
348+ , TraceContext. baggage_depth_of span_parent.context.trace_context + 1
349+ )
331350 in
332351 let span_id = Span_id. make () in
352+ let extra_context_with_depth =
353+ TraceContext. (
354+ update_with_baggage depth_key (string_of_int depth) extra_context
355+ )
356+ in
333357 let context : SpanContext.t =
334- {trace_id; span_id; trace_context= extra_context }
358+ {trace_id; span_id; trace_context= extra_context_with_depth }
335359 in
336360 let context =
337- (* If trace_context is provided to the call, override any inherited trace context. *)
338- trace_context
339- |> Option. fold ~none: context
340- ~some: (Fun. flip SpanContext. with_trace_context context)
361+ (* If trace_context is provided to the call, override any inherited trace
362+ context except span.depth which should still be maintained. *)
363+ match trace_context with
364+ | Some tc ->
365+ let tc_with_depth =
366+ TraceContext. (update_with_baggage depth_key (string_of_int depth) tc)
367+ in
368+ SpanContext. with_trace_context tc_with_depth context
369+ | None ->
370+ context
341371 in
342372 (* Using gettimeofday over Mtime as it is better for sharing timestamps between the systems *)
343373 let begin_time = Unix. gettimeofday () in
@@ -473,6 +503,11 @@ module Spans = struct
473503
474504 let set_max_traces x = Atomic. set max_traces x
475505
506+ (* Default is much larger than the largest current traces, so effectively off *)
507+ let max_depth = Atomic. make 100
508+
509+ let set_max_depth x = Atomic. set max_depth x
510+
476511 let finished_spans = Atomic. make ([] , 0 )
477512
478513 let span_hashtbl_is_empty () = TraceMap. is_empty (Atomic. get spans)
@@ -713,12 +748,18 @@ module Tracer = struct
713748 let get_tracer ~name :_ = TracerProvider. get_current ()
714749
715750 let span_of_span_context context name : Span.t =
751+ let tc = SpanContext. context_of_span_context context in
752+ let new_depth = TraceContext. baggage_depth_of tc in
753+ let new_tc =
754+ TraceContext. (update_with_baggage depth_key (string_of_int new_depth) tc)
755+ in
756+ let context = SpanContext. with_trace_context new_tc context in
716757 {
717758 context
718759 ; status= {status_code= Status. Unset ; _description= None }
719760 ; name
720761 ; parent= None
721- ; span_kind= SpanKind. Client (* This will be the span of the client call*)
762+ ; span_kind= SpanKind. Client (* This will be the span of the client call *)
722763 ; begin_time= Unix. gettimeofday ()
723764 ; end_time= None
724765 ; links= []
@@ -730,10 +771,32 @@ module Tracer = struct
730771 ?(span_kind = SpanKind. Internal ) ~name ~parent () :
731772 (Span. t option , exn ) result =
732773 let open TracerProvider in
733- (* Do not start span if the TracerProvider is disabled*)
774+ let parent_depth =
775+ Option. fold ~none: 1
776+ ~some: (fun parent ->
777+ parent.Span. context
778+ |> SpanContext. context_of_span_context
779+ |> TraceContext. baggage_depth_of
780+ )
781+ parent
782+ in
783+ (* Do not start span if the TracerProvider is disabled *)
734784 if not t.enabled then
785+ ok_none (* Do not start span if the max depth has been reached *)
786+ else if parent_depth > = Atomic. get Spans. max_depth then (
787+ let parent_trace_id =
788+ Option. fold ~none: " None"
789+ ~some: (fun p ->
790+ p.Span. context
791+ |> SpanContext. span_id_of_span_context
792+ |> Span_id. to_string
793+ )
794+ parent
795+ in
796+ debug " Max_span_depth limit reached, not creating span %s (parent %s)"
797+ name parent_trace_id ;
735798 ok_none
736- else
799+ ) else
737800 let attributes = Attributes. merge_into t.attributes attributes in
738801 let span =
739802 Span. start ~attributes ?trace_context ~name ~parent ~span_kind ()
@@ -750,16 +813,24 @@ module Tracer = struct
750813 |> Spans. remove_from_spans
751814 |> Option. map (fun existing_span ->
752815 let old_context = Span. get_context existing_span in
816+ let parent_trace_context = Span. get_trace_context parent in
817+ let new_depth =
818+ TraceContext. baggage_depth_of parent_trace_context + 1
819+ in
753820 let new_context : SpanContext.t =
754- let trace_context = span.Span. context.trace_context in
821+ let trace_context =
822+ TraceContext. (
823+ update_with_baggage depth_key (string_of_int new_depth)
824+ span.Span. context.trace_context
825+ )
826+ in
755827 SpanContext. context
756828 (SpanContext. trace_id_of_span_context parent.context)
757829 old_context.span_id
758830 |> SpanContext. with_trace_context trace_context
759831 in
760832 let updated_span = {existing_span with parent= Some parent} in
761833 let updated_span = {updated_span with context= new_context} in
762-
763834 let () = Spans. add_to_spans ~span: updated_span in
764835 updated_span
765836 )
@@ -926,7 +997,15 @@ module Propagator = struct
926997 let trace_context' =
927998 TraceContext. with_traceparent (Some traceparent) trace_context
928999 in
929- let carrier' = P. inject_into trace_context' carrier in
1000+ let new_depth =
1001+ TraceContext. baggage_depth_of trace_context' + 1 |> string_of_int
1002+ in
1003+ let trace_context'' =
1004+ TraceContext. (
1005+ update_with_baggage depth_key new_depth trace_context'
1006+ )
1007+ in
1008+ let carrier' = P. inject_into trace_context'' carrier in
9301009 f carrier'
9311010 | _ ->
9321011 f carrier
0 commit comments