RECORDER(3)

πŸ“¦ version 1.2.3, in fedora 43, fedora 44

✨ RECORDER, RECORDER_DEFINE, RECORDER_DECLARE ✨

okay bestie, this is a page from the Recorder Library and it's literally all about declaring and defining the little buffers that hold your events πŸ’–


🌸 NAME 🌸

RECORDER, RECORDER_DEFINE, RECORDER_DECLARE β€” declare and define buffers to record events πŸ’…


πŸŽ€ SYNOPSIS πŸŽ€

#include <recorder/recorder.h>

#define RECORDER(recname, recsize, rechelp) ...
#define RECORDER_DEFINE(recname, recsize, rechelp) ...
#define RECORDER_DECLARE(recname) ...

πŸ¦‹ DESCRIPTION πŸ¦‹

so the RECORDER() macro defines a buffer named recname that can store up to recsize events, and those events get used by the record(3) function. the rechelp string is the self-documentation β€” it describes what kinds of events live in that buffer. and the way you actually see that self-documentation? you turn on the help trace, which is described over in recorder_set_trace(3). iykyk ✨

the RECORDER_DECLARE() macro just declares an event recorder, and it's the one you're allowed to drop in header files πŸ“„

the RECORDER_DEFINE() macro is literally just an alias for RECORDER(). the vibe is intentional though:

  • use RECORDER() for event recorders that are local to a single file 🏠
  • use a RECORDER_DECLARE() in the header file paired with a RECORDER_DEFINE() in a non-header file for event recorders that get shared across multiple translation units 🀝

these macros need to live at file scope, aka exactly where a function definition or a global variable is allowed. no putting them inside functions, bestie πŸ™ˆ

every single recorder has a trace value associated with it β€” that's an integer value you can read with RECORDER_TRACE(3). see also recorder_trace_set(3). πŸ‘‘


πŸ”₯ EXAMPLES πŸ”₯

the program below records its input arguments, and it crashes if you pass crash as the first command-line argument. (yes it crashes on purpose, it's a demo, breathe 😭)

#include <recorder/recorder.h>
#include <string.h>

RECORDER(program_args, 32, "Program command-line arguments");
int main(int argc, char **argv)
{
    int a;
    recorder_dump_on_common_signals(0, 0);
    for (a = 0; a < argc; a++)
        record(program_args, "Argument %d is %+s", a, argv[a]);

    if (argc >= 2 && strcmp(argv[1], "crash") == 0)
    {
        char *ptr = NULL;
        strcpy(ptr, argv[1]);
    }
}

when a crash happens, the events that got recorded earlier get printed out on the console. iconic πŸ’€βœ¨


next up: the program below is an instrumented version of the classic recursive Fibonacci computation. it uses several recorders for different types of events, and it activates warnings and errors in a way you can configure by setting an environment variable 🌈

#include <recorder/recorder.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>

RECORDER(fib_main,    32, "Loops in fib function");
RECORDER(fib_loops,   32, "Loops in fib function");
RECORDER(fib_warning, 32, "Warnings in fib function");
RECORDER(fib_error,   32, "Errors in fib function");

int fib(int n)
{
    if (n <= 1) {
        if (n < 0)
            record(fib_error, "fib is undefined for negative value %d", n);
        return n;
    }
    record(fib_loops, "Computing fib(%d)", n);
    int result = fib(n-1) + fib(n-2);
    record(fib_loops, "Computed fib(%d) = %d", n, result);
    return result;
}

int main(int argc, char **argv)
{
    int a;
    recorder_dump_on_common_signals(0, 0);
    recorder_trace_set(".*_warning=35 .*_error");
    recorder_trace_set(getenv("FIB_TRACES"));
    for (a = 1; a < argc; a++) {
        int n = atoi(argv[a]);
        if (n >= RECORDER_TRACE(fib_warning))
            record(fib_warning, "Computing for %d may take a while", n);
        printf("fib(%d) = %d0, n, fib(n));
        if (n >= RECORDER_TRACE(fib_warning))
            record(fib_warning, "Computation for %d finally completed", n);
    }
}

this program will produce an output similar to the following πŸ‘‡

% fib 1 2 3 4 10 20 30 35 10 40 -1
fib(1) = 1
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(10) = 55
fib(20) = 6765
fib(30) = 832040
[2714667 0.177725] fib_warning: Computing for 35 may take a while
fib(35) = 9227465
[32575370 1.859156] fib_warning: Computation for 35 finally completed
fib(10) = 55
[32575547 1.859171] fib_warning: Computing for 40 may take a while
fib(40) = 102334155
[363735828 20.527882] fib_warning: Computation for 40 finally completed
[363735829 20.527887] fib_error: fib is undefined for negative value -1
fib(-1) = -1

about those trace outputs: the first column is the number of events that were recorded. the second column is the time in seconds since the program started ⏱️ (yes, that typo-ish capital in the original says THe β€” that's just how it is, no cap).


the same program can also be run with additional tracing or warnings, like so:

% FIB_TRACES="recorder_location fib_loops fib_warning=3" /tmp/fib 3 4
/tmp/fib.c:33:[82 0.000496] fib_warning: Computing for 3 may take a while
/tmp/fib.c:18:[83 0.000561] fib_loops: Computing fib(3)
/tmp/fib.c:18:[84 0.000570] fib_loops: Computing fib(2)
/tmp/fib.c:20:[85 0.000575] fib_loops: Computed fib(2) = 1
/tmp/fib.c:20:[86 0.000581] fib_loops: Computed fib(3) = 2
fib(3) = 2
/tmp/fib.c:36:[87 0.000590] fib_warning: Computation for 3 finally completed
/tmp/fib.c:33:[88 0.000596] fib_warning: Computing for 4 may take a while
/tmp/fib.c:18:[89 0.000601] fib_loops: Computing fib(4)
/tmp/fib.c:18:[90 0.000607] fib_loops: Computing fib(3)
/tmp/fib.c:18:[91 0.000612] fib_loops: Computing fib(2)
/tmp/fib.c:20:[92 0.000619] fib_loops: Computed fib(2) = 1
/tmp/fib.c:20:[93 0.000625] fib_loops: Computed fib(3) = 2
/tmp/fib.c:18:[94 0.000664] fib_loops: Computing fib(2)
/tmp/fib.c:20:[95 0.000707] fib_loops: Computed fib(2) = 1
/tmp/fib.c:20:[96 0.000724] fib_loops: Computed fib(4) = 3
fib(4) = 3
/tmp/fib.c:36:[97 0.000741] fib_warning: Computation for 4 finally completed

πŸ’€ BUGS πŸ’€

if you use these macros incorrectly, you're generally gonna get nonsensical compiler diagnostics. like, the compiler will start speaking in riddles. that's the punishment πŸ™ˆ

bugs should be reported using https://github.com/c3d/recorder/issues β€” pls actually report them, don't just suffer in silence bestie 🫢

🌟 SEE ALSO 🌟

additional documentation and tutorials can be found at https://github.com/c3d/recorder πŸ“šβœ¨


πŸ‘‘ AUTHOR πŸ‘‘

written by Christophe de Dinechin πŸ’œ


okay that's the whole thing, you're officially certified in recorder macros, slay πŸ’… this was version 1.0, dated 2019-03-09, and it's the RECORDER(3) page, so go forth and record your events, bestie πŸŽ€πŸ’–

πŸ“¦ where this page comes from