-
Notifications
You must be signed in to change notification settings - Fork 285
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Remove tracing dependency from http-lib and add baggage (#6065)
Removes dependency on `tracing` from `http-lib` and add baggage. --- The introduction of it as a dependency was to support this style of code: ```ocaml let@ req = Http.Request.with_tracing ~name req in ``` However, HTTP headers are just a carrier in the context of tracing. The library ought to be as inert as possible; providing enough to endow requests with tracing information, but not calling into the tracing library to export child spans (as is done above). To this end, the notion of a [propagator](https://opentelemetry.io/docs/specs/otel/context/api-propagators/) is introduced that provides an interface for doing the above, but generalised to arbitrary carriers. If you can describe how to inject/extract a "trace context" into/from a carrier, you can conceivably propagate tracing across it. --- In future, the idea will be to: - This trace context can be inherited by spans, so it can reach the exporter. We can probably use the `SpanContext.t` record to do this. If this information can reach the exporter, we can choose to decorate spans with tags derived from the trace context (such as baggage) during exportation. - At incoming service boundaries, instead of pushing down a `Span.t option` derived from an encoded `traceparent` in the carrier, we will push down `TraceContext` (which is more general than the encoded `SpanContext` carried by the optional `Span.t` that's currently pushed down). This is so we can more easily handle the case where baggage is provided but a traceparent isn't: in which case, a span is still created if tracing is enabled, but with no parent to inherit contextual metadata from (a previous - abandoned - PR introduced baggage in a way that only worked when a traceparent was provided). --- Opening this as a draft for now. Would appreciate any commentary. There appears to be duplication of `Helper` but this is largely because XAPI's `dune` defines separate libraries which have slightly different dependencies. This has been manually tested with Jaeger, but more thorough testing should probably be done (comparing deeper span forests before and after these changes).
- Loading branch information
Showing
23 changed files
with
470 additions
and
126 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
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
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,109 @@ | ||
(* | ||
* Copyright (c) Cloud Software Group, Inc. | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms of the GNU Lesser General Public License as published | ||
* by the Free Software Foundation; version 2.1 only. with the special | ||
* exception on linking described in file LICENSE. | ||
* | ||
* This program is distributed in the hope that it will be useful, | ||
* but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
* GNU Lesser General Public License for more details. | ||
*) | ||
|
||
module type S = sig | ||
type carrier | ||
|
||
val inject_into : Tracing.TraceContext.t -> carrier -> carrier | ||
|
||
val extract_from : carrier -> Tracing.TraceContext.t | ||
end | ||
|
||
let ( let* ) = Option.bind | ||
|
||
let ( >> ) f g x = g (f x) | ||
|
||
let maybe f = function Some _ as o -> f o | _ -> Fun.id | ||
|
||
let[@tail_mod_cons] rec filter_append p xs ys = | ||
match xs with | ||
| [] -> | ||
ys | ||
| x :: xs when p x -> | ||
x :: filter_append p xs ys | ||
| _ :: xs -> | ||
filter_append p xs ys | ||
|
||
module Http = struct | ||
type carrier = Http.Request.t | ||
|
||
open struct | ||
let hdr_traceparent = "traceparent" | ||
|
||
let hdr_baggage = "baggage" | ||
end | ||
|
||
let alloc_assoc k kvs = | ||
List.filter_map | ||
(fun (key, value) -> if key = k then Some value else None) | ||
kvs | ||
|> function | ||
| [] -> | ||
None | ||
| xs -> | ||
Some xs | ||
|
||
let parse input = | ||
let open Astring.String in | ||
let trim_pair (key, value) = (trim key, trim value) in | ||
input | ||
|> cuts ~sep:";" | ||
|> List.map (cut ~sep:"=" >> Option.map trim_pair) | ||
|> List.filter_map Fun.id | ||
|
||
let inject_into ctx req = | ||
let open Tracing in | ||
let traceparent = (hdr_traceparent, TraceContext.traceparent_of ctx) in | ||
let baggage = | ||
let encoded = | ||
let encode = | ||
List.map (fun (k, v) -> Printf.sprintf "%s=%s" k v) | ||
>> String.concat ";" | ||
in | ||
TraceContext.baggage_of ctx |> Option.map encode | ||
in | ||
(hdr_baggage, encoded) | ||
in | ||
let entries = [traceparent; baggage] in | ||
let filter_entries entries = | ||
let tbl = Hashtbl.create 47 in | ||
let record (k, v) = | ||
match v with | ||
| Some v -> | ||
Hashtbl.replace tbl k () ; | ||
Some (k, v) | ||
| _ -> | ||
None | ||
in | ||
let entries = List.filter_map record entries in | ||
(entries, fst >> Hashtbl.mem tbl) | ||
in | ||
let entries, to_replace = filter_entries entries in | ||
let headers = req.Http.Request.additional_headers in | ||
let additional_headers = | ||
filter_append (Fun.negate to_replace) headers entries | ||
in | ||
{req with additional_headers} | ||
|
||
let extract_from req = | ||
let open Tracing in | ||
let headers = req.Http.Request.additional_headers in | ||
let traceparent = List.assoc_opt hdr_traceparent headers in | ||
let baggage = | ||
let* all = alloc_assoc hdr_baggage headers in | ||
Some (List.concat_map parse all) | ||
in | ||
let open TraceContext in | ||
empty |> maybe with_traceparent traceparent |> maybe with_baggage baggage | ||
end |
Oops, something went wrong.