]> git.proxmox.com Git - mirror_lxc.git/blame - src/lxc/log.h
API: expose function lxc_log_init
[mirror_lxc.git] / src / lxc / log.h
CommitLineData
e0b4037d
DL
1/*
2 * lxc: linux Container library
3 *
4 * (C) Copyright IBM Corp. 2007, 2008
5 *
6 * Authors:
9afe19d6 7 * Daniel Lezcano <daniel.lezcano at free.fr>
e0b4037d
DL
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
250b1eec 22 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e0b4037d 23 */
f1a4a029
ÇO
24#ifndef __LXC_LOG_H
25#define __LXC_LOG_H
0ad19a3f 26
9f4f402a
ÇO
27#include "config.h"
28
76d0127f 29#include <errno.h>
cb8c5720
CLG
30#include <stdarg.h>
31#include <stdio.h>
32#include <sys/time.h>
33#include <string.h>
65441ac9 34#include <strings.h>
fabf7361 35#include <stdbool.h>
76d0127f 36#include <syslog.h>
c57dbb96 37#include <time.h>
cb8c5720 38
858377e4
SH
39#include "conf.h"
40
eabbb2f0
MN
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
ed408e66 50#define LXC_LOG_BUFFER_SIZE 4096
eabbb2f0 51
13aad0ae
SG
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
76d0127f 59/* predefined lxc log priorities. */
4a85ce2a 60enum lxc_loglevel {
cb8c5720
CLG
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 */
74struct 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 */
84struct lxc_log_event {
85 const char* category;
86 int priority;
c57dbb96 87 struct timespec timestamp;
cb8c5720
CLG
88 struct lxc_log_locinfo *locinfo;
89 const char *fmt;
5fd8380b 90 va_list *vap;
cb8c5720
CLG
91};
92
93/* log appender object */
94struct lxc_log_appender {
95 const char* name;
5fd8380b 96 int (*append)(const struct lxc_log_appender *, struct lxc_log_event *);
cb8c5720
CLG
97
98 /*
99 * appenders can be stacked
100 */
101 struct lxc_log_appender *next;
102};
103
104/* log category object */
105struct 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
858377e4
SH
112#ifndef NO_LXC_CONF
113extern int lxc_log_use_global_fd;
114#endif
115
cb8c5720
CLG
116/*
117 * Returns true if the chained priority is equal to or higher than
118 * given priority.
119 */
120static inline int
121lxc_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
858377e4
SH
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;
cb8c5720
CLG
136}
137
138/*
139 * converts a priority to a literal string
140 */
141static 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}
76d0127f
CB
157
158static 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
cb8c5720
CLG
175/*
176 * converts a literal priority to an int
177 */
178static 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
76d0127f
CB
193static 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
cb8c5720
CLG
208static inline void
209__lxc_log_append(const struct lxc_log_appender *appender,
5fd8380b 210 struct lxc_log_event* event)
cb8c5720 211{
5fd8380b
MN
212 va_list va, *va_keep;
213 va_keep = event->vap;
214
cb8c5720 215 while (appender) {
5fd8380b
MN
216 va_copy(va, *va_keep);
217 event->vap = &va;
cb8c5720
CLG
218 appender->append(appender, event);
219 appender = appender->next;
5fd8380b 220 va_end(va);
cb8c5720
CLG
221 }
222}
223
224static inline void
225__lxc_log(const struct lxc_log_category* category,
5fd8380b 226 struct lxc_log_event* event)
cb8c5720
CLG
227{
228 while (category) {
229 __lxc_log_append(category->appender, event);
230 category = category->parent;
231 }
232}
233
234/*
e6a19d26 235 * Helper macro to define log functions.
cb8c5720
CLG
236 */
237#define lxc_log_priority_define(acategory, PRIORITY) \
238 \
13aad0ae 239ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo *, \
cb8c5720
CLG
240 const char *, ...) __attribute__ ((format (printf, 2, 3))); \
241 \
13aad0ae 242ATTR_UNUSED static inline void LXC_##PRIORITY(struct lxc_log_locinfo* locinfo, \
cb8c5720
CLG
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 }; \
5fd8380b 253 va_list va_ref; \
cb8c5720 254 \
c57dbb96
CB
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); \
cb8c5720 259 \
5fd8380b
MN
260 va_start(va_ref, format); \
261 evt.vap = &va_ref; \
cb8c5720 262 __lxc_log(acategory, &evt); \
5fd8380b 263 va_end(va_ref); \
cb8c5720
CLG
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 */
cb8c5720
CLG
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 { \
69c3910d 346 ERROR("%s - " format, strerror(errno), ##__VA_ARGS__); \
cb8c5720
CLG
347} while (0)
348
641c20a6
CLG
349extern int lxc_log_fd;
350
858377e4 351extern int lxc_log_set_file(int *fd, const char *fname);
64c57ea1
BD
352extern int lxc_log_syslog(int facility);
353extern void lxc_log_enable_syslog(void);
858377e4 354extern int lxc_log_set_level(int *dest, int level);
ab1bf971 355extern void lxc_log_set_prefix(const char *prefix);
9ea87d5d 356extern const char *lxc_log_get_file(void);
ab1bf971 357extern int lxc_log_get_level(void);
fabf7361 358extern bool lxc_log_has_valid_level(void);
ab1bf971 359extern const char *lxc_log_get_prefix(void);
6edbfc86 360extern void lxc_log_options_no_override();
0ad19a3f 361#endif