Library
Module
Module type
Parameter
Class
Class type
ppx_minidebug
usageppx_minidebug
traces selected code if it has type annotations. ppx_minidebug
offers three ways of instrumenting the code: %debug_pp
and %debug_show
based on deriving.show
, and %debug_sexp
based on sexplib0
and ppx_sexp_conv
. The syntax extension expects a module Debug_runtime
in the scope. The ppx_minidebug.runtime
library offers three ways of logging the traces, as functors generating Debug_runtime
modules given an output channel (e.g. for a file).
Take a look at ppx_debug
which is significantly more powerful!
See Minidebug_runtime
for the provided loggers.
Try opam install ppx_minidebug
to install from the opam repository. To install `ppx_minidebug` from sources, download it with e.g. gh repo clone lukstafi/ppx_minidebug; cd ppx_minidebug
and then either dune install
or opam install .
.
To use ppx_minidebug
in a Dune project, add/modify these stanzas: (preprocess (pps ... ppx_minidebug))
, and (libraries ... ppx_minidebug.runtime)
.
To trace a function, you have to type-annotate the function result. To trace an argument of a traced function, or a let
-binding, you need to type-annotate it. You can control how much gets logged by adding or removing type annotations.
Tracing only happens in explicitly marked scopes, using the extension points: %debug_pp
, %debug_this_pp
, %debug_show
, %debug_this_show
(based on printing functionality provided by deriving.show
), %debug_sexp
, %debug_this_sexp
(using functionality provided by sexplib0
and ppx_sexp_conv
). See examples in the test directory.
The %debug_this
variants are intended only for let
-bindings: let%debug_this v: t = compute value in body
will trace v
and the type-annotated bindings and functions inside compute value
, but it will not trace body
.
Example setting up a logger printing to the screen:
module Debug_runtime = (val Minidebug_runtime.debug_flushing ())
let%debug_show test_logging: string = "Hello World"
Example setting up a logger printing to a file:
module Debug_runtime =
Minidebug_runtime.Flushing((val Minidebug_runtime.debug_ch "debugger_flushing.log"))
let%debug_show test_logging: string = "Hello World"
Example setting up a logger printing to an HTML file -- this is only possible with the PrintBox
runtime. In this example, we also configure the converting the sexp
-based logs to the PrintBox
format (when they have at least 50 atoms). This means that both the log tree structure and the structure of large values can be incrementally explored using collapsible trees in an HTML renderer.
module Debug_runtime =
Minidebug_runtime.PrintBox ((val Minidebug_runtime.debug_ch "debug.html"))
let () = Debug_runtime.to_html := true
let () = Debug_runtime.boxify_sexp_from_size := 50
debug_html
is a configurable shorthand for the above setup:
module Debug_runtime = (val Minidebug_runtime.debug_html "debug.html")
Similarly, debug
and debug_flushing
are configurable shorthands that default to logging to stdout
(but accept a `~debug_ch` argument).
Computation can be optionally interruped using the ~max_nesting_depth
and ~max_num_children
settings. The first raises a failure when the nesting of logs exceeds the given threshold, the second raises a failure when the number of log entries under a single parent exceeds the threshold. E.g.:
module Debug_runtime =
(val Minidebug_runtime.debug_html ~max_nesting_depth:20 ~max_num_children:50 "debug.html")
The cutoff points are indicated in the logs.
VOCaml helpers for coding in OCaml provide commands to add and remove annotations on selected bindings. They can be used to introduce logging, tune it, and cleanup afterward. It also has a command to populate the _Quick Open_ dialog with a file name and location from a line under cursor. It can be used to jump to the source code from a log file.
Note that you can add and remove type annotations using VSCode OCaml Platform's code actions, and the Find and Transform suggestion below is a more flexible go-to-file solution -- so VOCaml is somewhat redundant. But, it is still valuable: (1) it annotates multiple let
-bindings at once in a selection, and (2) it annotates the argument types and the return type of a function (as required by ppx_debug
) when invoked on a function definition.
Log Inspector (sub-millisecond)'s main feature is visualizing timestamped logs as flame graphs. To invoke it in VS Code, go to the Minidebug_runtime.Flushing
-style logs file, press crtl+shift+P, and execute the command Log Inspector: Draw.
The sub-millisecond functionality is now upstreamed to Log Inspector.
This will expand your general-purpose VS Code toolbox!
Find and Transform is a powerful VS Code extension. I put the following in my `keybindings.json` file (command: Open Keyboard Shortcuts (JSON)):
{
"key": "alt+q",
"command": "findInCurrentFile",
"args": {
"description": "Open file at cursor",
"find": "\"([^\"]+)\":([0-9]+)",
"run": [
"$${",
"const pos = new vscode.Position($2, 0);",
"const range = new vscode.Range(pos, pos);",
"const options = {selection: range};",
"const wsFolderUri = vscode.workspace.workspaceFolders[0].uri;",
"const uri = await vscode.Uri.joinPath(wsFolderUri, '$1');",
"await vscode.commands.executeCommand('vscode.open', uri, options);",
// "await vscode.commands.executeCommand('workbench.action.quickOpen', `$1:$2`);",
"}$$",
],
"isRegex": true,
"restrictFind": "line",
}
}
Then, pressing `alt+q` will open a pre-populated dialog, and `enter` will get me to the file location. The file-and-location detection above matches the default one from the Flushing
module, you can adjust the find
pattern to match other formats.