Skip to content

Commit 0c65928

Browse files
authored
Merge pull request #5735 from GabrielBuica/private/dbuica/CA-394169-tracing
Instrument task related functionality
2 parents cbd156c + d496db1 commit 0c65928

File tree

5 files changed

+117
-71
lines changed

5 files changed

+117
-71
lines changed

ocaml/xapi/context.ml

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -503,12 +503,23 @@ let get_user_agent context =
503503
let with_tracing ?originator ~__context name f =
504504
let open Tracing in
505505
let parent = __context.tracing in
506-
let span_attributes = Attributes.attr_of_originator originator in
506+
let span_attributes =
507+
Attributes.attr_of_originator originator
508+
@ make_attributes ~task_id:__context.task_id
509+
?session_id:__context.session_id ()
510+
in
507511
match start_tracing_helper ~span_attributes (fun _ -> parent) name with
508-
| Some _ as span ->
512+
| Some _ as span -> (
513+
try
509514
let new_context = {__context with tracing= span} in
510515
let result = f new_context in
511516
let _ = Tracer.finish span in
512517
result
518+
with exn ->
519+
let backtrace = Printexc.get_raw_backtrace () in
520+
let error = (exn, Printexc.raw_backtrace_to_string backtrace) in
521+
ignore @@ Tracer.finish span ~error ;
522+
Printexc.raise_with_backtrace exn backtrace
523+
)
513524
| None ->
514525
f __context

ocaml/xapi/helpers.ml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -550,6 +550,7 @@ let call_api_functions_internal ~__context f =
550550
)
551551

