]>
Commit | Line | Data |
---|---|---|
064af421 | 1 | /* |
c7981f8c | 2 | * Copyright (c) 2008, 2009, 2010, 2011 Nicira Networks. |
064af421 | 3 | * |
a14bc59f BP |
4 | * Licensed under the Apache License, Version 2.0 (the "License"); |
5 | * you may not use this file except in compliance with the License. | |
6 | * You may obtain a copy of the License at: | |
064af421 | 7 | * |
a14bc59f BP |
8 | * http://www.apache.org/licenses/LICENSE-2.0 |
9 | * | |
10 | * Unless required by applicable law or agreed to in writing, software | |
11 | * distributed under the License is distributed on an "AS IS" BASIS, | |
12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
13 | * See the License for the specific language governing permissions and | |
14 | * limitations under the License. | |
064af421 BP |
15 | */ |
16 | ||
17 | #ifndef VLOG_H | |
18 | #define VLOG_H 1 | |
19 | ||
20 | #include <limits.h> | |
21 | #include <stdarg.h> | |
22 | #include <stdbool.h> | |
23 | #include <time.h> | |
1c5a216a | 24 | #include "compiler.h" |
064af421 | 25 | #include "util.h" |
d295e8e9 | 26 | |
f4ade105 JG |
27 | #ifdef __cplusplus |
28 | extern "C" { | |
29 | #endif | |
064af421 | 30 | |
c7981f8c BP |
31 | /* Logging importance levels. |
32 | * | |
33 | * The following log levels, in descending order of importance, are enabled by | |
34 | * default: | |
35 | * | |
36 | * - EMER: Not currently used. | |
37 | * | |
38 | * - ERR: A high-level operation or a subsystem failed. Attention is | |
39 | * warranted. | |
40 | * | |
41 | * - WARN: A low-level operation failed, but higher-level subsystems may be | |
42 | * able to recover. | |
43 | * | |
44 | * - INFO: Information that may be useful in retrospect when investigating | |
45 | * a problem. | |
46 | * | |
47 | * The lowest log level is not enabled by default: | |
48 | * | |
49 | * - DBG: Information useful only to someone with intricate knowledge of the | |
50 | * system, or that would commonly cause too-voluminous log output. | |
51 | */ | |
064af421 BP |
52 | #define VLOG_LEVELS \ |
53 | VLOG_LEVEL(EMER, LOG_ALERT) \ | |
54 | VLOG_LEVEL(ERR, LOG_ERR) \ | |
55 | VLOG_LEVEL(WARN, LOG_WARNING) \ | |
56 | VLOG_LEVEL(INFO, LOG_NOTICE) \ | |
57 | VLOG_LEVEL(DBG, LOG_DEBUG) | |
58 | enum vlog_level { | |
59 | #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) VLL_##NAME, | |
60 | VLOG_LEVELS | |
61 | #undef VLOG_LEVEL | |
62 | VLL_N_LEVELS | |
63 | }; | |
64 | ||
65 | const char *vlog_get_level_name(enum vlog_level); | |
66 | enum vlog_level vlog_get_level_val(const char *name); | |
67 | ||
68 | /* Facilities that we can log to. */ | |
69 | #define VLOG_FACILITIES \ | |
70 | VLOG_FACILITY(SYSLOG, "%05N|%c|%p|%m") \ | |
71 | VLOG_FACILITY(CONSOLE, "%d{%b %d %H:%M:%S}|%05N|%c|%p|%m") \ | |
72 | VLOG_FACILITY(FILE, "%d{%b %d %H:%M:%S}|%05N|%c|%p|%m") | |
73 | enum vlog_facility { | |
74 | #define VLOG_FACILITY(NAME, PATTERN) VLF_##NAME, | |
75 | VLOG_FACILITIES | |
76 | #undef VLOG_FACILITY | |
77 | VLF_N_FACILITIES, | |
78 | VLF_ANY_FACILITY = -1 | |
79 | }; | |
80 | ||
81 | const char *vlog_get_facility_name(enum vlog_facility); | |
82 | enum vlog_facility vlog_get_facility_val(const char *name); | |
83 | ||
480ce8ab BP |
84 | /* A log module. */ |
85 | struct vlog_module { | |
86 | const char *name; /* User-visible name. */ | |
87 | int levels[VLF_N_FACILITIES]; /* Minimum log level for each facility. */ | |
88 | int min_level; /* Minimum log level for any facility. */ | |
064af421 BP |
89 | }; |
90 | ||
480ce8ab BP |
91 | /* Creates and initializes a global instance of a module named MODULE. */ |
92 | #if USE_LINKER_SECTIONS | |
93 | #define VLOG_DEFINE_MODULE(MODULE) \ | |
94 | VLOG_DEFINE_MODULE__(MODULE) \ | |
f4070db7 | 95 | extern struct vlog_module *vlog_module_ptr_##MODULE; \ |
480ce8ab | 96 | struct vlog_module *vlog_module_ptr_##MODULE \ |
d98e6007 | 97 | __attribute__((section("vlog_modules"))) = &VLM_##MODULE |
480ce8ab | 98 | #else |
d98e6007 | 99 | #define VLOG_DEFINE_MODULE(MODULE) extern struct vlog_module VLM_##MODULE |
480ce8ab BP |
100 | #endif |
101 | ||
102 | const char *vlog_get_module_name(const struct vlog_module *); | |
103 | struct vlog_module *vlog_module_from_name(const char *name); | |
064af421 BP |
104 | |
105 | /* Rate-limiter for log messages. */ | |
106 | struct vlog_rate_limit { | |
107 | /* Configuration settings. */ | |
108 | unsigned int rate; /* Tokens per second. */ | |
109 | unsigned int burst; /* Max cumulative tokens credit. */ | |
110 | ||
111 | /* Current status. */ | |
112 | unsigned int tokens; /* Current number of tokens. */ | |
113 | time_t last_fill; /* Last time tokens added. */ | |
114 | time_t first_dropped; /* Time first message was dropped. */ | |
115 | unsigned int n_dropped; /* Number of messages dropped. */ | |
116 | }; | |
117 | ||
118 | /* Number of tokens to emit a message. We add 'rate' tokens per second, which | |
119 | * is 60 times the unit used for 'rate', thus 60 tokens are required to emit | |
120 | * one message. */ | |
121 | #define VLOG_MSG_TOKENS 60 | |
122 | ||
123 | /* Initializer for a struct vlog_rate_limit, to set up a maximum rate of RATE | |
124 | * messages per minute and a maximum burst size of BURST messages. */ | |
125 | #define VLOG_RATE_LIMIT_INIT(RATE, BURST) \ | |
126 | { \ | |
127 | RATE, /* rate */ \ | |
128 | (MIN(BURST, UINT_MAX / VLOG_MSG_TOKENS) \ | |
129 | * VLOG_MSG_TOKENS), /* burst */ \ | |
130 | 0, /* tokens */ \ | |
131 | 0, /* last_fill */ \ | |
132 | 0, /* first_dropped */ \ | |
133 | 0, /* n_dropped */ \ | |
134 | } | |
135 | ||
136 | /* Configuring how each module logs messages. */ | |
480ce8ab BP |
137 | enum vlog_level vlog_get_level(const struct vlog_module *, enum vlog_facility); |
138 | void vlog_set_levels(struct vlog_module *, | |
139 | enum vlog_facility, enum vlog_level); | |
064af421 BP |
140 | char *vlog_set_levels_from_string(const char *); |
141 | char *vlog_get_levels(void); | |
480ce8ab BP |
142 | bool vlog_is_enabled(const struct vlog_module *, enum vlog_level); |
143 | bool vlog_should_drop(const struct vlog_module *, enum vlog_level, | |
064af421 BP |
144 | struct vlog_rate_limit *); |
145 | void vlog_set_verbosity(const char *arg); | |
146 | ||
147 | /* Configuring log facilities. */ | |
148 | void vlog_set_pattern(enum vlog_facility, const char *pattern); | |
149 | const char *vlog_get_log_file(void); | |
150 | int vlog_set_log_file(const char *file_name); | |
151 | int vlog_reopen_log_file(void); | |
152 | ||
279c9e03 | 153 | /* Initialization. */ |
064af421 BP |
154 | void vlog_init(void); |
155 | void vlog_exit(void); | |
279c9e03 BP |
156 | |
157 | /* Functions for actual logging. */ | |
480ce8ab | 158 | void vlog(const struct vlog_module *, enum vlog_level, const char *format, ...) |
1c5a216a | 159 | PRINTF_FORMAT (3, 4); |
480ce8ab BP |
160 | void vlog_valist(const struct vlog_module *, enum vlog_level, |
161 | const char *, va_list) | |
1c5a216a | 162 | PRINTF_FORMAT (3, 0); |
279c9e03 BP |
163 | |
164 | void vlog_fatal(const struct vlog_module *, enum vlog_level, | |
165 | const char *format, ...) | |
166 | PRINTF_FORMAT (3, 4) NO_RETURN; | |
167 | void vlog_fatal_valist(const struct vlog_module *, enum vlog_level, | |
168 | const char *, va_list) | |
169 | PRINTF_FORMAT (3, 0) NO_RETURN; | |
170 | ||
480ce8ab | 171 | void vlog_rate_limit(const struct vlog_module *, enum vlog_level, |
064af421 | 172 | struct vlog_rate_limit *, const char *, ...) |
1c5a216a | 173 | PRINTF_FORMAT (4, 5); |
064af421 | 174 | |
480ce8ab BP |
175 | /* Creates and initializes a global instance of a module named MODULE, and |
176 | * defines a static variable named THIS_MODULE that points to it, for use with | |
177 | * the convenience macros below. */ | |
178 | #define VLOG_DEFINE_THIS_MODULE(MODULE) \ | |
d98e6007 BP |
179 | VLOG_DEFINE_MODULE(MODULE); \ |
180 | static struct vlog_module *const THIS_MODULE = &VLM_##MODULE | |
5136ce49 | 181 | |
480ce8ab BP |
182 | /* Convenience macros. These assume that THIS_MODULE points to a "struct |
183 | * vlog_module" for the current module, as set up by e.g. the | |
184 | * VLOG_DEFINE_MODULE macro above. | |
5136ce49 | 185 | * |
064af421 BP |
186 | * Guaranteed to preserve errno. |
187 | */ | |
279c9e03 | 188 | #define VLOG_FATAL(...) vlog_fatal(THIS_MODULE, VLL_ERR, __VA_ARGS__) |
064af421 BP |
189 | #define VLOG_EMER(...) VLOG(VLL_EMER, __VA_ARGS__) |
190 | #define VLOG_ERR(...) VLOG(VLL_ERR, __VA_ARGS__) | |
191 | #define VLOG_WARN(...) VLOG(VLL_WARN, __VA_ARGS__) | |
192 | #define VLOG_INFO(...) VLOG(VLL_INFO, __VA_ARGS__) | |
193 | #define VLOG_DBG(...) VLOG(VLL_DBG, __VA_ARGS__) | |
194 | ||
195 | /* More convenience macros, for testing whether a given level is enabled in | |
196 | * THIS_MODULE. When constructing a log message is expensive, this enables it | |
197 | * to be skipped. */ | |
198 | #define VLOG_IS_EMER_ENABLED() true | |
199 | #define VLOG_IS_ERR_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_EMER) | |
200 | #define VLOG_IS_WARN_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_WARN) | |
201 | #define VLOG_IS_INFO_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_INFO) | |
202 | #define VLOG_IS_DBG_ENABLED() vlog_is_enabled(THIS_MODULE, VLL_DBG) | |
203 | ||
204 | /* Convenience macros for rate-limiting. | |
205 | * Guaranteed to preserve errno. | |
206 | */ | |
207 | #define VLOG_ERR_RL(RL, ...) VLOG_RL(RL, VLL_ERR, __VA_ARGS__) | |
208 | #define VLOG_WARN_RL(RL, ...) VLOG_RL(RL, VLL_WARN, __VA_ARGS__) | |
209 | #define VLOG_INFO_RL(RL, ...) VLOG_RL(RL, VLL_INFO, __VA_ARGS__) | |
210 | #define VLOG_DBG_RL(RL, ...) VLOG_RL(RL, VLL_DBG, __VA_ARGS__) | |
211 | ||
212 | #define VLOG_DROP_ERR(RL) vlog_should_drop(THIS_MODULE, VLL_ERR, RL) | |
213 | #define VLOG_DROP_WARN(RL) vlog_should_drop(THIS_MODULE, VLL_WARN, RL) | |
214 | #define VLOG_DROP_INFO(RL) vlog_should_drop(THIS_MODULE, VLL_INFO, RL) | |
215 | #define VLOG_DROP_DBG(RL) vlog_should_drop(THIS_MODULE, VLL_DBG, RL) | |
216 | ||
5136364f BP |
217 | /* Macros for logging at most once per execution. */ |
218 | #define VLOG_ERR_ONCE(...) VLOG_ONCE(VLL_ERR, __VA_ARGS__) | |
219 | #define VLOG_WARN_ONCE(...) VLOG_ONCE(VLL_WARN, __VA_ARGS__) | |
220 | #define VLOG_INFO_ONCE(...) VLOG_ONCE(VLL_INFO, __VA_ARGS__) | |
221 | #define VLOG_DBG_ONCE(...) VLOG_ONCE(VLL_DBG, __VA_ARGS__) | |
222 | ||
064af421 BP |
223 | /* Command line processing. */ |
224 | #define VLOG_OPTION_ENUMS OPT_LOG_FILE | |
225 | #define VLOG_LONG_OPTIONS \ | |
e3c17733 BP |
226 | {"verbose", optional_argument, NULL, 'v'}, \ |
227 | {"log-file", optional_argument, NULL, OPT_LOG_FILE} | |
064af421 BP |
228 | #define VLOG_OPTION_HANDLERS \ |
229 | case 'v': \ | |
230 | vlog_set_verbosity(optarg); \ | |
231 | break; \ | |
232 | case OPT_LOG_FILE: \ | |
233 | vlog_set_log_file(optarg); \ | |
234 | break; | |
235 | void vlog_usage(void); | |
236 | ||
237 | /* Implementation details. */ | |
45704b24 BP |
238 | #define VLOG(LEVEL, ...) \ |
239 | do { \ | |
240 | enum vlog_level level__ = LEVEL; \ | |
241 | if (THIS_MODULE->min_level >= level__) { \ | |
242 | vlog(THIS_MODULE, level__, __VA_ARGS__); \ | |
243 | } \ | |
064af421 BP |
244 | } while (0) |
245 | #define VLOG_RL(RL, LEVEL, ...) \ | |
246 | do { \ | |
45704b24 BP |
247 | enum vlog_level level__ = LEVEL; \ |
248 | if (THIS_MODULE->min_level >= level__) { \ | |
249 | vlog_rate_limit(THIS_MODULE, level__, RL, __VA_ARGS__); \ | |
064af421 BP |
250 | } \ |
251 | } while (0) | |
5136364f BP |
252 | #define VLOG_ONCE(LEVEL, ...) \ |
253 | do { \ | |
254 | static bool already_logged; \ | |
255 | if (!already_logged) { \ | |
256 | already_logged = true; \ | |
257 | vlog(THIS_MODULE, LEVEL, __VA_ARGS__); \ | |
258 | } \ | |
259 | } while (0) | |
260 | ||
480ce8ab | 261 | #define VLOG_DEFINE_MODULE__(MODULE) \ |
f4070db7 | 262 | extern struct vlog_module VLM_##MODULE; \ |
480ce8ab BP |
263 | struct vlog_module VLM_##MODULE = \ |
264 | { \ | |
265 | #MODULE, /* name */ \ | |
266 | { [ 0 ... VLF_N_FACILITIES - 1] = VLL_INFO }, /* levels */ \ | |
267 | VLL_INFO, /* min_level */ \ | |
268 | }; | |
269 | ||
f4ade105 JG |
270 | #ifdef __cplusplus |
271 | } | |
272 | #endif | |
064af421 BP |
273 | |
274 | ||
275 | #endif /* vlog.h */ |