]> git.proxmox.com Git - mirror_lxc.git/blob - src/lxc/log.h
Merge pull request #1169 from brauner/2016-09-04/fix_syslog
[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
38 #include "conf.h"
39
40 #ifndef O_CLOEXEC
41 #define O_CLOEXEC 02000000
42 #endif
43
44 #ifndef F_DUPFD_CLOEXEC
45 #define F_DUPFD_CLOEXEC 1030
46 #endif
47
48 #define LXC_LOG_PREFIX_SIZE 32
49 #define LXC_LOG_BUFFER_SIZE 1024
50
51 /* This attribute is required to silence clang warnings */
52 #if defined(__GNUC__)
53 #define ATTR_UNUSED __attribute__ ((unused))
54 #else
55 #define ATTR_UNUSED
56 #endif
57
58 /* predefined lxc log priorities. */
59 enum lxc_loglevel {
60 LXC_LOG_PRIORITY_TRACE,
61 LXC_LOG_PRIORITY_DEBUG,
62 LXC_LOG_PRIORITY_INFO,
63 LXC_LOG_PRIORITY_NOTICE,
64 LXC_LOG_PRIORITY_WARN,
65 LXC_LOG_PRIORITY_ERROR,
66 LXC_LOG_PRIORITY_CRIT,
67 LXC_LOG_PRIORITY_ALERT,
68 LXC_LOG_PRIORITY_FATAL,
69 LXC_LOG_PRIORITY_NOTSET,
70 };
71
72 /* location information of the logging event */
73 struct lxc_log_locinfo {
74 const char *file;
75 const char *func;
76 int line;
77 };
78
79 #define LXC_LOG_LOCINFO_INIT \
80 { .file = __FILE__, .func = __func__, .line = __LINE__ }
81
82 /* brief logging event object */
83 struct lxc_log_event {
84 const char* category;
85 int priority;
86 struct timeval timestamp;
87 struct lxc_log_locinfo *locinfo;
88 const char *fmt;
89 va_list *vap;
90 };
91
92 /* log appender object */
93 struct lxc_log_appender {
94 const char* name;
95 int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
96
97 /*
98 * appenders can be stacked
99 */
100 struct lxc_log_appender *next;
101 };
102
103 /* log category object */
104 struct lxc_log_category {
105 const char *name;
106 int priority;
107 struct lxc_log_appender *appender;
108 const struct lxc_log_category *parent;
109 };
110
111 #ifndef NO_LXC_CONF
112 extern int lxc_log_use_global_fd;
113 #endif
114
115 /*
116 * Returns true if the chained priority is equal to or higher than
117 * given priority.
118 */
119 static inline int
120 lxc_log_priority_is_enabled(const struct lxc_log_category* category,
121 int priority)
122 {
123 while (category->priority == LXC_LOG_PRIORITY_NOTSET &&
124 category->parent)
125 category = category->parent;
126
127 int cmp_prio = category->priority;
128 #ifndef NO_LXC_CONF
129 if (!lxc_log_use_global_fd && current_config &&
130 current_config->loglevel != LXC_LOG_PRIORITY_NOTSET)
131 cmp_prio = current_config->loglevel;
132 #endif
133
134 return priority >= cmp_prio;
135 }
136
137 /*
138 * converts a priority to a literal string
139 */
140 static inline const char* lxc_log_priority_to_string(int priority)
141 {
142 switch (priority) {
143 case LXC_LOG_PRIORITY_TRACE: return "TRACE";
144 case LXC_LOG_PRIORITY_DEBUG: return "DEBUG";
145 case LXC_LOG_PRIORITY_INFO: return "INFO";
146 case LXC_LOG_PRIORITY_NOTICE: return "NOTICE";
147 case LXC_LOG_PRIORITY_WARN: return "WARN";
148 case LXC_LOG_PRIORITY_ERROR: return "ERROR";
149 case LXC_LOG_PRIORITY_CRIT: return "CRIT";
150 case LXC_LOG_PRIORITY_ALERT: return "ALERT";
151 case LXC_LOG_PRIORITY_FATAL: return "FATAL";
152 default:
153 return "NOTSET";
154 }
155 }
156
157 static inline const char* lxc_syslog_priority_to_string(int priority)
158 {
159 switch (priority) {
160 case LOG_DAEMON: return "daemon";
161 case LOG_LOCAL0: return "local0";
162 case LOG_LOCAL1: return "local1";
163 case LOG_LOCAL2: return "local2";
164 case LOG_LOCAL3: return "local3";
165 case LOG_LOCAL4: return "local4";
166 case LOG_LOCAL5: return "local5";
167 case LOG_LOCAL6: return "local6";
168 case LOG_LOCAL7: return "local7";
169 default:
170 return "NOTSET";
171 }
172 }
173
174 /*
175 * converts a literal priority to an int
176 */
177 static inline int lxc_log_priority_to_int(const char* name)
178 {
179 if (!strcasecmp("TRACE", name)) return LXC_LOG_PRIORITY_TRACE;
180 if (!strcasecmp("DEBUG", name)) return LXC_LOG_PRIORITY_DEBUG;
181 if (!strcasecmp("INFO", name)) return LXC_LOG_PRIORITY_INFO;
182 if (!strcasecmp("NOTICE", name)) return LXC_LOG_PRIORITY_NOTICE;
183 if (!strcasecmp("WARN", name)) return LXC_LOG_PRIORITY_WARN;
184 if (!strcasecmp("ERROR", name)) return LXC_LOG_PRIORITY_ERROR;
185 if (!strcasecmp("CRIT", name)) return LXC_LOG_PRIORITY_CRIT;
186 if (!strcasecmp("ALERT", name)) return LXC_LOG_PRIORITY_ALERT;
187 if (!strcasecmp("FATAL", name)) return LXC_LOG_PRIORITY_FATAL;
188
189 return LXC_LOG_PRIORITY_NOTSET;
190 }
191
192 static inline int lxc_syslog_priority_to_int(const char* name)
193 {
194 if (!strcasecmp("daemon", name)) return LOG_DAEMON;
195 if (!strcasecmp("local0", name)) return LOG_LOCAL0;
196 if (!strcasecmp("local1", name)) return LOG_LOCAL1;
197 if (!strcasecmp("local2", name)) return LOG_LOCAL2;
198 if (!strcasecmp("local3", name)) return LOG_LOCAL3;
199 if (!strcasecmp("local4", name)) return LOG_LOCAL4;
200 if (!strcasecmp("local5", name)) return LOG_LOCAL5;
201 if (!strcasecmp("local6", name)) return LOG_LOCAL6;
202 if (!strcasecmp("local7", name)) return LOG_LOCAL7;
203
204 return -EINVAL;
205 }
206
207 static inline void
208 __lxc_log_append(const struct lxc_log_appender *appender,
209 struct lxc_log_event* event)
210 {
211 va_list va, *va_keep;
212 va_keep = event->vap;
213
214 while (appender) {
215 va_copy(va, *va_keep);
216 event->vap = &va;
217 appender->append(appender, event);
218 appender = appender->next;
219 va_end(va);
220 }
221 }
222
223 static inline void
224 __lxc_log(const struct lxc_log_category* category,
225 struct lxc_log_event* event)
226 {
227 while (category) {
228 __lxc_log_append(category->appender, event);
229 category = category->parent;
230 }
231 }
232
233 /*
234 * Helper macro to define log functions.
235 */
236 #define lxc_log_priority_define(acategory, PRIORITY) \
237 \
238 ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \
239 const char *, ...) __attribute__ ((format (printf, 2, 3))); \
240 \
241 ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
242 const char* format, ...) \
243 { \
244 if (lxc_log_priority_is_enabled(acategory, \
245 LXC_LOG_PRIORITY_##PRIORITY)) { \
246 struct lxc_log_event evt = { \
247 .category = (acategory)->name, \
248 .priority = LXC_LOG_PRIORITY_##PRIORITY, \
249 .fmt = format, \
250 .locinfo = locinfo \
251 }; \
252 va_list va_ref; \
253 \
254 gettimeofday(&evt.timestamp, NULL); \
255 \
256 va_start(va_ref, format); \
257 evt.vap = &va_ref; \
258 __lxc_log(acategory, &evt); \
259 va_end(va_ref); \
260 } \
261 }
262
263 /*
264 * Helper macro to define and use static categories.
265 */
266 #define lxc_log_category_define(name, parent) \
267 extern struct lxc_log_category lxc_log_category_##parent; \
268 struct lxc_log_category lxc_log_category_##name = { \
269 #name, \
270 LXC_LOG_PRIORITY_NOTSET, \
271 NULL, \
272 &lxc_log_category_##parent \
273 };
274
275 #define lxc_log_define(name, parent) \
276 lxc_log_category_define(name, parent) \
277 \
278 lxc_log_priority_define(&lxc_log_category_##name, TRACE) \
279 lxc_log_priority_define(&lxc_log_category_##name, DEBUG) \
280 lxc_log_priority_define(&lxc_log_category_##name, INFO) \
281 lxc_log_priority_define(&lxc_log_category_##name, NOTICE) \
282 lxc_log_priority_define(&lxc_log_category_##name, WARN) \
283 lxc_log_priority_define(&lxc_log_category_##name, ERROR) \
284 lxc_log_priority_define(&lxc_log_category_##name, CRIT) \
285 lxc_log_priority_define(&lxc_log_category_##name, ALERT) \
286 lxc_log_priority_define(&lxc_log_category_##name, FATAL)
287
288 #define lxc_log_category_priority(name) \
289 (lxc_log_priority_to_string(lxc_log_category_##name.priority))
290
291 /*
292 * top categories
293 */
294 #define TRACE(format, ...) do { \
295 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
296 LXC_TRACE(&locinfo, format, ##__VA_ARGS__); \
297 } while (0)
298
299 #define DEBUG(format, ...) do { \
300 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
301 LXC_DEBUG(&locinfo, format, ##__VA_ARGS__); \
302 } while (0)
303
304 #define INFO(format, ...) do { \
305 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
306 LXC_INFO(&locinfo, format, ##__VA_ARGS__); \
307 } while (0)
308
309 #define NOTICE(format, ...) do { \
310 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
311 LXC_NOTICE(&locinfo, format, ##__VA_ARGS__); \
312 } while (0)
313
314 #define WARN(format, ...) do { \
315 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
316 LXC_WARN(&locinfo, format, ##__VA_ARGS__); \
317 } while (0)
318
319 #define ERROR(format, ...) do { \
320 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
321 LXC_ERROR(&locinfo, format, ##__VA_ARGS__); \
322 } while (0)
323
324 #define CRIT(format, ...) do { \
325 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
326 LXC_CRIT(&locinfo, format, ##__VA_ARGS__); \
327 } while (0)
328
329 #define ALERT(format, ...) do { \
330 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
331 LXC_ALERT(&locinfo, format, ##__VA_ARGS__); \
332 } while (0)
333
334 #define FATAL(format, ...) do { \
335 struct lxc_log_locinfo locinfo = LXC_LOG_LOCINFO_INIT; \
336 LXC_FATAL(&locinfo, format, ##__VA_ARGS__); \
337 } while (0)
338
339
340
341 #define SYSERROR(format, ...) do { \
342 ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \
343 } while (0)
344
345 extern int lxc_log_fd;
346
347 extern int lxc_log_init(const char *name, const char *file,
348 const char *priority, const char *prefix, int quiet,
349 const char *lxcpath);
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