wip: cohttp integration

This commit is contained in:
Matt Bray 2022-03-24 13:46:06 +00:00
parent c419a61815
commit a1115661b4
5 changed files with 118 additions and 0 deletions

View file

@ -45,3 +45,14 @@
(odoc :with-doc)
ocurl)
(synopsis "Collector client for opentelemetry, using http + ocurl"))
(package
(name opentelemetry-cohttp-lwt)
(depends
(ocaml (>= "4.08"))
(dune (>= "2.3"))
(opentelemetry (= :version))
(opentelemetry-lwt (= :version))
(odoc :with-doc)
cohttp-lwt)
(synopsis "Opentelemetry tracing for Cohttp HTTP servers"))

View file

@ -0,0 +1,33 @@
# This file is generated by dune, edit dune-project instead
opam-version: "2.0"
synopsis: "Opentelemetry tracing for Cohttp HTTP servers"
maintainer: ["the Imandra team"]
authors: ["the Imandra team"]
license: "MIT"
homepage: "https://github.com/aestheticintegration/ocaml-opentelemetry"
bug-reports:
"https://github.com/aestheticintegration/ocaml-opentelemetry/issues"
depends: [
"ocaml" {>= "4.08"}
"dune" {>= "2.3"}
"opentelemetry" {= version}
"opentelemetry-lwt" {= version}
"odoc" {with-doc}
"cohttp-lwt"
]
build: [
["dune" "subst"] {pinned}
[
"dune"
"build"
"-p"
name
"-j"
jobs
"@install"
"@runtest" {with-test}
"@doc" {with-doc}
]
]
dev-repo:
"git+https://github.com/aestheticintegration/ocaml-opentelemetry.git"

View file

@ -0,0 +1,11 @@
# Opentelemetry tracing for Cohttp_lwt servers
Wrap your server callback with `Opentelemetry_cohttp_lwt.trace`:
```ocaml
let my_server callback =
Cohttp_lwt_unix.Server.create ~mode:(`TCP (`Port 8080))
(Server.make
~callback:(Opentelemetry_cohttp_lwt.trace ~service_name:"my-service" callback)
())
```

View file

@ -0,0 +1,4 @@
(library
(name opentelemetry_cohttp_lwt)
(public_name opentelemetry-cohttp-lwt)
(libraries cohttp-lwt opentelemetry opentelemetry-lwt))

View file

@ -0,0 +1,59 @@
open Cohttp
open Cohttp_lwt
type ('conn, 'body) callback =
'conn (* Cohttp_lwt_unix.Server.conn *)
-> Request.t
-> 'body (* Cohttp_lwt.Body.t *)
-> (Response.t * 'body) Lwt.t
let span_attrs (req : Request.t) =
let meth = req |> Request.meth |> Code.string_of_method in
let referer = Header.get (Request.headers req) "referer" in
let host = Header.get (Request.headers req) "host" in
let ua = Header.get (Request.headers req) "user-agent" in
let uri = Request.uri req in
List.concat
[ [ ("http.method", `String meth) ]
; (match host with None -> [] | Some h -> [ ("http.host", `String h) ])
; [ ("http.url", `String (Uri.to_string uri)) ]
; ( match ua with
| None ->
[]
| Some ua ->
[ ("http.user_agent", `String ua) ] )
; ( match referer with
| None ->
[]
| Some r ->
[ ("http.request.header.referer", `String r) ] )
]
let trace ~service_name (callback : ('conn, 'body) callback ) : ('conn, 'body) callback =
fun conn req body ->
let trace_id =
Header.get (Request.headers req) "trace-id"
|> Option.map (fun s ->
s |> Bytes.of_string |> Opentelemetry.Trace_id.of_bytes )
in
let parent_id =
Header.get (Request.headers req) "parent-id"
|> Option.map (fun s ->
s |> Bytes.of_string |> Opentelemetry.Span_id.of_bytes )
in
let open Lwt.Syntax in
Opentelemetry_lwt.Trace.with_
~service_name
"request"
~kind:Span_kind_server
~attrs:(span_attrs req)
?parent:parent_id
?trace_id
(fun scope ->
let* (res, body) = callback conn req body in
Opentelemetry.Trace.add_attrs scope (fun () ->
let code = Response.status res in
let code = Code.code_of_status code in
[ ("http.status_code", `Int code) ]) ;
Lwt.return (res, body) )