package devkit

  1. Overview
  2. Docs

This module uses Lwt thread storage to give threads "marks", which store thread id (some unique int, autogenerated), name (given by user, see name and ignore_result), parent thread name, and few (currently 10, may be changed) last log messages that was output from this thread using Log module.

Thread mark is removed when the thread terminates.

summary () is the way to inspect current marks.

Marking must be initialized (init ()) to work with marks. When marking is not initialized, most of functions behave as no-op, this is implemented by checking internal_flag : bool ref, so it's cheap. There is no way to disable marking.

There are no "links from current thread mark to parent thread mark" ( = no "call stack"), as it may grow infinitely in a perfectly working code that uses constant memory otherwise.

Most of strings (names, logs) are lazy (internally), as their evaluation is needed only when one inspects current threads state. Functions that take strings wrap them with Lazy.from_val.

val init : unit -> unit

Enables thread marking. Use before calling other functions of this module.

val is_enabled : unit -> bool
val name : string -> (unit -> 'a Lwt.t) -> 'a Lwt.t

name n cont creates new lwt thread cont () marked with name n. Usage:

let myfunc () = Lwt_mark.name "myfunc" @@ fun () -> <the_body>

val status : string Lazy.t -> ?dump:('a -> string) -> (unit -> 'a Lwt.t) -> 'a Lwt.t

status lazy_name ?dump cont

Usage:

lwt was_read = Lwt_mark.status (lazy (sprintf "reading %i bytes" to_read)) ~dump:string_of_int @@ fun () -> Lwt_unix.read fd buf ofs to_read in

Start/exit of thread cont () will be logged to parent thread's last logs.

lazy_name must be able to be evaluated into a meaningful thread name when it is forced, no matter when (before thread startup, during thread execution, after thread exit).

Use ?dump argument when you need to log return value of the thread.

Internally status works like name, but statuses are groupped and displayed by summary in the section of thread that created them.

val status_s : string -> ?dump:('a -> string) -> (unit -> 'a Lwt.t) -> 'a Lwt.t
val async : ?log:Log.logger -> string -> (unit -> unit Lwt.t) -> unit

async ?log name run_thread works like name + Lwt.async run_thread, but thread is marked as "background" (just for display purposes). Pass ~log to log thread failure with devkit logger (level = warn).

val log : string -> unit

Adds line to current thread's last logs. When marking is enabled, but current thread is not marked/named, line is added to special "<top>" thread logs.

val log_l : string Lazy.t -> unit
val log_f : ('a, unit, string, unit) format4 -> 'a
val summary : unit -> string

Human-readable marks summary: current running threads, their last logs and statuses.