Skip to content

Commit cc66500

Browse files
authored
Merge pull request #5888 from GabrielBuica/private/dbuica/CP-50444
CP-50444: Instrument http svr with dt
2 parents a41c3fe + 0fd7d6b commit cc66500

File tree

12 files changed

+153
-19
lines changed

12 files changed

+153
-19
lines changed

dune

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
(ocamlopt_flags (:standard -g -p -w -39))
44
(flags (:standard -w -39))
55
)
6-
(dev (flags (:standard -g -w -39 -warn-error -69)))
6+
(dev (flags (:standard -g -w -39)))
77
(release
88
(flags (:standard -w -39-6@5))
99
(env-vars (ALCOTEST_COMPACT 1))

dune-project

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,7 @@
205205
(xapi-rrd (= :version))
206206
(xapi-stdext-threads (= :version))
207207
(xapi-stdext-unix (= :version))
208+
xapi-tracing
208209
)
209210
)
210211

ocaml/libs/http-lib/dune

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
ipaddr
4646
polly
4747
threads.posix
48+
tracing
4849
uri
4950
xapi-log
5051
xapi-stdext-pervasives

ocaml/libs/http-lib/http.ml

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,6 +694,29 @@ module Request = struct
694694
let headers, body = to_headers_and_body x in
695695
let frame_header = if x.frame then make_frame_header headers else "" in
696696
frame_header ^ headers ^ body
697+
698+
let traceparent_of req =
699+
let open Tracing in
700+
let ( let* ) = Option.bind in
701+
let* traceparent = req.traceparent in
702+
let* span_context = SpanContext.of_traceparent traceparent in
703+
let span = Tracer.span_of_span_context span_context req.uri in
704+
Some span
705+
706+
let with_tracing ?attributes ~name req f =
707+
let open Tracing in
708+
let parent = traceparent_of req in
709+
with_child_trace ?attributes parent ~name (fun (span : Span.t option) ->
710+
match span with
711+
| Some span ->
712+
let traceparent =
713+
Some (span |> Span.get_context |> SpanContext.to_traceparent)
714+
in
715+
let req = {req with traceparent} in
716+
f req
717+
| None ->
718+
f req
719+
)
697720
end
698721

699722
module Response = struct

ocaml/libs/http-lib/http.mli

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -128,6 +128,11 @@ module Request : sig
128128

