1
2record(3) Recorder Library record(3)
3
4
5
7 record, record_fast - Fast event logging in circular buffers
8
9
10
12 #include <recorder/recorder.h>
13
14 ringidx_t record(recorder_name recname, const char *format, ...);
15 ringidx_t record_fast(recorder_name recname, const char *format, ...);
16
18 The record() function stores an event in the recorder identified by
19 recname. The event record includes a time stamp provided by the get‐
20 timeofday(3) function (or a similar absolute time function), as well as
21 the format string and up to 12 additional arguments. The format string
22 should follow the printf(3) conventions, with the exceptions and addi‐
23 tions indicated below.
24
25
26 The record_fast() reuses the time stamp of the previous record() func‐
27 tion for the same recorder, making it approximately twice as fast on
28 some modern systems. The cost difference should be in the order of the
29 cost of a call like gettimeofday(3)
30
31
32 Event recording code is designed to remain active in your program at
33 all times. Unlike typical printf(3) messages, events recorded by
34 record() are not generally intended to be seen immediately, but rather
35 to be shown laster, for example in case of crash. See recorder_dump(3).
36 Formatting only happens when the message is actually printed.
37
38
39 Events can also be traced on a per-recorder basis. In that case, the
40 record() and record_fast() functions will immediately format their out‐
41 put. See recorder_set_trace(3)
42
43
44 Automatic end of line
45 Event records are always printed on an individual line. It is not nec‐
46 essary to add a \n character at the end of the format string. If one is
47 present, it will have no effect.
48
49 record(my_recorder, "Hello");
50 record(my_recorder, "World0);
51
52
53 The use of \n at other positions in the string is possible and has the
54 usual effect.
55
56
57 Formatting character strings: %s and %+s
58 Since formatting an event may happen at an unknown time after its
59 recording, the %s and S formats are treated like %p unless formatting
60 happens as part of tracing. If you are passing a character string that
61 is known to be constant, or at least still valid when it will be for‐
62 matted, then you can use the %+s format instead.
63
64 const char *name[2] = { "false", "true" };
65 record(my_recorder, "Value %d is %+s", value, name[!!value]);
66
67
68
69 Extended format characters
70 It is possible to configure additional format characters. See
71 recorder_configure_type. When this function is used, format strings
72 may deviate notably from the printf(3) standard, or may conflict with
73 other extensions to that standard.
74
75
76
78 The return value is the index of the event that was recorded. This
79 value is rarely useful and can generally be ignored.
80
81
82
84 The program below records its input arguments, and crashes if passed
85 crash as the first command-line argument.
86
87 #include <recorder/recorder.h>
88 #include <string.h>
89
90 RECORDER(program_args, 32, "Program command-line arguments");
91 int main(int argc, char **argv)
92 {
93 int a;
94 recorder_dump_on_common_signals(0, 0);
95 for (a = 0; a < argc; a++)
96 record(program_args, "Argument %d is %+s", a, argv[a]);
97
98 if (argc >= 2 && strcmp(argv[1], "crash") == 0)
99 {
100 char *ptr = NULL;
101 strcpy(ptr, argv[1]);
102 }
103 }
104
105 When a crash occurs, previously recorded events are printed out on the
106 console.
107
108
109 The program below is an instrumented version of the classical recursive
110 Fibonacci computation. It uses several recorders corresponding to dif‐
111 ferent types of events, and activates warnings and errors in a way that
112 can be configured by setting an environment variable.
113
114 #include <recorder/recorder.h>
115 #include <string.h>
116 #include <stdio.h>
117 #include <stdlib.h>
118
119 RECORDER(fib_main, 32, "Loops in fib function");
120 RECORDER(fib_loops, 32, "Loops in fib function");
121 RECORDER(fib_warning, 32, "Warnings in fib function");
122 RECORDER(fib_error, 32, "Errors in fib function");
123
124 int fib(int n)
125 {
126 if (n <= 1) {
127 if (n < 0)
128 record(fib_error, "fib is undefined for negative value %d", n);
129 return n;
130 }
131 record(fib_loops, "Computing fib(%d)", n);
132 int result = fib(n-1) + fib(n-2);
133 record(fib_loops, "Computed fib(%d) = %d", n, result);
134 return result;
135 }
136
137 int main(int argc, char **argv)
138 {
139 int a;
140 recorder_dump_on_common_signals(0, 0);
141 recorder_trace_set(".*_warning=35 .*_error");
142 recorder_trace_set(getenv("FIB_TRACES"));
143 for (a = 1; a < argc; a++) {
144 int n = atoi(argv[a]);
145 if (n >= RECORDER_TRACE(fib_warning))
146 record(fib_warning, "Computing for %d may take a while", n);
147 printf("fib(%d) = %d0, n, fib(n));
148 if (n >= RECORDER_TRACE(fib_warning))
149 record(fib_warning, "Computation for %d finally completed", n);
150 }
151 }
152
153 This program will produce an output similar to the following:
154
155 % fib 1 2 3 4 10 20 30 35 10 40 -1
156 fib(1) = 1
157 fib(2) = 1
158 fib(3) = 2
159 fib(4) = 3
160 fib(10) = 55
161 fib(20) = 6765
162 fib(30) = 832040
163 [2714667 0.177725] fib_warning: Computing for 35 may take a while
164 fib(35) = 9227465
165 [32575370 1.859156] fib_warning: Computation for 35 finally completed
166 fib(10) = 55
167 [32575547 1.859171] fib_warning: Computing for 40 may take a while
168 fib(40) = 102334155
169 [363735828 20.527882] fib_warning: Computation for 40 finally completed
170 [363735829 20.527887] fib_error: fib is undefined for negative value -1
171 fib(-1) = -1
172 The first column in trace outputs is the number of events that were
173 recorded. THe second column is the time in seconds since the program
174 started.
175
176
177 The same program can also be run with additional tracing or warnings,
178 for example:
179
180 % FIB_TRACES="recorder_location fib_loops fib_warning=3" /tmp/fib 3 4
181 /tmp/fib.c:33:[82 0.000496] fib_warning: Computing for 3 may take a while
182 /tmp/fib.c:18:[83 0.000561] fib_loops: Computing fib(3)
183 /tmp/fib.c:18:[84 0.000570] fib_loops: Computing fib(2)
184 /tmp/fib.c:20:[85 0.000575] fib_loops: Computed fib(2) = 1
185 /tmp/fib.c:20:[86 0.000581] fib_loops: Computed fib(3) = 2
186 fib(3) = 2
187 /tmp/fib.c:36:[87 0.000590] fib_warning: Computation for 3 finally completed
188 /tmp/fib.c:33:[88 0.000596] fib_warning: Computing for 4 may take a while
189 /tmp/fib.c:18:[89 0.000601] fib_loops: Computing fib(4)
190 /tmp/fib.c:18:[90 0.000607] fib_loops: Computing fib(3)
191 /tmp/fib.c:18:[91 0.000612] fib_loops: Computing fib(2)
192 /tmp/fib.c:20:[92 0.000619] fib_loops: Computed fib(2) = 1
193 /tmp/fib.c:20:[93 0.000625] fib_loops: Computed fib(3) = 2
194 /tmp/fib.c:18:[94 0.000664] fib_loops: Computing fib(2)
195 /tmp/fib.c:20:[95 0.000707] fib_loops: Computed fib(2) = 1
196 /tmp/fib.c:20:[96 0.000724] fib_loops: Computed fib(4) = 3
197 fib(4) = 3
198 /tmp/fib.c:36:[97 0.000741] fib_warning: Computation for 4 finally completed
199
200
201
203 There is a limit to the number of arguments that can be passed to
204 record() and record_fast(). As of version 1.0, the maximum number is
205 12. If that number is exceeded, the compilation error message is not
206 friendly.
207
208
209 Bugs should be reported using https://github.com/c3d/recorder/issues.
210
211
212
214 RECORDER_DEFINE(3), RECORDER_DECLARE(3)
215 recorder_trace_set(3) RECORDER_TRACE(3)
216 recorder_dump(3), recorder_dump_for(3),
217 recorder_configure_output(3), recorder_configure_show(3)
218 recorder_configure_format(3), recorder_configure_type(3)
219
220
221 Additional documentation and tutorials can be found at
222 https://github.com/c3d/recorder.
223
224
225
227 Written by Christophe de Dinechin
228
229
230
2311.0 2019-03-09 record(3)