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