129129
val to_wire_string : t -> string
130130
(** [to_wire_string t] returns a string which could be sent to a server *)
131+
132+
val traceparent_of : t -> Tracing.Span.t option
133+
134+
val with_tracing :
135+
?attributes:(string * string) list -> name:string -> t -> (t -> 'a) -> 'a
131136
end
132137

133138
(** Parsed form of the HTTP response *)

ocaml/libs/http-lib/http_svr.ml

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,8 @@ module E = Debug.Make (struct let name = "http_internal_errors" end)
4343

4444
let ( let* ) = Option.bind
4545

46+
let ( let@ ) f x = f x
47+
4648
type uri_path = string
4749

4850
module Stats = struct
@@ -101,6 +103,7 @@ let response_of_request req hdrs =
101103

102104
let response_fct req ?(hdrs = []) s (response_length : int64)
103105
(write_response_to_fd_fn : Unix.file_descr -> unit) =
106+
let@ req = Http.Request.with_tracing ~name:__FUNCTION__ req in
104107
let res =
105108
{
106109
(response_of_request req hdrs) with
@@ -441,9 +444,28 @@ let request_of_bio_exn ~proxy_seen ~read_timeout ~total_timeout ~max_length bio
441444
already sent back a suitable error code and response to the client. *)
442445
let request_of_bio ?proxy_seen ~read_timeout ~total_timeout ~max_length ic =
443446
try
447+
let tracer = Tracing.Tracer.get_tracer ~name:"http_tracer" in
448+
let loop_span =
449+
match Tracing.Tracer.start ~tracer ~name:__FUNCTION__ ~parent:None () with
450+
| Ok span ->
451+
span
452+
| Error _ ->
453+
None
454+
in
444455
let r, proxy =
445456
request_of_bio_exn ~proxy_seen ~read_timeout ~total_timeout ~max_length ic
446457
in
458+
let parent_span = Http.Request.traceparent_of r in
459+
let loop_span =
460+
Option.fold ~none:None
461+
~some:(fun span ->
462+
Tracing.Tracer.update_span_with_parent span parent_span
463+
)
464+
loop_span
465+
in
466+
let _ : (Tracing.Span.t option, exn) result =
467+
Tracing.Tracer.finish loop_span
468+
in
447469
(Some r, proxy)
448470
with e ->
449471
D.warn "%s (%s)" (Printexc.to_string e) __LOC__ ;
@@ -486,6 +508,8 @@ let request_of_bio ?proxy_seen ~read_timeout ~total_timeout ~max_length ic =
486508
(None, None)
487509

488510
let handle_one (x : 'a Server.t) ss context req =
511+
let@ req = Http.Request.with_tracing ~name:__FUNCTION__ req in
512+
let span = Http.Request.traceparent_of req in
489513
let ic = Buf_io.of_fd ss in
490514
let finished = ref false in
491515
try
@@ -499,6 +523,7 @@ let handle_one (x : 'a Server.t) ss context req =
499523
Option.value ~default:empty
500524
(Radix_tree.longest_prefix req.Request.uri method_map)
501525
in
526+
let@ _ = Tracing.with_child_trace span ~name:"handler" in
502527
( match te.TE.handler with
503528
| BufIO handlerfn ->
504529
handlerfn req ic context
@@ -561,6 +586,7 @@ let handle_connection ~header_read_timeout ~header_total_timeout
561586
request_of_bio ?proxy_seen ~read_timeout ~total_timeout
562587
~max_length:max_header_length ic
563588
in
589+
564590
(* 2. now we attempt to process the request *)
565591
let finished =
566592
Option.fold ~none:true

ocaml/libs/tracing/tracing.ml

Lines changed: 49 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -127,7 +127,7 @@ let ok_none = Ok None
127127
module Status = struct
128128
type status_code = Unset | Ok | Error [@@deriving rpcty]
129129

130-
type t = {status_code: status_code; description: string option}
130+
type t = {status_code: status_code; _description: string option}
131131
end
132132

133133
module Attributes = struct
@@ -151,6 +151,8 @@ end
151151
module SpanContext = struct
152152
type t = {trace_id: string; span_id: string} [@@deriving rpcty]
153153

154+
let context trace_id span_id = {trace_id; span_id}
155+
154156
let to_traceparent t = Printf.sprintf "00-%s-%s-01" t.trace_id t.span_id
155157

156158
let of_traceparent traceparent =
@@ -167,7 +169,7 @@ module SpanContext = struct
167169
end
168170

169171
module SpanLink = struct
170-
type t = {context: SpanContext.t; attributes: (string * string) list}
172+
type t = {_context: SpanContext.t; _attributes: (string * string) list}
171173
end
172174

173175
module Span = struct
@@ -208,7 +210,7 @@ module Span = struct
208210
(* Using gettimeofday over Mtime as it is better for sharing timestamps between the systems *)
209211
let begin_time = Unix.gettimeofday () in
210212
let end_time = None in
211-
let status : Status.t = {status_code= Status.Unset; description= None} in
213+
let status : Status.t = {status_code= Status.Unset; _description= None} in
212214
let links = [] in
213215
let events = [] in
214216
{
@@ -250,7 +252,7 @@ module Span = struct
250252
let set_span_kind span span_kind = {span with span_kind}
251253

252254
let add_link span context attributes =
253-
let link : SpanLink.t = {context; attributes} in
255+
let link : SpanLink.t = {_context= context; _attributes= attributes} in
254256
{span with links= link :: span.links}
255257

256258
let add_event span name attributes =
@@ -263,7 +265,7 @@ module Span = struct
263265
| exn, stacktrace -> (
264266
let msg = Printexc.to_string exn in
265267
let exn_type = Printexc.exn_slot_name exn in
266-
let description =
268+
let _description =
267269
Some
268270
(Printf.sprintf "Error: %s Type: %s Backtrace: %s" msg exn_type
269271
stacktrace
@@ -286,17 +288,17 @@ module Span = struct
286288
span.attributes
287289
(Attributes.of_list exn_attributes)
288290
in
289-
{span with status= {status_code; description}; attributes}
291+
{span with status= {status_code; _description}; attributes}
290292
| _ ->
291293
span
292294
)
293295

294296
let set_ok span =
295-
let description = None in
297+
let _description = None in
296298
let status_code = Status.Ok in
297299
match span.status.status_code with
298300
| Unset ->
299-
{span with status= {status_code; description}}
301+
{span with status= {status_code; _description}}
300302
| _ ->
301303
span
302304
end
@@ -311,7 +313,7 @@ module Spans = struct
311313
Hashtbl.length spans
312314
)
313315

314-
let max_spans = Atomic.make 1000
316+
let max_spans = Atomic.make 2500
315317

316318
let set_max_spans x = Atomic.set max_spans x
317319

@@ -519,8 +521,8 @@ module TracerProvider = struct
519521
get_tracer_providers_unlocked
520522

521523
let set ?enabled ?attributes ?endpoints ~uuid () =
522-
let update_provider (provider : t) ?(enabled = provider.enabled) attributes
523-
endpoints =
524+
let update_provider (provider : t) enabled attributes endpoints =
525+
let enabled = Option.value ~default:provider.enabled enabled in
524526
let attributes : string Attributes.t =
525527
Option.fold ~none:provider.attributes ~some:Attributes.of_list
526528
attributes
@@ -537,7 +539,7 @@ module TracerProvider = struct
537539
let provider =
538540
match Hashtbl.find_opt tracer_providers uuid with
539541
| Some (provider : t) ->
540-
update_provider provider ?enabled attributes endpoints
542+
update_provider provider enabled attributes endpoints
541543
| None ->
542544
fail "The TracerProvider : %s does not exist" uuid
543545
in
@@ -564,9 +566,9 @@ module TracerProvider = struct
564566
end
565567

566568
module Tracer = struct
567-
type t = {name: string; provider: TracerProvider.t}
569+
type t = {_name: string; provider: TracerProvider.t}
568570

569-
let create ~name ~provider = {name; provider}
571+
let create ~name ~provider = {_name= name; provider}
570572

571573
let no_op =
572574
let provider : TracerProvider.t =
@@ -577,7 +579,7 @@ module Tracer = struct
577579
; enabled= false
578580
}
579581
in
580-
{name= ""; provider}
582+
{_name= ""; provider}
581583

582584
let get_tracer ~name =
583585
if Atomic.get observe then (
@@ -598,7 +600,7 @@ module Tracer = struct
598600
let span_of_span_context context name : Span.t =
599601
{
600602
context
601-
; status= {status_code= Status.Unset; description= None}
603+
; status= {status_code= Status.Unset; _description= None}
602604
; name
603605
; parent= None
604606
; span_kind= SpanKind.Client (* This will be the span of the client call*)
@@ -624,6 +626,30 @@ module Tracer = struct
624626
let span = Span.start ~attributes ~name ~parent ~span_kind () in
625627
Spans.add_to_spans ~span ; Ok (Some span)
626628

629+
let update_span_with_parent span (parent : Span.t option) =
630+
if Atomic.get observe then
631+
match parent with
632+
| None ->
633+
Some span
634+
| Some parent ->
635+
span
636+
|> Spans.remove_from_spans
637+
|> Option.map (fun existing_span ->
638+
let old_context = Span.get_context existing_span in
639+
let new_context : SpanContext.t =
640+
SpanContext.context
641+
(SpanContext.trace_id_of_span_context parent.context)
642+
old_context.span_id
643+
in
644+
let updated_span = {existing_span with parent= Some parent} in
645+
let updated_span = {updated_span with context= new_context} in
646+
647+
let () = Spans.add_to_spans ~span:updated_span in
648+
updated_span
649+
)
650+
else
651+
Some span
652+
627653
let finish ?error span =
628654
Ok
629655
(Option.map
@@ -673,6 +699,13 @@ let with_tracing ?(attributes = []) ?(parent = None) ~name f =
673699
) else
674700
f None
675701

702+
let with_child_trace ?attributes parent ~name f =
703+
match parent with
704+
| None ->
705+
f None
706+
| Some _ as parent ->
707+
with_tracing ?attributes ~parent ~name f
708+
676709
module EnvHelpers = struct
677710
let traceparent_key = "TRACEPARENT"
678711

ocaml/libs/tracing/tracing.mli

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,8 @@ end
5757
module SpanContext : sig
5858
type t
5959

60+
val context : string -> string -> t
61+
6062
val to_traceparent : t -> string
6163

6264
val of_traceparent : string -> t option
@@ -125,6 +127,16 @@ module Tracer : sig
125127
-> unit
126128
-> (Span.t option, exn) result
127129

130+
val update_span_with_parent : Span.t -> Span.t option -> Span.t option
131+
(**[update_span_with_parent s p] returns [Some span] where [span] is an
132+
updated verison of the span [s].
133+
If [p] is [Some parent], [span] is a child of [parent], otherwise it is the
134+
original [s].
135+
136+
If the span [s] is finished or is no longer considered an on-going span,
137+
returns [None].
138+
*)
139+
128140
val finish :
129141
?error:exn * string -> Span.t option -> (Span.t option, exn) result
130142

@@ -199,6 +211,15 @@ val with_tracing :
199211
-> (Span.t option -> 'a)
200212
-> 'a
201213

214+
val with_child_trace :
215+
?attributes:(string * string) list
216+
-> Span.t option
217+
-> name:string
218+
-> (Span.t option -> 'a)
219+
-> 'a
220+
(** [with_child_trace ?attributes ?parent ~name f] is like {!val:with_tracing}, but
221+
only creates a span if the [parent] span exists. *)
222+
202223
val get_observe : unit -> bool
203224

204225
val validate_attribute : string * string -> bool

0 commit comments

Comments
 (0)