package trace

  1. Overview
  2. Docs

Source file trace_core.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
include Types
module A = Atomic_
module Collector = Collector
module Level = Level
module Core_ext = Core_ext

type collector = Collector.t

(* ## globals ## *)

(** Global collector. *)
let collector : collector A.t = A.make Collector.C_none

(* default level for spans without a level *)
let default_level_ = A.make Level.Trace
let current_level_ = A.make Level.Trace

(* ## implementation ## *)

let data_empty_build_ () = []
let[@inline] enabled () = Collector.is_some (A.get collector)
let[@inline] get_default_level () = A.get default_level_
let[@inline] set_default_level l = A.set default_level_ l
let[@inline] set_current_level l = A.set current_level_ l
let[@inline] get_current_level () = A.get current_level_

let[@inline] check_level_ ~level st (cbs : _ Collector.Callbacks.t) : bool =
  Level.leq level (A.get current_level_) && cbs.enabled st level

let parent_of_span_opt_opt = function
  | None -> P_unknown
  | Some None -> P_none
  | Some (Some p) -> P_some p

let enter_span_st st (cbs : _ Collector.Callbacks.t) ?__FUNCTION__ ~__FILE__
    ~__LINE__ ~level ?parent ?(params = []) ?(data = data_empty_build_) name :
    span =
  let parent = parent_of_span_opt_opt parent in
  let data = data () in
  cbs.enter_span st ~__FUNCTION__ ~__FILE__ ~__LINE__ ~level ~parent ~params
    ~data name

let with_span_collector_ st (cbs : _ Collector.Callbacks.t) ?__FUNCTION__
    ~__FILE__ ~__LINE__ ~level ?parent ?params ?data name f =
  let sp : span =
    enter_span_st st cbs ?__FUNCTION__ ~__FILE__ ~__LINE__ ~level ?parent
      ?params ?data name
  in
  match f sp with
  | res ->
    cbs.exit_span st sp;
    res
  | exception exn ->
    let bt = Printexc.get_raw_backtrace () in
    cbs.exit_span st sp;
    Printexc.raise_with_backtrace exn bt

let[@inline] with_span ?(level = A.get default_level_) ?__FUNCTION__ ~__FILE__
    ~__LINE__ ?parent ?params ?data name f =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    with_span_collector_ st cbs ?__FUNCTION__ ~__FILE__ ~__LINE__ ~level ?parent
      ?params ?data name f
  | _ ->
    (* fast path: no collector, no span *)
    f Collector.dummy_span

let[@inline] enter_span ?(level = A.get default_level_) ?__FUNCTION__ ~__FILE__
    ~__LINE__ ?flavor ?parent ?(params = []) ?data name : span =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    let params =
      match flavor with
      | None -> params
      | Some f -> Core_ext.Extension_span_flavor f :: params
    in
    (enter_span_st [@inlined never]) st cbs ?__FUNCTION__ ~__FILE__ ~__LINE__
      ~level ?parent ~params ?data name
  | _ -> Collector.dummy_span

let[@inline] exit_span sp : unit =
  match A.get collector with
  | C_none -> ()
  | C_some (st, cbs) -> cbs.exit_span st sp

let[@inline] add_data_to_span sp data : unit =
  if sp != Collector.dummy_span && data <> [] then (
    match A.get collector with
    | C_none -> ()
    | C_some (st, cbs) -> cbs.add_data_to_span st sp data
  )

let message_collector_ st (cbs : _ Collector.Callbacks.t) ~level ?span
    ?(params = []) ?(data = data_empty_build_) msg : unit =
  let data = data () in
  cbs.message st ~level ~span ~params ~data msg

let[@inline] message ?(level = A.get default_level_) ?span ?params ?data msg :
    unit =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    (message_collector_ [@inlined never]) st cbs ~level ?span ?params ?data msg
  | _ -> ()

let messagef ?(level = A.get default_level_) ?span ?params ?data k =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    k (fun fmt ->
        Format.kasprintf
          (fun str -> message_collector_ st cbs ~level ?span ?params ?data str)
          fmt)
  | _ -> ()

let metric ?(level = A.get default_level_) ?(params = [])
    ?(data = data_empty_build_) name m : unit =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    let data = data () in
    cbs.metric st ~level ~params ~data name m
  | _ -> ()

let counter_int ?level ?params ?data name n : unit =
  metric ?level ?params ?data name (Core_ext.Metric_int n)

let counter_float ?level ?params ?data name n : unit =
  metric ?level ?params ?data name (Core_ext.Metric_float n)

let setup_collector c : unit =
  while
    let cur = A.get collector in
    match cur with
    | C_some _ -> invalid_arg "trace: collector already present"
    | C_none -> not (A.compare_and_set collector cur c)
  do
    ()
  done;

  (* initialize collector *)
  match c with
  | C_none -> ()
  | C_some (st, cb) -> cb.init st

let shutdown () =
  match A.exchange collector C_none with
  | C_none -> ()
  | C_some (st, cbs) -> cbs.shutdown st

let with_setup_collector c f =
  setup_collector c;
  Fun.protect ~finally:shutdown f

type extension_event = Types.extension_event = ..

let[@inline] extension_event ?(level = A.get default_level_) ev : unit =
  match A.get collector with
  | C_some (st, cbs) when check_level_ ~level st cbs ->
    cbs.extension st ~level ev
  | _ -> ()

let set_thread_name name : unit =
  extension_event @@ Core_ext.Extension_set_thread_name name

let set_process_name name : unit =
  extension_event @@ Core_ext.Extension_set_process_name name

module Internal_ = struct
  module Atomic_ = Atomic_
end

(* ### deprecated *)

[@@@ocaml.alert "-deprecated"]

let enter_manual_span ~parent ?flavor ?level ?__FUNCTION__ ~__FILE__ ~__LINE__
    ?data name : explicit_span =
  let params =
    match flavor with
    | None -> []
    | Some f -> [ Core_ext.Extension_span_flavor f ]
  in
  enter_span ~parent ~params ?level ?__FUNCTION__ ~__FILE__ ~__LINE__ ?data name

let enter_manual_toplevel_span ?flavor ?level ?__FUNCTION__ ~__FILE__ ~__LINE__
    ?data name : explicit_span =
  enter_manual_span ~parent:None ?flavor ?level ?__FUNCTION__ ~__FILE__
    ~__LINE__ ?data name

let enter_manual_sub_span ~parent ?flavor ?level ?__FUNCTION__ ~__FILE__
    ~__LINE__ ?data name : explicit_span =
  enter_manual_span ~parent:(Some parent) ?flavor ?level ?__FUNCTION__ ~__FILE__
    ~__LINE__ ?data name

let exit_manual_span = exit_span
let add_data_to_manual_span = add_data_to_span

[@@@ocaml.alert "+deprecated"]