]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/log.h
API: expose function lxc_log_init
[mirror_lxc.git] / src / lxc / log.h
1 /*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
7 * Daniel Lezcano <daniel.lezcano at free.fr>
8 * Cedric Le Goater <legoater@free.fr>
9 *
10 * This library is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU Lesser General Public
12 * License as published by the Free Software Foundation; either
13 * version 2.1 of the License, or (at your option) any later version.
14 *
15 * This library is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * Lesser General Public License for more details.
19 *
20 * You should have received a copy of the GNU Lesser General Public
21 * License along with this library; if not, write to the Free Software
22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 */
24 #ifndef __LXC_LOG_H
25 #define __LXC_LOG_H
26
27 #include "config.h"
28
29 #include <errno.h>
30 #include <stdarg.h>
31 #include <stdio.h>
32 #include <sys/time.h>
33 #include <string.h>
34 #include <strings.h>
35 #include <stdbool.h>
36 #include <syslog.h>
37 #include <time.h>
38
39 #include "conf.h"
40
41 #ifndef O_CLOEXEC
42 #define O_CLOEXEC 02000000
43 #endif
44
45 #ifndef F_DUPFD_CLOEXEC
46 #define F_DUPFD_CLOEXEC 1030
47 #endif
48
49 #define LXC_LOG_PREFIX_SIZE 32
50 #define LXC_LOG_BUFFER_SIZE 4096
51
52 /* This attribute is required to silence clang warnings */
53 #if defined(__GNUC__)
54 #define ATTR_UNUSED __attribute__ ((unused))
55 #else
56 #define ATTR_UNUSED
57 #endif
58
59 /* predefined lxc log priorities. */
60 enum lxc_loglevel {
61 LXC_LOG_PRIORITY_TRACE,
62 LXC_LOG_PRIORITY_DEBUG,
63 LXC_LOG_PRIORITY_INFO,
64 LXC_LOG_PRIORITY_NOTICE,
65 LXC_LOG_PRIORITY_WARN,
66 LXC_LOG_PRIORITY_ERROR,
67 LXC_LOG_PRIORITY_CRIT,
68 LXC_LOG_PRIORITY_ALERT,
69 LXC_LOG_PRIORITY_FATAL,
70 LXC_LOG_PRIORITY_NOTSET,
71 };
72
73 /* location information of the logging event */
74 struct lxc_log_locinfo {
75 const char *file;
76 const char *func;
77 int line;
78 };
79
80 #define LXC_LOG_LOCINFO_INIT \
81 { .file = __FILE__, .func = __func__, .line = __LINE__ }
82
83 /* brief logging event object */
84 struct lxc_log_event {
85 const char* category;
86 int priority;
87 struct timespec timestamp;
88 struct lxc_log_locinfo *locinfo;
89 const char *fmt;
90 va_list *vap;
91 };
92
93 /* log appender object */
94 struct lxc_log_appender {
95 const char* name;
96 int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
97
98 /*
99 * appenders can be stacked
100 */
101 struct lxc_log_appender *next;
102 };
103
104 /* log category object */
105 struct lxc_log_category {
106 const char *name;
107 int priority;
108 struct lxc_log_appender *appender;
109 const struct lxc_log_category *parent;
110 };
111
112 #ifndef NO_LXC_CONF
113 extern int lxc_log_use_global_fd;
114 #endif
115
116 /*
117 * Returns true if the chained priority is equal to or higher than
118 * given priority.
119 */
120 static inline int
121 lxc_log_priority_is_enabled(const struct lxc_log_category* category,
122 int priority)
123 {
124 while (category->priority == LXC_LOG_PRIORITY_NOTSET &&
125 category->parent)
126 category = category->parent;
127
128 int cmp_prio = category->priority;
129 #ifndef NO_LXC_CONF
130 if (!lxc_log_use_global_fd && current_config &&
131 current_config->loglevel != LXC_LOG_PRIORITY_NOTSET)
132 cmp_prio = current_config->loglevel;
133 #endif
134
135 return priority >= cmp_prio;
136 }
137
138 /*
139 * converts a priority to a literal string
140 */
141 static inline const char* lxc_log_priority_to_string(int priority)
142 {
143 switch (priority) {
144 case LXC_LOG_PRIORITY_TRACE: return "TRACE";
145 case LXC_LOG_PRIORITY_DEBUG: return "DEBUG";
146 case LXC_LOG_PRIORITY_INFO: return "INFO";
147 case LXC_LOG_PRIORITY_NOTICE: return "NOTICE";
148 case LXC_LOG_PRIORITY_WARN: return "WARN";
149 case LXC_LOG_PRIORITY_ERROR: return "ERROR";
150 case LXC_LOG_PRIORITY_CRIT: return "CRIT";
151 case LXC_LOG_PRIORITY_ALERT: return "ALERT";
152 case LXC_LOG_PRIORITY_FATAL: return "FATAL";
153 default:
154 return "NOTSET";
155 }
156 }
157
158 static inline const char* lxc_syslog_priority_to_string(int priority)
159 {
160 switch (priority) {
161 case LOG_DAEMON: return "daemon";
162 case LOG_LOCAL0: return "local0";
163 case LOG_LOCAL1: return "local1";
164 case LOG_LOCAL2: return "local2";
165 case LOG_LOCAL3: return "local3";
166 case LOG_LOCAL4: return "local4";
167 case LOG_LOCAL5: return "local5";
168 case LOG_LOCAL6: return "local6";
169 case LOG_LOCAL7: return "local7";
170 default:
171 return "NOTSET";
172 }
173 }
174
175 /*
176 * converts a literal priority to an int
177 */
178 static inline int lxc_log_priority_to_int(const char* name)
179 {
180 if (!strcasecmp("TRACE", name)) return LXC_LOG_PRIORITY_TRACE;
181 if (!strcasecmp("DEBUG", name)) return LXC_LOG_PRIORITY_DEBUG;
182 if (!strcasecmp("INFO", name)) return LXC_LOG_PRIORITY_INFO;
183 if (!strcasecmp("NOTICE", name)) return LXC_LOG_PRIORITY_NOTICE;
184 if (!strcasecmp("WARN", name)) return LXC_LOG_PRIORITY_WARN;
185 if (!strcasecmp("ERROR", name)) return LXC_LOG_PRIORITY_ERROR;
186 if (!strcasecmp("CRIT", name)) return LXC_LOG_PRIORITY_CRIT;
187 if (!strcasecmp("ALERT", name)) return LXC_LOG_PRIORITY_ALERT;
188 if (!strcasecmp("FATAL", name)) return LXC_LOG_PRIORITY_FATAL;
189
190 return LXC_LOG_PRIORITY_NOTSET;
191 }
192
193 static inline int lxc_syslog_priority_to_int(const char* name)
194 {
195 if (!strcasecmp("daemon", name)) return LOG_DAEMON;
196 if (!strcasecmp("local0", name)) return LOG_LOCAL0;
197 if (!strcasecmp("local1", name)) return LOG_LOCAL1;
198 if (!strcasecmp("local2", name)) return LOG_LOCAL2;
199 if (!strcasecmp("local3", name)) return LOG_LOCAL3;
200 if (!strcasecmp("local4", name)) return LOG_LOCAL4;
201 if (!strcasecmp("local5", name)) return LOG_LOCAL5;
202 if (!strcasecmp("local6", name)) return LOG_LOCAL6;
203 if (!strcasecmp("local7", name)) return LOG_LOCAL7;
204
205 return -EINVAL;
206 }
207
208 static inline void
209 __lxc_log_append(const struct lxc_log_appender *appender,
210 struct lxc_log_event* event)
211 {
212 va_list va, *va_keep;
213 va_keep = event->vap;
214
215 while (appender) {
216 va_copy(va, *va_keep);
217 event->vap = &va;
218 appender->append(appender, event);
219 appender = appender->next;
220 va_end(va);
221 }
222 }
223
224 static inline void
225 __lxc_log(const struct lxc_log_category* category,
226 struct lxc_log_event* event)
227 {
228 while (category) {
229 __lxc_log_append(category->appender, event);
230 category = category->parent;
231 }
232 }
233
234 /*
235 * Helper macro to define log functions.
236 */
237 #define lxc_log_priority_define(acategory, PRIORITY) \
238 \
239 ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \
240 const char *, ...) __attribute__ ((format (printf, 2, 3))); \
241 \
242 ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
243 const char* format, ...) \
244 { \
245 if (lxc_log_priority_is_enabled(acategory, \
246 LXC_LOG_PRIORITY_##PRIORITY)) { \
247 struct lxc_log_event evt = { \
248 .category = (acategory)->name, \
249 .priority = LXC_LOG_PRIORITY_##PRIORITY, \
250 .fmt = format, \
251 .locinfo = locinfo \
252 }; \
253 va_list va_ref; \
254 \
255 /* clock_gettime() is explicitly marked as MT-Safe \
256 * without restrictions. So let's use it for our \
257 * logging stamps. */ \
258 clock_gettime(CLOCK_REALTIME, &evt.timestamp); \
259 \
260 va_start(va_ref, format); \
261 evt.vap = &va_ref; \
262 __lxc_log(acategory, &evt); \
263 va_end(va_ref); \
264 } \
265 }
266
267 /*
268 * Helper macro to define and use static categories.
269 */
270 #define lxc_log_category_define(name, parent) \
271 extern struct lxc_log_category lxc_log_category_##parent; \
272 struct lxc_log_category lxc_log_category_##name = { \
273 #name, \
274 LXC_LOG_PRIORITY_NOTSET, \
275 NULL, \
276 &lxc_log_category_##parent \
277 };
278
279 #define lxc_log_define(name, parent) \
280 lxc_log_category_define(name, parent) \
281 \
282 lxc_log_priority_define(&lxc_log_category_##name, TRACE) \
283 lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \
284 lxc_log_priority_define(&lxc_log_category_##name, INFO) \
285 lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \
286 lxc_log_priority_define(&lxc_log_category_##name, WARN) \
287 lxc_log_priority_define(&lxc_log_category_##name, ERROR) \
288 lxc_log_priority_define(&lxc_log_category_##name, CRIT) \
289 lxc_log_priority_define(&lxc_log_category_##name, ALERT) \
290 lxc_log_priority_define(&lxc_log_category_##name, FATAL)
291
292 #define lxc_log_category_priority(name) \
293 (lxc_log_priority_to_string(lxc_log_category_##name.priority))
294
295 /*
296 * top categories
297 */
298 #define TRACE(format, ...) do { \
299 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
300 LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \
301 } while (0)
302
303 #define DEBUG(format, ...) do { \
304 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
305 LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \
306 } while (0)
307
308 #define INFO(format, ...) do { \
309 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
310 LXC_INFO(&locinfo, format, ##__VA_ARGS__); \
311 } while (0)
312
313 #define NOTICE(format, ...) do { \
314 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
315 LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \
316 } while (0)
317
318 #define WARN(format, ...) do { \
319 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
320 LXC_WARN(&locinfo, format, ##__VA_ARGS__); \
321 } while (0)
322
323 #define ERROR(format, ...) do { \
324 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
325 LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \
326 } while (0)
327
328 #define CRIT(format, ...) do { \
329 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
330 LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \
331 } while (0)
332
333 #define ALERT(format, ...) do { \
334 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
335 LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \
336 } while (0)
337
338 #define FATAL(format, ...) do { \
339 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
340 LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \
341 } while (0)
342
343
344
345 #define SYSERROR(format, ...) do { \
346 ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \
347 } while (0)
348
349 extern int lxc_log_fd;
350
351 extern int lxc_log_set_file(int *fd, const char *fname);
352 extern int lxc_log_syslog(int facility);
353 extern void lxc_log_enable_syslog(void);
354 extern int lxc_log_set_level(int *dest, int level);
355 extern void lxc_log_set_prefix(const char *prefix);
356 extern const char *lxc_log_get_file(void);
357 extern int lxc_log_get_level(void);
358 extern bool lxc_log_has_valid_level(void);
359 extern const char *lxc_log_get_prefix(void);
360 extern void lxc_log_options_no_override();
361 #endif