1QBLOG.H(3) libqb Programmer's Manual QBLOG.H(3)
2
3
4
6 qblog.h - The logging API provides four main parts (basics, filtering,
7 threading & blackbox).
8
9
11 #include <qb/qblog.h>
12
14 The idea behind this logging system is not to be prescriptive but to
15 provide a set of tools to help the developer achieve what they want
16 quickly and easily.
17
18 Basic logging API.
19
20 Call qb_log() to generate a log message. Then to write the message
21 somewhere meaningful call qb_log_ctl() to configure the targets.
22
23 Simplest possible use:
24
25 main() {
26 qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
27 // ...
28 qb_log(LOG_WARNING, "watch out");
29 // ...
30 qb_log_fini();
31 }
32
33
34 Configuring log targets.
35
36 A log target can be syslog, stderr, the blackbox, stdout, or a text
37 file. By default, only syslog is enabled. While this is usual for dae‐
38 mons, it is rarely appropriate for ordinary programs, which should dis‐
39 able it when other targets (see below) are to be used:
40
41 qb_log_ctl(B_LOG_SYSLOG, QB_LOG_CONF_ENABLED, QB_FALSE);
42
43
44 To enable a target do the following:
45
46 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
47
48
49 syslog, stderr, the blackbox, and stdout are static (they don't need to
50 be created, just enabled or disabled). However, you can open multiple
51 logfiles (falling within inclusive range QB_LOG_TARGET_DYNAMIC_START up
52 to QB_LOG_TARGET_DYNAMIC_END). To do this, use the following code:
53
54 mytarget = qb_log_file_open("/var/log/mylogfile");
55 qb_log_ctl(mytarget, QB_LOG_CONF_ENABLED, QB_TRUE);
56
57
58 Once your targets are enabled/opened, you can configure them as fol‐
59 lows: Configure the size of blackbox:
60
61 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
62
63
64 Make logging to file threaded:
65
66 qb_log_ctl(mytarget, QB_LOG_CONF_THREADED, QB_TRUE);
67
68
69 Sometimes, syslog daemons are (pre)configured to filter messages not
70 exceeding a particular priority. When this happens to be the logging
71 target, the designated priority of the message is passed along un‐
72 changed, possibly resulting in message loss. For messages up to LOG_DE‐
73 BUG importance, this can be worked around by proportionally bumping the
74 priorities to be passed to syslog (here, the step is such that LOG_DE‐
75 BUG gets promoted to LOG_INFO):
76
77 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_PRIORITY_BUMP,
78 LOG_INFO - LOG_DEBUG);
79
80
81 To ensure all logs to file targets are fsync'ed (new messages expressly
82 transferred to the storage device as they keep coming, otherwise de‐
83 faults to QB_FALSE):
84
85 qb_log_ctl(mytarget, QB_LOG_CONF_FILE_SYNC, QB_TRUE);
86
87
88 Filtering messages.
89
90 To have more power over what log messages go to which target you can
91 apply filters to the targets. What happens is the desired callsites
92 have the correct bit set. Then when the log message is generated it
93 gets sent to the targets based on which bit is set in the callsite's
94 "target" bitmap. Messages can be filtered based on the:
95
96 So to make all logs from evil_function() go to stderr, do the follow‐
97 ing:
98
99 qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
100 QB_LOG_FILTER_FUNCTION, "evil_function", LOG_TRACE);
101
102
103 So to make all logs from totem* (with a priority <= LOG_INFO) go to
104 stderr, do the following:
105
106 qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
107 QB_LOG_FILTER_FILE, "totem", LOG_INFO);
108
109
110 So to make all logs with the substring "ringbuffer" go to stderr, do
111 the following:
112
113 qb_log_filter_ctl(QB_LOG_STDERR, QB_LOG_FILTER_ADD,
114 QB_LOG_FILTER_FORMAT, "ringbuffer", LOG_TRACE);
115
116
117 Thread safe non-blocking logging.
118
119 Logging is only thread safe when threaded logging is in use. If you
120 plan on logging from multiple threads, you must initialize libqb's log‐
121 ger thread and use qb_log_filter_ctl to set the QB_LOG_CONF_THREADED
122 flag on all the logging targets in use.
123
124 To achieve non-blocking logging, so that any calls to write() or sys‐
125 log() will not hold up your program, you can use threaded logging as
126 well.
127
128 Threaded logging use:
129
130 main() {
131 qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
132 qb_log_ctl(QB_LOG_SYSLOG, QB_LOG_CONF_THREADED, QB_TRUE);
133 // ...
134 daemonize();
135 // call this after you fork()
136 qb_log_thread_start();
137 // ...
138 qb_log(LOG_WARNING, "watch out");
139 // ...
140 qb_log_fini();
141 }
142
143
144 A blackbox for in-field diagnosis.
145
146 This stores log messages in a ringbuffer so they can be written to file
147 if the program crashes (you will need to catch SIGSEGV). These can then
148 be easily printed out later.
149
150 Blackbox usage:
151
152 static void sigsegv_handler(int sig)
153 {
154 (void)signal (SIGSEGV, SIG_DFL);
155 qb_log_blackbox_write_to_file("simple-log.fdata");
156 qb_log_fini();
157 raise(SIGSEGV);
158 }
159
160 main() {
161
162 signal(SIGSEGV, sigsegv_handler);
163
164 qb_log_init("simple-log", LOG_DAEMON, LOG_INFO);
165 qb_log_filter_ctl(QB_LOG_BLACKBOX, QB_LOG_FILTER_ADD,
166 QB_LOG_FILTER_FILE, "*", LOG_DEBUG);
167 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_SIZE, 1024*10);
168 qb_log_ctl(QB_LOG_BLACKBOX, QB_LOG_CONF_ENABLED, QB_TRUE);
169 // ...
170 qb_log(LOG_WARNING, "watch out");
171 // ...
172 qb_log_fini();
173 }
174
175
176 Tagging messages.
177
178 You can tag messages using the second argument to qb_logt() or by using
179 qb_log_filter_ctl(). This can be used to add feature or sub-system in‐
180 formation to the logs.
181
182 const char* my_tags_stringify(uint32_t tags) {
183 if (qb_bit_is_set(tags, QB_LOG_TAG_LIBQB_MSG_BIT) {
184 return "libqb";
185 } else if (tags == 3) {
186 return "three";
187 } else {
188 return "MAIN";
189 }
190 }
191 main() {
192 // ...
193 qb_log_tags_stringify_fn_set(my_tags_stringify);
194 qb_log_format_set(QB_LOG_STDERR, "[%5g] %p %b");
195 // ...
196 qb_logt(LOG_INFO, 3, "hello");
197 qb_logt(LOG_INFO, 0, "hello");
198 }
199
200
201 The code above will produce:
202
203 [libqb] some message
204 [three] info hello
205 [MAIN ] info hello
206
207
209 the blackbox is not enabled by default.
210
212 qb_log_filter_fn_set(3), qb_log_from_external_source_va2(3),
213 qb_log_thread_start(3), qb_log_target_user_data_get(3),
214 qb_log_tags_stringify_fn_set(3), qb_log_file_reopen(3), qb_log_fini(3),
215 qb_log_callsites_dump(3), qb_log_ctl2(3),
216 qb_log_target_user_data_set(3), qb_log_target_format(3),
217 qb_log_thread_priority_set(3), qb_log_facility2int(3),
218 qb_log_callsites_register(3), qb_log_filter_ctl2(3),
219 qb_log_file_close(3), qb_log_format_set(3), qb_log_real_(3),
220 qb_log_from_external_source_va(3), qb_log_callsite_get(3),
221 qb_log_blackbox_write_to_file(3), qb_log_real_va_(3),
222 qb_log_from_external_source(3), qb_log_blackbox_print_from_file(3),
223 qb_log_facility2str(3), qb_log_callsite_get2(3), qb_log_ctl(3),
224 qb_log_filter_ctl(3), qb_log_custom_close(3), qb_log_init(3),
225 qb_log_file_open(3), qb_log_custom_open(3)
226
228 Copyright (c) 2017 Red Hat, Inc.
229
230
231
232LIBQB 2023-07-21 QBLOG.H(3)