552552
let call_api_functions ~__context f =
553+
Context.with_tracing ~__context __FUNCTION__ @@ fun __context ->
553554
match Context.get_test_rpc __context with
554555
| Some rpc ->
555556
f rpc (Ref.of_string "fake_session")
@@ -1764,6 +1765,7 @@ module Task : sig
17641765
end = struct
17651766
(* can't place these functions in task helpers due to circular dependencies *)
17661767
let wait_for_ ~__context ~tasks ~propagate_cancel cb =
1768+
Context.with_tracing ~__context __FUNCTION__ @@ fun __context ->
17671769
let our_task = Context.get_task_id __context in
17681770
let classes =
17691771
List.map
@@ -1850,6 +1852,7 @@ end = struct
18501852
wait_for_ ~__context ~tasks:[t] mirror
18511853

18521854
let to_result ~__context ~of_rpc ~t =
1855+
Context.with_tracing ~__context __FUNCTION__ @@ fun __context ->
18531856
wait_for_mirror ~__context ~propagate_cancel:true ~t ;
18541857
let fail msg =
18551858
raise

ocaml/xapi/message_forwarding.ml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -699,6 +699,7 @@ functor
699699
include Local.Task
700700

701701
let cancel ~__context ~task =
702+
Context.with_tracing ~__context __FUNCTION__ @@ fun __context ->
702703
TaskHelper.assert_op_valid ~__context task ;
703704
let local_fn = cancel ~task in
704705
let forwarded_to = Db.Task.get_forwarded_to ~__context ~self:task in
@@ -1196,6 +1197,7 @@ functor
11961197
with _ -> ()
11971198

11981199
let cancel ~__context ~vm ~ops =
1200+
Context.with_tracing ~__context __FUNCTION__ @@ fun __context ->
11991201
let cancelled =
12001202
List.filter_map
12011203
(fun (task, op) ->

ocaml/xapi/taskHelper.ml

Lines changed: 91 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,19 @@ module Date = Xapi_stdext_date.Date
1818

1919
let with_lock = Xapi_stdext_threads.Threadext.Mutex.execute
2020

21+
let ( let@ ) f x = f x
22+
23+
let finally_complete_tracing ?error __context f =
24+
Xapi_stdext_pervasives.Pervasiveext.finally f (fun () ->
25+
Context.complete_tracing ?error __context
26+
)
27+
2128
type t = API.ref_task
2229

2330
(* creates a new task *)
2431
let make ~__context ~http_other_config ?(description = "") ?session_id
2532
?subtask_of label : t * t Uuidx.t =
33+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
2634
let uuid = Uuidx.make () in
2735
let uuid_str = Uuidx.to_string uuid in
2836
let ref = Ref.make () in
@@ -35,8 +43,7 @@ let make ~__context ~http_other_config ?(description = "") ?session_id
3543
Ref.null
3644
in
3745
let (_ : unit) =
38-
Db_actions.DB_Action.Task.create ~ref ~__context
39-
~created:(Date.of_float (Unix.time ()))
46+
Db_actions.DB_Action.Task.create ~ref ~__context ~created:(Date.now ())
4047
~finished:(Date.of_float 0.0) ~current_operations:[] ~_type:"<none/>"
4148
~session:(Option.value ~default:Ref.null session_id)
4249
~resident_on:!Xapi_globs.localhost_ref ~status:`pending ~result:""
@@ -64,6 +71,7 @@ let are_auth_user_ids_of_sessions_equal ~__context s1 s2 =
6471
s1_auth_user_sid = s2_auth_user_sid
6572

6673
let assert_op_valid ?(ok_if_no_session_in_context = false) ~__context task_id =
74+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
6775
let assert_permission_task_op_any () =
6876
match !rbac_assert_permission_fn with
6977
| None ->
@@ -106,13 +114,15 @@ let assert_op_valid ?(ok_if_no_session_in_context = false) ~__context task_id =
106114
assert_permission_task_op_any ()
107115

108116
let get_name ~__context =
117+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
109118
let task_id = Context.get_task_id __context in
110119
if Ref.is_dummy task_id then
111120
Ref.name_of_dummy task_id
112121
else
113122
Db.Task.get_name_label ~__context ~self:task_id
114123

115124
let destroy ~__context task_id =
125+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
116126
if not (Ref.is_dummy task_id) then (
117127
assert_op_valid ~ok_if_no_session_in_context:true ~__context task_id ;
118128
Db_actions.DB_Action.Task.destroy ~__context ~self:task_id
@@ -128,34 +138,36 @@ let init () =
128138
Context.__make_task := make
129139

130140
let operate_on_db_task ~__context f =
141+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
131142
if Context.task_in_database __context then
132143
f (Context.get_task_id __context)
133144

134145
let set_description ~__context value =
135-
operate_on_db_task ~__context (fun self ->
136-
Db_actions.DB_Action.Task.set_name_description ~__context ~self ~value
137-
)
146+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
147+
let@ self = operate_on_db_task ~__context in
148+
Db_actions.DB_Action.Task.set_name_description ~__context ~self ~value
138149

139150
let add_to_other_config ~__context key value =
140-
operate_on_db_task ~__context (fun self ->
141-
Db_actions.DB_Action.Task.remove_from_other_config ~__context ~self ~key ;
142-
Db_actions.DB_Action.Task.add_to_other_config ~__context ~self ~key ~value
143-
)
151+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
152+
let@ self = operate_on_db_task ~__context in
153+
Db_actions.DB_Action.Task.remove_from_other_config ~__context ~self ~key ;
154+
Db_actions.DB_Action.Task.add_to_other_config ~__context ~self ~key ~value
144155

145156
let set_progress ~__context value =
146-
operate_on_db_task ~__context (fun self ->
147-
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value
148-
)
157+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
158+
let@ self = operate_on_db_task ~__context in
159+
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value
149160

150161
let set_external_pid ~__context pid =
151-
operate_on_db_task ~__context (fun self ->
152-
Db_actions.DB_Action.Task.set_externalpid ~__context ~self
153-
~value:(Int64.of_int pid)
154-
)
162+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
163+
let@ self = operate_on_db_task ~__context in
164+
Db_actions.DB_Action.Task.set_externalpid ~__context ~self
165+
~value:(Int64.of_int pid)
155166

156167
let clear_external_pid ~__context = set_external_pid ~__context (-1)
157168

158169
let set_result_on_task ~__context task_id result =
170+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
159171
match result with
160172
| None ->
161173
()
@@ -165,7 +177,9 @@ let set_result_on_task ~__context task_id result =
165177

166178
(** Only set the result without completing the task. Useful for vm import *)
167179
let set_result ~__context result =
168-
operate_on_db_task ~__context (fun t -> set_result_on_task ~__context t result)
180+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
181+
let@ self = operate_on_db_task ~__context in
182+
set_result_on_task ~__context self result
169183

170184
let status_to_string = function
171185
| `pending ->
@@ -183,36 +197,36 @@ let status_is_completed task_status =
183197
task_status = `success || task_status = `failure || task_status = `cancelled
184198

185199
let complete ~__context result =
186-
Context.complete_tracing __context ;
187-
operate_on_db_task ~__context (fun self ->
188-
let status = Db_actions.DB_Action.Task.get_status ~__context ~self in
189-
if status = `pending then (
190-
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
191-
~value:[] ;
192-
Db_actions.DB_Action.Task.set_finished ~__context ~self
193-
~value:(Date.of_float (Unix.time ())) ;
194-
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value:1. ;
195-
set_result_on_task ~__context self result ;
196-
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`success
197-
) else
198-
debug "the status of %s is: %s; cannot set it to `success"
199-
(Ref.really_pretty_and_small self)
200-
(status_to_string status)
201-
)
200+
let@ () = finally_complete_tracing __context in
201+
let@ self = operate_on_db_task ~__context in
202+
let status = Db_actions.DB_Action.Task.get_status ~__context ~self in
203+
match status with
204+
| `pending ->
205+
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
206+
~value:[] ;
207+
Db_actions.DB_Action.Task.set_finished ~__context ~self
208+
~value:(Date.now ()) ;
209+
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value:1. ;
210+
set_result_on_task ~__context self result ;
211+
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`success
212+
| _ ->
213+
debug "the status of %s is: %s; cannot set it to `success"
214+
(Ref.really_pretty_and_small self)
215+
(status_to_string status)
202216

203217
let set_cancellable ~__context =
204-
operate_on_db_task ~__context (fun self ->
205-
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
206-
~value:[`cancel]
207-
)
218+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
219+
let@ self = operate_on_db_task ~__context in
220+
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
221+
~value:[`cancel]
208222

209223
let set_not_cancellable ~__context =
210-
operate_on_db_task ~__context (fun self ->
211-
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
212-
~value:[]
213-
)
224+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
225+
let@ self = operate_on_db_task ~__context in
226+
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self ~value:[]
214227

215228
let is_cancelling ~__context =
229+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
216230
Context.task_in_database __context
217231
&&
218232
let l =
@@ -222,21 +236,22 @@ let is_cancelling ~__context =
222236
List.exists (fun (_, x) -> x = `cancel) l
223237

224238
let raise_cancelled ~__context =
239+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
225240
let task_id = Context.get_task_id __context in
226241
raise Api_errors.(Server_error (task_cancelled, [Ref.string_of task_id]))
227242

228243
let exn_if_cancelling ~__context =
244+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
229245
if is_cancelling ~__context then
230246
raise_cancelled ~__context
231247

232248
let cancel_this ~__context ~self =
233-
Context.complete_tracing __context ;
249+
let@ () = finally_complete_tracing __context in
234250
assert_op_valid ~__context self ;
235251
let status = Db_actions.DB_Action.Task.get_status ~__context ~self in
236252
if status = `pending then (
237253
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value:1. ;
238-
Db_actions.DB_Action.Task.set_finished ~__context ~self
239-
~value:(Date.of_float (Unix.time ())) ;
254+
Db_actions.DB_Action.Task.set_finished ~__context ~self ~value:(Date.now ()) ;
240255
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`cancelled ;
241256
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self ~value:[]
242257
) else
@@ -245,35 +260,40 @@ let cancel_this ~__context ~self =
245260
(status_to_string status)
246261

247262
let cancel ~__context =
248-
operate_on_db_task ~__context (fun self -> cancel_this ~__context ~self)
263+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
264+
let@ self = operate_on_db_task ~__context in
265+
cancel_this ~__context ~self
249266

250267
let failed ~__context exn =
251268
let backtrace = Printexc.get_backtrace () in
252-
Context.complete_tracing __context ~error:(exn, backtrace) ;
269+
let@ () = finally_complete_tracing ~error:(exn, backtrace) __context in
253270
let code, params = ExnHelper.error_of_exn exn in
254-
operate_on_db_task ~__context (fun self ->
255-
let status = Db_actions.DB_Action.Task.get_status ~__context ~self in
256-
if status = `pending then (
257-
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value:1. ;
258-
Db_actions.DB_Action.Task.set_error_info ~__context ~self
259-
~value:(code :: params) ;
260-
Db_actions.DB_Action.Task.set_backtrace ~__context ~self
261-
~value:(Sexplib.Sexp.to_string Backtrace.(sexp_of_t (get exn))) ;
262-
Db_actions.DB_Action.Task.set_finished ~__context ~self
263-
~value:(Date.of_float (Unix.time ())) ;
264-
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
265-
~value:[] ;
266-
if code = Api_errors.task_cancelled then
267-
Db_actions.DB_Action.Task.set_status ~__context ~self
268-
~value:`cancelled
269-
else
270-
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`failure
271-
) else
272-
debug "the status of %s is %s; cannot set it to %s"
273-
(Ref.really_pretty_and_small self)
274-
(status_to_string status)
275-
(if code = Api_errors.task_cancelled then "`cancelled" else "`failure")
276-
)
271+
let@ self = operate_on_db_task ~__context in
272+
let status = Db_actions.DB_Action.Task.get_status ~__context ~self in
273+
match status with
274+
| `pending ->
275+
Db_actions.DB_Action.Task.set_progress ~__context ~self ~value:1. ;
276+
Db_actions.DB_Action.Task.set_error_info ~__context ~self
277+
~value:(code :: params) ;
278+
Db_actions.DB_Action.Task.set_backtrace ~__context ~self
279+
~value:(Sexplib.Sexp.to_string Backtrace.(sexp_of_t (get exn))) ;
280+
Db_actions.DB_Action.Task.set_finished ~__context ~self
281+
~value:(Date.now ()) ;
282+
Db_actions.DB_Action.Task.set_allowed_operations ~__context ~self
283+
~value:[] ;
284+
if code = Api_errors.task_cancelled then
285+
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`cancelled
286+
else
287+
Db_actions.DB_Action.Task.set_status ~__context ~self ~value:`failure
288+
| _ ->
289+
debug "the status of %s is %s; cannot set it to %s"
290+
(Ref.really_pretty_and_small self)
291+
(status_to_string status)
292+
( if code = Api_errors.task_cancelled then
293+
"`cancelled"
294+
else
295+
"`failure"
296+
)
277297

278298
type id = Sm of string | Xenops of string * string
279299

@@ -292,6 +312,7 @@ let task_to_id_exn task =
292312
with_lock task_tbl_m (fun () -> Hashtbl.find task_to_id_tbl task)
293313

294314
let register_task __context ?(cancellable = true) id =
315+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
295316
let task = Context.get_task_id __context in
296317
with_lock task_tbl_m (fun () ->
297318
Hashtbl.replace id_to_task_tbl id task ;
@@ -307,6 +328,7 @@ let register_task __context ?(cancellable = true) id =
307328
()
308329

309330
let unregister_task __context id =
331+
let@ __context = Context.with_tracing ~__context __FUNCTION__ in
310332
(* The rest of the XenAPI Task won't be cancellable *)
311333
set_not_cancellable ~__context ;
312334
with_lock task_tbl_m (fun () ->

0 commit comments

Comments
 (0)