]> git.proxmox.com Git - mirror_ovs.git/blame - lib/vlog.c
ovsdb-idl: Fix iteration over tracked rows with no actual data.
[mirror_ovs.git] / lib / vlog.c
CommitLineData
064af421 1/*
934d84fb 2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013, 2015, 2016 Nicira, Inc.
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#include <config.h>
e6211adc 18#include "openvswitch/vlog.h"
064af421
BP
19#include <assert.h>
20#include <ctype.h>
21#include <errno.h>
9eb94563 22#include <fcntl.h>
064af421
BP
23#include <stdarg.h>
24#include <stdlib.h>
25#include <string.h>
68cb8aaf 26#include <sys/stat.h>
064af421
BP
27#include <sys/types.h>
28#include <syslog.h>
29#include <time.h>
30#include <unistd.h>
a5fb0e29 31#include "async-append.h"
4958e3ee 32#include "coverage.h"
064af421 33#include "dirs.h"
3e8a2ad1 34#include "openvswitch/dynamic-string.h"
64c96779 35#include "openvswitch/ofpbuf.h"
81d6495f 36#include "ovs-thread.h"
064af421 37#include "sat-math.h"
afc9f547 38#include "socket-util.h"
8628b0b7 39#include "svec.h"
fe089c0d
AA
40#include "syslog-direct.h"
41#include "syslog-libc.h"
e11f0c25 42#include "syslog-null.h"
fe089c0d 43#include "syslog-provider.h"
064af421
BP
44#include "timeval.h"
45#include "unixctl.h"
46#include "util.h"
47
d98e6007 48VLOG_DEFINE_THIS_MODULE(vlog);
064af421 49
4958e3ee
BP
50/* ovs_assert() logs the assertion message, so using ovs_assert() in this
51 * source file could cause recursion. */
52#undef ovs_assert
53#define ovs_assert use_assert_instead_of_ovs_assert_in_this_module
54
064af421 55/* Name for each logging level. */
4b5f1d2c 56static const char *const level_names[VLL_N_LEVELS] = {
afc9f547 57#define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) #NAME,
064af421
BP
58 VLOG_LEVELS
59#undef VLOG_LEVEL
60};
61
62/* Syslog value for each logging level. */
4b5f1d2c 63static const int syslog_levels[VLL_N_LEVELS] = {
afc9f547 64#define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) SYSLOG_LEVEL,
064af421
BP
65 VLOG_LEVELS
66#undef VLOG_LEVEL
67};
68
afc9f547
HM
69/* RFC 5424 defines specific values for each syslog level. Normally LOG_* use
70 * the same values. Verify that in fact they're the same. If we get assertion
71 * failures here then we need to define a separate rfc5424_levels[] array. */
72#define VLOG_LEVEL(NAME, SYSLOG_LEVEL, RFC5424) \
73 BUILD_ASSERT_DECL(SYSLOG_LEVEL == RFC5424);
74VLOG_LEVELS
75#undef VLOG_LEVELS
76
77/* Similarly, RFC 5424 defines the local0 facility with the value ordinarily
78 * used for LOG_LOCAL0. */
79BUILD_ASSERT_DECL(LOG_LOCAL0 == (16 << 3));
80
d5460484 81/* Protects the 'pattern' in all "struct destination"s, so that a race between
97be1538
EJ
82 * changing and reading the pattern does not cause an access to freed
83 * memory. */
84static struct ovs_rwlock pattern_rwlock = OVS_RWLOCK_INITIALIZER;
85
d5460484
GS
86/* Information about each destination. */
87struct destination {
064af421 88 const char *name; /* Name. */
97be1538 89 char *pattern OVS_GUARDED_BY(pattern_rwlock); /* Current pattern. */
064af421
BP
90 bool default_pattern; /* Whether current pattern is the default. */
91};
d5460484
GS
92static struct destination destinations[VLF_N_DESTINATIONS] = {
93#define VLOG_DESTINATION(NAME, PATTERN) {#NAME, PATTERN, true},
94 VLOG_DESTINATIONS
95#undef VLOG_DESTINATION
064af421
BP
96};
97
81d6495f 98/* Sequence number for the message currently being composed. */
2ba4f163 99DEFINE_STATIC_PER_THREAD_DATA(unsigned int, msg_num, 0);
81d6495f
BP
100
101/* VLF_FILE configuration.
102 *
103 * All of the following is protected by 'log_file_mutex', which nests inside
104 * pattern_rwlock. */
867a2e3a
BP
105static struct ovs_mutex log_file_mutex OVS_ACQ_AFTER(pattern_rwlock)
106 = OVS_MUTEX_INITIALIZER;
3e2493e1 107static char *log_file_name OVS_GUARDED_BY(log_file_mutex) = NULL;
97be1538
EJ
108static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
109static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
888e0cf4 110static bool log_async OVS_GUARDED_BY(log_file_mutex);
fe089c0d 111static struct syslogger *syslogger = NULL;
064af421 112
867a2e3a
BP
113/* The log modules. */
114static struct ovs_list vlog_modules OVS_GUARDED_BY(log_file_mutex)
115 = OVS_LIST_INITIALIZER(&vlog_modules);
116
afc9f547
HM
117/* Syslog export configuration. */
118static int syslog_fd OVS_GUARDED_BY(pattern_rwlock) = -1;
119
d69d61c7
GS
120/* Log facility configuration. */
121static atomic_int log_facility = ATOMIC_VAR_INIT(0);
122
123/* Facility name and its value. */
124struct vlog_facility {
125 char *name; /* Name. */
126 unsigned int value; /* Facility associated with 'name'. */
127};
128static struct vlog_facility vlog_facilities[] = {
129 {"kern", LOG_KERN},
130 {"user", LOG_USER},
131 {"mail", LOG_MAIL},
132 {"daemon", LOG_DAEMON},
133 {"auth", LOG_AUTH},
134 {"syslog", LOG_SYSLOG},
135 {"lpr", LOG_LPR},
136 {"news", LOG_NEWS},
137 {"uucp", LOG_UUCP},
138 {"clock", LOG_CRON},
139 {"ftp", LOG_FTP},
140 {"ntp", 12<<3},
141 {"audit", 13<<3},
142 {"alert", 14<<3},
143 {"clock2", 15<<3},
144 {"local0", LOG_LOCAL0},
145 {"local1", LOG_LOCAL1},
146 {"local2", LOG_LOCAL2},
147 {"local3", LOG_LOCAL3},
148 {"local4", LOG_LOCAL4},
149 {"local5", LOG_LOCAL5},
150 {"local6", LOG_LOCAL6},
151 {"local7", LOG_LOCAL7}
152};
153static bool vlog_facility_exists(const char* facility, int *value);
154
480ce8ab 155static void format_log_message(const struct vlog_module *, enum vlog_level,
afc9f547 156 const char *pattern,
064af421 157 const char *message, va_list, struct ds *)
cab50449 158 OVS_PRINTF_FORMAT(4, 0);
064af421
BP
159
160/* Searches the 'n_names' in 'names'. Returns the index of a match for
161 * 'target', or 'n_names' if no name matches. */
162static size_t
4b5f1d2c 163search_name_array(const char *target, const char *const *names, size_t n_names)
064af421
BP
164{
165 size_t i;
166
167 for (i = 0; i < n_names; i++) {
168 assert(names[i]);
169 if (!strcasecmp(names[i], target)) {
170 break;
171 }
172 }
173 return i;
174}
175
176/* Returns the name for logging level 'level'. */
177const char *
178vlog_get_level_name(enum vlog_level level)
179{
180 assert(level < VLL_N_LEVELS);
181 return level_names[level];
182}
183
184/* Returns the logging level with the given 'name', or VLL_N_LEVELS if 'name'
185 * is not the name of a logging level. */
186enum vlog_level
d295e8e9 187vlog_get_level_val(const char *name)
064af421
BP
188{
189 return search_name_array(name, level_names, ARRAY_SIZE(level_names));
190}
191
d5460484 192/* Returns the name for logging destination 'destination'. */
064af421 193const char *
d5460484 194vlog_get_destination_name(enum vlog_destination destination)
064af421 195{
d5460484
GS
196 assert(destination < VLF_N_DESTINATIONS);
197 return destinations[destination].name;
064af421
BP
198}
199
d5460484
GS
200/* Returns the logging destination named 'name', or VLF_N_DESTINATIONS if
201 * 'name' is not the name of a logging destination. */
202enum vlog_destination
203vlog_get_destination_val(const char *name)
064af421
BP
204{
205 size_t i;
206
d5460484
GS
207 for (i = 0; i < VLF_N_DESTINATIONS; i++) {
208 if (!strcasecmp(destinations[i].name, name)) {
064af421
BP
209 break;
210 }
211 }
212 return i;
213}
214
922fed06
BP
215void
216vlog_insert_module(struct ovs_list *vlog)
e6211adc 217{
867a2e3a 218 ovs_mutex_lock(&log_file_mutex);
417e7e66 219 ovs_list_insert(&vlog_modules, vlog);
867a2e3a 220 ovs_mutex_unlock(&log_file_mutex);
e6211adc
TG
221}
222
064af421 223/* Returns the name for logging module 'module'. */
480ce8ab
BP
224const char *
225vlog_get_module_name(const struct vlog_module *module)
064af421 226{
480ce8ab 227 return module->name;
064af421
BP
228}
229
480ce8ab
BP
230/* Returns the logging module named 'name', or NULL if 'name' is not the name
231 * of a logging module. */
232struct vlog_module *
233vlog_module_from_name(const char *name)
064af421 234{
86e504e1 235 struct vlog_module *mp;
480ce8ab 236
867a2e3a 237 ovs_mutex_lock(&log_file_mutex);
86e504e1
HS
238 LIST_FOR_EACH (mp, list, &vlog_modules) {
239 if (!strcasecmp(name, mp->name)) {
867a2e3a 240 ovs_mutex_unlock(&log_file_mutex);
86e504e1 241 return mp;
480ce8ab
BP
242 }
243 }
867a2e3a 244 ovs_mutex_unlock(&log_file_mutex);
86e504e1 245
480ce8ab 246 return NULL;
064af421
BP
247}
248
d5460484
GS
249/* Returns the current logging level for the given 'module' and
250 * 'destination'. */
064af421 251enum vlog_level
d5460484
GS
252vlog_get_level(const struct vlog_module *module,
253 enum vlog_destination destination)
064af421 254{
d5460484
GS
255 assert(destination < VLF_N_DESTINATIONS);
256 return module->levels[destination];
064af421
BP
257}
258
97be1538 259static void
1b6db6a5 260update_min_level(struct vlog_module *module) OVS_REQUIRES(log_file_mutex)
064af421 261{
d5460484 262 enum vlog_destination destination;
064af421 263
c1a543a8 264 module->min_level = VLL_OFF;
d5460484
GS
265 for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
266 if (log_fd >= 0 || destination != VLF_FILE) {
267 enum vlog_level level = module->levels[destination];
56cee53b 268 if (level > module->min_level) {
480ce8ab
BP
269 module->min_level = level;
270 }
064af421
BP
271 }
272 }
064af421
BP
273}
274
275static void
d5460484
GS
276set_destination_level(enum vlog_destination destination,
277 struct vlog_module *module, enum vlog_level level)
064af421 278{
d5460484 279 assert(destination >= 0 && destination < VLF_N_DESTINATIONS);
064af421
BP
280 assert(level < VLL_N_LEVELS);
281
97be1538 282 ovs_mutex_lock(&log_file_mutex);
480ce8ab 283 if (!module) {
86e504e1
HS
284 struct vlog_module *mp;
285 LIST_FOR_EACH (mp, list, &vlog_modules) {
d5460484 286 mp->levels[destination] = level;
86e504e1 287 update_min_level(mp);
064af421
BP
288 }
289 } else {
d5460484 290 module->levels[destination] = level;
064af421
BP
291 update_min_level(module);
292 }
97be1538 293 ovs_mutex_unlock(&log_file_mutex);
064af421
BP
294}
295
d5460484
GS
296/* Sets the logging level for the given 'module' and 'destination' to 'level'.
297 * A null 'module' or a 'destination' of VLF_ANY_DESTINATION is treated as a
298 * wildcard across all modules or destinations, respectively. */
064af421 299void
d5460484 300vlog_set_levels(struct vlog_module *module, enum vlog_destination destination,
d295e8e9 301 enum vlog_level level)
064af421 302{
d5460484
GS
303 assert(destination < VLF_N_DESTINATIONS ||
304 destination == VLF_ANY_DESTINATION);
305 if (destination == VLF_ANY_DESTINATION) {
306 for (destination = 0; destination < VLF_N_DESTINATIONS;
307 destination++) {
308 set_destination_level(destination, module, level);
064af421
BP
309 }
310 } else {
d5460484 311 set_destination_level(destination, module, level);
064af421
BP
312 }
313}
314
315static void
d5460484 316do_set_pattern(enum vlog_destination destination, const char *pattern)
064af421 317{
d5460484 318 struct destination *f = &destinations[destination];
81d6495f 319
97be1538 320 ovs_rwlock_wrlock(&pattern_rwlock);
064af421
BP
321 if (!f->default_pattern) {
322 free(f->pattern);
323 } else {
324 f->default_pattern = false;
325 }
326 f->pattern = xstrdup(pattern);
97be1538 327 ovs_rwlock_unlock(&pattern_rwlock);
064af421
BP
328}
329
d5460484 330/* Sets the pattern for the given 'destination' to 'pattern'. */
064af421 331void
d5460484
GS
332vlog_set_pattern(enum vlog_destination destination, const char *pattern)
333{
334 assert(destination < VLF_N_DESTINATIONS ||
335 destination == VLF_ANY_DESTINATION);
336 if (destination == VLF_ANY_DESTINATION) {
337 for (destination = 0; destination < VLF_N_DESTINATIONS;
338 destination++) {
339 do_set_pattern(destination, pattern);
064af421
BP
340 }
341 } else {
d5460484 342 do_set_pattern(destination, pattern);
064af421
BP
343 }
344}
345
064af421
BP
346/* Sets the name of the log file used by VLF_FILE to 'file_name', or to the
347 * default file name if 'file_name' is null. Returns 0 if successful,
348 * otherwise a positive errno value. */
349int
350vlog_set_log_file(const char *file_name)
351{
81d6495f 352 char *new_log_file_name;
86e504e1 353 struct vlog_module *mp;
81d6495f
BP
354 struct stat old_stat;
355 struct stat new_stat;
356 int new_log_fd;
357 bool same_file;
97be1538 358 bool log_close;
81d6495f
BP
359
360 /* Open new log file. */
361 new_log_file_name = (file_name
362 ? xstrdup(file_name)
363 : xasprintf("%s/%s.log", ovs_logdir(), program_name));
03736a67 364 new_log_fd = open(new_log_file_name, O_WRONLY | O_CREAT | O_APPEND, 0660);
81d6495f
BP
365 if (new_log_fd < 0) {
366 VLOG_WARN("failed to open %s for logging: %s",
367 new_log_file_name, ovs_strerror(errno));
368 free(new_log_file_name);
369 return errno;
370 }
371
372 /* If the new log file is the same one we already have open, bail out. */
97be1538 373 ovs_mutex_lock(&log_file_mutex);
81d6495f
BP
374 same_file = (log_fd >= 0
375 && new_log_fd >= 0
376 && !fstat(log_fd, &old_stat)
377 && !fstat(new_log_fd, &new_stat)
378 && old_stat.st_dev == new_stat.st_dev
379 && old_stat.st_ino == new_stat.st_ino);
97be1538 380 ovs_mutex_unlock(&log_file_mutex);
81d6495f
BP
381 if (same_file) {
382 close(new_log_fd);
383 free(new_log_file_name);
384 return 0;
385 }
064af421 386
81d6495f 387 /* Log closing old log file (we can't log while holding log_file_mutex). */
97be1538
EJ
388 ovs_mutex_lock(&log_file_mutex);
389 log_close = log_fd >= 0;
390 ovs_mutex_unlock(&log_file_mutex);
391 if (log_close) {
064af421 392 VLOG_INFO("closing log file");
81d6495f 393 }
a5fb0e29 394
81d6495f 395 /* Close old log file, if any, and install new one. */
97be1538 396 ovs_mutex_lock(&log_file_mutex);
81d6495f 397 if (log_fd >= 0) {
9eb94563 398 close(log_fd);
81d6495f 399 async_append_destroy(log_writer);
064af421
BP
400 }
401
1bbc32df 402 free(log_file_name);
81d6495f
BP
403 log_file_name = xstrdup(new_log_file_name);
404 log_fd = new_log_fd;
888e0cf4
BP
405 if (log_async) {
406 log_writer = async_append_create(new_log_fd);
407 }
81d6495f 408
86e504e1
HS
409 LIST_FOR_EACH (mp, list, &vlog_modules) {
410 update_min_level(mp);
064af421 411 }
97be1538 412 ovs_mutex_unlock(&log_file_mutex);
064af421 413
81d6495f
BP
414 /* Log opening new log file (we can't log while holding log_file_mutex). */
415 VLOG_INFO("opened log file %s", new_log_file_name);
416 free(new_log_file_name);
064af421 417
81d6495f 418 return 0;
064af421
BP
419}
420
421/* Closes and then attempts to re-open the current log file. (This is useful
422 * just after log rotation, to ensure that the new log file starts being used.)
423 * Returns 0 if successful, otherwise a positive errno value. */
424int
425vlog_reopen_log_file(void)
426{
81d6495f 427 char *fn;
68cb8aaf 428
97be1538 429 ovs_mutex_lock(&log_file_mutex);
2225c0b9 430 fn = nullable_xstrdup(log_file_name);
97be1538 431 ovs_mutex_unlock(&log_file_mutex);
68cb8aaf 432
81d6495f
BP
433 if (fn) {
434 int error = vlog_set_log_file(fn);
435 free(fn);
436 return error;
437 } else {
68cb8aaf
BP
438 return 0;
439 }
064af421
BP
440}
441
de929213 442#ifndef _WIN32
3de44dd1
AZ
443/* In case a log file exists, change its owner to new 'user' and 'group'.
444 *
445 * This is useful for handling cases where the --log-file option is
446 * specified ahead of the --user option. */
447void
de929213 448vlog_change_owner_unix(uid_t user, gid_t group)
3de44dd1 449{
e9d6808c
AZ
450 struct ds err = DS_EMPTY_INITIALIZER;
451 int error;
3de44dd1 452
e9d6808c
AZ
453 ovs_mutex_lock(&log_file_mutex);
454 error = log_file_name ? chown(log_file_name, user, group) : 0;
3de44dd1 455 if (error) {
e9d6808c
AZ
456 /* Build the error message. We can not call VLOG_FATAL directly
457 * here because VLOG_FATAL() will try again to to acquire
458 * 'log_file_mutex' lock, causing deadlock.
459 */
460 ds_put_format(&err, "Failed to change %s ownership: %s.",
461 log_file_name, ovs_strerror(errno));
3de44dd1 462 }
3e2493e1 463 ovs_mutex_unlock(&log_file_mutex);
e9d6808c
AZ
464
465 if (error) {
466 VLOG_FATAL("%s", ds_steal_cstr(&err));
467 }
3de44dd1 468}
de929213 469#endif
3de44dd1 470
2a3e30b2
BP
471/* Set debugging levels. Returns null if successful, otherwise an error
472 * message that the caller must free(). */
064af421
BP
473char *
474vlog_set_levels_from_string(const char *s_)
475{
064af421 476 char *s = xstrdup(s_);
2a3e30b2
BP
477 char *save_ptr = NULL;
478 char *msg = NULL;
479 char *word;
064af421 480
2a3e30b2
BP
481 word = strtok_r(s, " ,:\t", &save_ptr);
482 if (word && !strcasecmp(word, "PATTERN")) {
d5460484 483 enum vlog_destination destination;
064af421 484
2a3e30b2
BP
485 word = strtok_r(NULL, " ,:\t", &save_ptr);
486 if (!word) {
d5460484 487 msg = xstrdup("missing destination");
2a3e30b2 488 goto exit;
064af421
BP
489 }
490
d5460484
GS
491 destination = (!strcasecmp(word, "ANY")
492 ? VLF_ANY_DESTINATION
493 : vlog_get_destination_val(word));
494 if (destination == VLF_N_DESTINATIONS) {
495 msg = xasprintf("unknown destination \"%s\"", word);
2a3e30b2
BP
496 goto exit;
497 }
d5460484 498 vlog_set_pattern(destination, save_ptr);
d69d61c7
GS
499 } else if (word && !strcasecmp(word, "FACILITY")) {
500 int value;
501
502 if (!vlog_facility_exists(save_ptr, &value)) {
503 msg = xstrdup("invalid facility");
504 goto exit;
505 }
506 atomic_store_explicit(&log_facility, value, memory_order_relaxed);
2a3e30b2
BP
507 } else {
508 struct vlog_module *module = NULL;
509 enum vlog_level level = VLL_N_LEVELS;
d5460484 510 enum vlog_destination destination = VLF_N_DESTINATIONS;
2a3e30b2
BP
511
512 for (; word != NULL; word = strtok_r(NULL, " ,:\t", &save_ptr)) {
513 if (!strcasecmp(word, "ANY")) {
514 continue;
d5460484
GS
515 } else if (vlog_get_destination_val(word) != VLF_N_DESTINATIONS) {
516 if (destination != VLF_N_DESTINATIONS) {
517 msg = xstrdup("cannot specify multiple destinations");
2a3e30b2 518 goto exit;
064af421 519 }
d5460484 520 destination = vlog_get_destination_val(word);
2a3e30b2
BP
521 } else if (vlog_get_level_val(word) != VLL_N_LEVELS) {
522 if (level != VLL_N_LEVELS) {
523 msg = xstrdup("cannot specify multiple levels");
524 goto exit;
525 }
526 level = vlog_get_level_val(word);
527 } else if (vlog_module_from_name(word)) {
528 if (module) {
529 msg = xstrdup("cannot specify multiple modules");
530 goto exit;
531 }
532 module = vlog_module_from_name(word);
533 } else {
d5460484
GS
534 msg = xasprintf("no destination, level, or module \"%s\"",
535 word);
2a3e30b2 536 goto exit;
064af421 537 }
2a3e30b2 538 }
064af421 539
d5460484
GS
540 if (destination == VLF_N_DESTINATIONS) {
541 destination = VLF_ANY_DESTINATION;
2a3e30b2
BP
542 }
543 if (level == VLL_N_LEVELS) {
544 level = VLL_DBG;
064af421 545 }
d5460484 546 vlog_set_levels(module, destination, level);
064af421 547 }
2a3e30b2
BP
548
549exit:
064af421 550 free(s);
2a3e30b2 551 return msg;
064af421
BP
552}
553
316bd0f8
BP
554/* Set debugging levels. Abort with an error message if 's' is invalid. */
555void
556vlog_set_levels_from_string_assert(const char *s)
557{
558 char *error = vlog_set_levels_from_string(s);
559 if (error) {
560 ovs_fatal(0, "%s", error);
561 }
562}
563
064af421
BP
564/* If 'arg' is null, configure maximum verbosity. Otherwise, sets
565 * configuration according to 'arg' (see vlog_set_levels_from_string()). */
566void
567vlog_set_verbosity(const char *arg)
568{
569 if (arg) {
570 char *msg = vlog_set_levels_from_string(arg);
571 if (msg) {
572 ovs_fatal(0, "processing \"%s\": %s", arg, msg);
573 }
574 } else {
d5460484 575 vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
064af421
BP
576 }
577}
578
fe089c0d
AA
579void
580vlog_set_syslog_method(const char *method)
581{
582 if (syslogger) {
583 /* Set syslogger only, if one is not already set. This effectively
584 * means that only the first --syslog-method argument is honored. */
585 return;
586 }
587
e11f0c25
BP
588 if (!strcmp(method, "null")) {
589 syslogger = syslog_null_create();
590 } else if (!strcmp(method, "libc")) {
fe089c0d
AA
591 syslogger = syslog_libc_create();
592 } else if (!strncmp(method, "udp:", 4) || !strncmp(method, "unix:", 5)) {
593 syslogger = syslog_direct_create(method);
594 } else {
595 ovs_fatal(0, "unsupported syslog method '%s'", method);
596 }
597}
598
afc9f547
HM
599/* Set the vlog udp syslog target. */
600void
601vlog_set_syslog_target(const char *target)
602{
603 int new_fd;
604
1bb01121 605 inet_open_active(SOCK_DGRAM, target, -1, NULL, &new_fd, 0);
afc9f547
HM
606
607 ovs_rwlock_wrlock(&pattern_rwlock);
608 if (syslog_fd >= 0) {
609 close(syslog_fd);
610 }
611 syslog_fd = new_fd;
612 ovs_rwlock_unlock(&pattern_rwlock);
613}
614
ecbc7f0a
WT
615/*
616 * This function writes directly to log file without using async writer or
617 * taking a lock. Caller must hold 'log_file_mutex' or be sure that it's
618 * not necessary. Could be used in exceptional cases like dumping of backtrace
619 * on fatal signals.
620 */
621void
622vlog_direct_write_to_log_file_unsafe(const char *s)
623 OVS_NO_THREAD_SAFETY_ANALYSIS
ecd4a8fc 624{
ecbc7f0a
WT
625 if (log_fd >= 0) {
626 ignore(write(log_fd, s, strlen(s)));
627 }
ecd4a8fc
WT
628}
629
d69d61c7
GS
630/* Returns 'false' if 'facility' is not a valid string. If 'facility'
631 * is a valid string, sets 'value' with the integer value of 'facility'
632 * and returns 'true'. */
633static bool
634vlog_facility_exists(const char* facility, int *value)
635{
636 size_t i;
637 for (i = 0; i < ARRAY_SIZE(vlog_facilities); i++) {
638 if (!strcasecmp(vlog_facilities[i].name, facility)) {
639 *value = vlog_facilities[i].value;
640 return true;
641 }
642 }
643 return false;
644}
645
064af421 646static void
0e15264f
BP
647vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
648 void *aux OVS_UNUSED)
064af421 649{
0e15264f
BP
650 int i;
651
f446e7ce
JP
652 /* With no argument, set all destinations and modules to "dbg". */
653 if (argc == 1) {
654 vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
655 }
0e15264f
BP
656 for (i = 1; i < argc; i++) {
657 char *msg = vlog_set_levels_from_string(argv[i]);
658 if (msg) {
bde9f75d 659 unixctl_command_reply_error(conn, msg);
0e15264f
BP
660 free(msg);
661 return;
662 }
663 }
bde9f75d 664 unixctl_command_reply(conn, NULL);
064af421
BP
665}
666
667static void
0e15264f
BP
668vlog_unixctl_list(struct unixctl_conn *conn, int argc OVS_UNUSED,
669 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
064af421
BP
670{
671 char *msg = vlog_get_levels();
bde9f75d 672 unixctl_command_reply(conn, msg);
064af421
BP
673 free(msg);
674}
675
532e1463
AA
676static void
677vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED,
678 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
679{
680 char *msg;
681
682 msg = vlog_get_patterns();
683 unixctl_command_reply(conn, msg);
684 free(msg);
685}
686
064af421 687static void
0e15264f
BP
688vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED,
689 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
064af421 690{
97be1538
EJ
691 bool has_log_file;
692
693 ovs_mutex_lock(&log_file_mutex);
694 has_log_file = log_file_name != NULL;
695 ovs_mutex_unlock(&log_file_mutex);
696
697 if (has_log_file) {
064af421
BP
698 int error = vlog_reopen_log_file();
699 if (error) {
10a89ef0 700 unixctl_command_reply_error(conn, ovs_strerror(errno));
064af421 701 } else {
bde9f75d 702 unixctl_command_reply(conn, NULL);
064af421
BP
703 }
704 } else {
bde9f75d 705 unixctl_command_reply_error(conn, "Logging to file not configured");
064af421
BP
706 }
707}
708
06380128
BP
709static void
710vlog_unixctl_close(struct unixctl_conn *conn, int argc OVS_UNUSED,
711 const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
712{
713 ovs_mutex_lock(&log_file_mutex);
714 if (log_fd >= 0) {
715 close(log_fd);
716 log_fd = -1;
717
718 async_append_destroy(log_writer);
719 log_writer = NULL;
720
721 struct vlog_module *mp;
722 LIST_FOR_EACH (mp, list, &vlog_modules) {
723 update_min_level(mp);
724 }
725 }
726 ovs_mutex_unlock(&log_file_mutex);
727
728 unixctl_command_reply(conn, NULL);
729}
730
4958e3ee
BP
731static void
732set_all_rate_limits(bool enable)
733{
86e504e1 734 struct vlog_module *mp;
4958e3ee 735
867a2e3a 736 ovs_mutex_lock(&log_file_mutex);
86e504e1
HS
737 LIST_FOR_EACH (mp, list, &vlog_modules) {
738 mp->honor_rate_limits = enable;
4958e3ee 739 }
867a2e3a 740 ovs_mutex_unlock(&log_file_mutex);
4958e3ee
BP
741}
742
743static void
744set_rate_limits(struct unixctl_conn *conn, int argc,
745 const char *argv[], bool enable)
746{
747 if (argc > 1) {
748 int i;
749
750 for (i = 1; i < argc; i++) {
751 if (!strcasecmp(argv[i], "ANY")) {
752 set_all_rate_limits(enable);
753 } else {
754 struct vlog_module *module = vlog_module_from_name(argv[i]);
755 if (!module) {
756 unixctl_command_reply_error(conn, "unknown module");
757 return;
758 }
759 module->honor_rate_limits = enable;
760 }
761 }
762 } else {
763 set_all_rate_limits(enable);
764 }
765 unixctl_command_reply(conn, NULL);
766}
767
768static void
769vlog_enable_rate_limit(struct unixctl_conn *conn, int argc,
770 const char *argv[], void *aux OVS_UNUSED)
771{
772 set_rate_limits(conn, argc, argv, true);
773}
774
775static void
776vlog_disable_rate_limit(struct unixctl_conn *conn, int argc,
777 const char *argv[], void *aux OVS_UNUSED)
778{
779 set_rate_limits(conn, argc, argv, false);
780}
781
81d6495f
BP
782/* Initializes the logging subsystem and registers its unixctl server
783 * commands. */
784void
785vlog_init(void)
786{
c3b758f6
BP
787 static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
788
789 if (ovsthread_once_start(&once)) {
c3b758f6 790 long long int now;
d69d61c7 791 int facility;
195360dc 792 bool print_syslog_target_deprecation;
c3b758f6
BP
793
794 /* Do initialization work that needs to be done before any logging
795 * occurs. We want to keep this really minimal because any attempt to
796 * log anything before calling ovsthread_once_done() will deadlock. */
d69d61c7 797 atomic_read_explicit(&log_facility, &facility, memory_order_relaxed);
fe089c0d 798 if (!syslogger) {
e11f0c25
BP
799 char *env = getenv("OVS_SYSLOG_METHOD");
800 if (env && env[0]) {
801 vlog_set_syslog_method(env);
802 } else {
803 syslogger = syslog_libc_create();
804 }
fe089c0d
AA
805 }
806 syslogger->class->openlog(syslogger, facility ? facility : LOG_DAEMON);
c3b758f6
BP
807 ovsthread_once_done(&once);
808
809 /* Now do anything that we want to happen only once but doesn't have to
810 * finish before we start logging. */
811
812 now = time_wall_msec();
813 if (now < 0) {
814 char *s = xastrftime_msec("%a, %d %b %Y %H:%M:%S", now, true);
815 VLOG_ERR("current time is negative: %s (%lld)", s, now);
816 free(s);
817 }
818
819 unixctl_command_register(
d5460484 820 "vlog/set", "{spec | PATTERN:destination:pattern}",
f446e7ce 821 0, INT_MAX, vlog_unixctl_set, NULL);
c3b758f6
BP
822 unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list,
823 NULL);
532e1463
AA
824 unixctl_command_register("vlog/list-pattern", "", 0, 0,
825 vlog_unixctl_list_pattern, NULL);
c3b758f6
BP
826 unixctl_command_register("vlog/enable-rate-limit", "[module]...",
827 0, INT_MAX, vlog_enable_rate_limit, NULL);
828 unixctl_command_register("vlog/disable-rate-limit", "[module]...",
829 0, INT_MAX, vlog_disable_rate_limit, NULL);
830 unixctl_command_register("vlog/reopen", "", 0, 0,
831 vlog_unixctl_reopen, NULL);
06380128
BP
832 unixctl_command_register("vlog/close", "", 0, 0,
833 vlog_unixctl_close, NULL);
195360dc
AA
834
835 ovs_rwlock_rdlock(&pattern_rwlock);
836 print_syslog_target_deprecation = syslog_fd >= 0;
837 ovs_rwlock_unlock(&pattern_rwlock);
838
839 if (print_syslog_target_deprecation) {
840 VLOG_WARN("--syslog-target flag is deprecated, use "
841 "--syslog-method instead");
842 }
c3b758f6 843 }
81d6495f
BP
844}
845
888e0cf4
BP
846/* Enables VLF_FILE log output to be written asynchronously to disk.
847 * Asynchronous file writes avoid blocking the process in the case of a busy
848 * disk, but on the other hand they are less robust: there is a chance that the
849 * write will not make it to the log file if the process crashes soon after the
850 * log call. */
851void
852vlog_enable_async(void)
853{
854 ovs_mutex_lock(&log_file_mutex);
855 log_async = true;
856 if (log_fd >= 0 && !log_writer) {
857 log_writer = async_append_create(log_fd);
858 }
859 ovs_mutex_unlock(&log_file_mutex);
860}
861
93f55842
BP
862void
863vlog_disable_async(void)
864{
865 ovs_mutex_lock(&log_file_mutex);
866 log_async = false;
867 async_append_destroy(log_writer);
868 log_writer = NULL;
869 ovs_mutex_unlock(&log_file_mutex);
870}
871
064af421
BP
872/* Print the current logging level for each module. */
873char *
874vlog_get_levels(void)
875{
876 struct ds s = DS_EMPTY_INITIALIZER;
86e504e1 877 struct vlog_module *mp;
8628b0b7 878 struct svec lines = SVEC_EMPTY_INITIALIZER;
8628b0b7 879 size_t i;
064af421
BP
880
881 ds_put_format(&s, " console syslog file\n");
882 ds_put_format(&s, " ------- ------ ------\n");
883
867a2e3a 884 ovs_mutex_lock(&log_file_mutex);
86e504e1 885 LIST_FOR_EACH (mp, list, &vlog_modules) {
4958e3ee
BP
886 struct ds line;
887
888 ds_init(&line);
889 ds_put_format(&line, "%-16s %4s %4s %4s",
86e504e1
HS
890 vlog_get_module_name(mp),
891 vlog_get_level_name(vlog_get_level(mp, VLF_CONSOLE)),
892 vlog_get_level_name(vlog_get_level(mp, VLF_SYSLOG)),
893 vlog_get_level_name(vlog_get_level(mp, VLF_FILE)));
894 if (!mp->honor_rate_limits) {
4958e3ee
BP
895 ds_put_cstr(&line, " (rate limiting disabled)");
896 }
897 ds_put_char(&line, '\n');
898
899 svec_add_nocopy(&lines, ds_steal_cstr(&line));
8628b0b7 900 }
867a2e3a 901 ovs_mutex_unlock(&log_file_mutex);
8628b0b7
JP
902
903 svec_sort(&lines);
71f21279
BP
904
905 char *line;
8628b0b7
JP
906 SVEC_FOR_EACH (i, line, &lines) {
907 ds_put_cstr(&s, line);
064af421 908 }
8628b0b7 909 svec_destroy(&lines);
064af421
BP
910
911 return ds_cstr(&s);
912}
913
532e1463
AA
914/* Returns as a string current logging patterns for each destination.
915 * This string must be released by caller. */
916char *
917vlog_get_patterns(void)
918{
919 struct ds ds = DS_EMPTY_INITIALIZER;
920 enum vlog_destination destination;
921
922 ovs_rwlock_rdlock(&pattern_rwlock);
923 ds_put_format(&ds, " prefix format\n");
924 ds_put_format(&ds, " ------ ------\n");
925
926 for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
ea53e3a8 927 struct destination *f = &destinations[destination];
532e1463
AA
928 const char *prefix = "none";
929
930 if (destination == VLF_SYSLOG && syslogger) {
931 prefix = syslog_get_prefix(syslogger);
932 }
933 ds_put_format(&ds, "%-7s %-32s %s\n", f->name, prefix, f->pattern);
934 }
935 ovs_rwlock_unlock(&pattern_rwlock);
936
937 return ds_cstr(&ds);
938}
939
064af421
BP
940/* Returns true if a log message emitted for the given 'module' and 'level'
941 * would cause some log output, false if that module and level are completely
942 * disabled. */
943bool
480ce8ab 944vlog_is_enabled(const struct vlog_module *module, enum vlog_level level)
064af421 945{
480ce8ab 946 return module->min_level >= level;
064af421
BP
947}
948
949static const char *
950fetch_braces(const char *p, const char *def, char *out, size_t out_size)
951{
952 if (*p == '{') {
953 size_t n = strcspn(p + 1, "}");
954 size_t n_copy = MIN(n, out_size - 1);
955 memcpy(out, p + 1, n_copy);
956 out[n_copy] = '\0';
957 p += n + 2;
958 } else {
959 ovs_strlcpy(out, def, out_size);
960 }
961 return p;
962}
963
964static void
480ce8ab 965format_log_message(const struct vlog_module *module, enum vlog_level level,
afc9f547
HM
966 const char *pattern, const char *message,
967 va_list args_, struct ds *s)
064af421
BP
968{
969 char tmp[128];
970 va_list args;
971 const char *p;
d69d61c7 972 int facility;
064af421
BP
973
974 ds_clear(s);
afc9f547 975 for (p = pattern; *p != '\0'; ) {
bc9fb3a9 976 const char *subprogram_name;
064af421 977 enum { LEFT, RIGHT } justify = RIGHT;
c9bc8c11 978 int pad = ' ';
064af421
BP
979 size_t length, field, used;
980
981 if (*p != '%') {
982 ds_put_char(s, *p++);
983 continue;
984 }
985
986 p++;
987 if (*p == '-') {
988 justify = LEFT;
989 p++;
990 }
991 if (*p == '0') {
992 pad = '0';
993 p++;
994 }
995 field = 0;
be2c418b 996 while (isdigit((unsigned char)*p)) {
064af421
BP
997 field = (field * 10) + (*p - '0');
998 p++;
999 }
1000
1001 length = s->length;
1002 switch (*p++) {
1003 case 'A':
1004 ds_put_cstr(s, program_name);
1005 break;
afc9f547 1006 case 'B':
d69d61c7
GS
1007 atomic_read_explicit(&log_facility, &facility,
1008 memory_order_relaxed);
1009 facility = facility ? facility : LOG_LOCAL0;
1010 ds_put_format(s, "%d", facility + syslog_levels[level]);
afc9f547 1011 break;
064af421
BP
1012 case 'c':
1013 p = fetch_braces(p, "", tmp, sizeof tmp);
1014 ds_put_cstr(s, vlog_get_module_name(module));
1015 break;
1016 case 'd':
2b31d8e7
PI
1017 p = fetch_braces(p, "%Y-%m-%d %H:%M:%S.###", tmp, sizeof tmp);
1018 ds_put_strftime_msec(s, tmp, time_wall_msec(), false);
b5d29991
GS
1019 break;
1020 case 'D':
2b31d8e7
PI
1021 p = fetch_braces(p, "%Y-%m-%d %H:%M:%S.###", tmp, sizeof tmp);
1022 ds_put_strftime_msec(s, tmp, time_wall_msec(), true);
064af421 1023 break;
afc9f547
HM
1024 case 'E':
1025 gethostname(tmp, sizeof tmp);
1026 tmp[sizeof tmp - 1] = '\0';
1027 ds_put_cstr(s, tmp);
1028 break;
064af421
BP
1029 case 'm':
1030 /* Format user-supplied log message and trim trailing new-lines. */
1031 length = s->length;
1032 va_copy(args, args_);
1033 ds_put_format_valist(s, message, args);
1034 va_end(args);
1035 while (s->length > length && s->string[s->length - 1] == '\n') {
1036 s->length--;
1037 }
1038 break;
1039 case 'N':
81d6495f 1040 ds_put_format(s, "%u", *msg_num_get_unsafe());
064af421
BP
1041 break;
1042 case 'n':
1043 ds_put_char(s, '\n');
1044 break;
1045 case 'p':
1046 ds_put_cstr(s, vlog_get_level_name(level));
1047 break;
1048 case 'P':
1049 ds_put_format(s, "%ld", (long int) getpid());
1050 break;
1051 case 'r':
4ae90ff9 1052 ds_put_format(s, "%lld", time_msec() - time_boot_msec());
064af421 1053 break;
781dee08 1054 case 't':
bc9fb3a9 1055 subprogram_name = get_subprogram_name();
781dee08
BP
1056 ds_put_cstr(s, subprogram_name[0] ? subprogram_name : "main");
1057 break;
1058 case 'T':
bc9fb3a9 1059 subprogram_name = get_subprogram_name();
781dee08
BP
1060 if (subprogram_name[0]) {
1061 ds_put_format(s, "(%s)", subprogram_name);
1062 }
1063 break;
064af421
BP
1064 default:
1065 ds_put_char(s, p[-1]);
1066 break;
1067 }
1068 used = s->length - length;
1069 if (used < field) {
1070 size_t n_pad = field - used;
1071 if (justify == RIGHT) {
1072 ds_put_uninit(s, n_pad);
1073 memmove(&s->string[length + n_pad], &s->string[length], used);
1074 memset(&s->string[length], pad, n_pad);
1075 } else {
1076 ds_put_char_multiple(s, pad, n_pad);
1077 }
1078 }
1079 }
1080}
1081
afc9f547
HM
1082/* Exports the given 'syslog_message' to the configured udp syslog sink. */
1083static void
1084send_to_syslog_fd(const char *s, size_t length)
1085 OVS_REQ_RDLOCK(pattern_rwlock)
1086{
1087 static size_t max_length = SIZE_MAX;
1088 size_t send_len = MIN(length, max_length);
1089
1090 while (write(syslog_fd, s, send_len) < 0 && errno == EMSGSIZE) {
1091 send_len -= send_len / 20;
1092 max_length = send_len;
1093 }
1094}
1095
064af421
BP
1096/* Writes 'message' to the log at the given 'level' and as coming from the
1097 * given 'module'.
1098 *
1099 * Guaranteed to preserve errno. */
1100void
480ce8ab 1101vlog_valist(const struct vlog_module *module, enum vlog_level level,
064af421
BP
1102 const char *message, va_list args)
1103{
480ce8ab
BP
1104 bool log_to_console = module->levels[VLF_CONSOLE] >= level;
1105 bool log_to_syslog = module->levels[VLF_SYSLOG] >= level;
542dbc5a
AI
1106 bool log_to_file = module->levels[VLF_FILE] >= level;
1107
1108 if (!(log_to_console || log_to_syslog || log_to_file)) {
1109 /* fast path - all logging levels specify no logging, no
1110 * need to hog the log mutex
1111 */
1112 return;
1113 }
97be1538
EJ
1114
1115 ovs_mutex_lock(&log_file_mutex);
542dbc5a 1116 log_to_file &= (log_fd >= 0);
97be1538 1117 ovs_mutex_unlock(&log_file_mutex);
064af421
BP
1118 if (log_to_console || log_to_syslog || log_to_file) {
1119 int save_errno = errno;
064af421
BP
1120 struct ds s;
1121
1e8cf0f7
BP
1122 vlog_init();
1123
064af421
BP
1124 ds_init(&s);
1125 ds_reserve(&s, 1024);
81d6495f 1126 ++*msg_num_get();
064af421 1127
97be1538 1128 ovs_rwlock_rdlock(&pattern_rwlock);
064af421 1129 if (log_to_console) {
d5460484
GS
1130 format_log_message(module, level,
1131 destinations[VLF_CONSOLE].pattern, message,
1132 args, &s);
064af421
BP
1133 ds_put_char(&s, '\n');
1134 fputs(ds_cstr(&s), stderr);
1135 }
1136
1137 if (log_to_syslog) {
1138 int syslog_level = syslog_levels[level];
1139 char *save_ptr = NULL;
1140 char *line;
d69d61c7 1141 int facility;
064af421 1142
d5460484 1143 format_log_message(module, level, destinations[VLF_SYSLOG].pattern,
afc9f547 1144 message, args, &s);
064af421
BP
1145 for (line = strtok_r(s.string, "\n", &save_ptr); line;
1146 line = strtok_r(NULL, "\n", &save_ptr)) {
d69d61c7
GS
1147 atomic_read_explicit(&log_facility, &facility,
1148 memory_order_relaxed);
fe089c0d 1149 syslogger->class->syslog(syslogger, syslog_level|facility, line);
064af421 1150 }
afc9f547
HM
1151
1152 if (syslog_fd >= 0) {
1153 format_log_message(module, level,
1154 "<%B>1 %D{%Y-%m-%dT%H:%M:%S.###Z} "
1155 "%E %A %P %c - \xef\xbb\xbf%m",
1156 message, args, &s);
1157 send_to_syslog_fd(ds_cstr(&s), s.length);
1158 }
064af421
BP
1159 }
1160
1161 if (log_to_file) {
d5460484 1162 format_log_message(module, level, destinations[VLF_FILE].pattern,
afc9f547 1163 message, args, &s);
064af421 1164 ds_put_char(&s, '\n');
81d6495f 1165
97be1538 1166 ovs_mutex_lock(&log_file_mutex);
81d6495f 1167 if (log_fd >= 0) {
888e0cf4
BP
1168 if (log_writer) {
1169 async_append_write(log_writer, s.string, s.length);
1170 if (level == VLL_EMER) {
1171 async_append_flush(log_writer);
1172 }
1173 } else {
1174 ignore(write(log_fd, s.string, s.length));
81d6495f 1175 }
a5fb0e29 1176 }
97be1538 1177 ovs_mutex_unlock(&log_file_mutex);
064af421 1178 }
97be1538 1179 ovs_rwlock_unlock(&pattern_rwlock);
064af421
BP
1180
1181 ds_destroy(&s);
1182 errno = save_errno;
1183 }
1184}
1185
1186void
480ce8ab
BP
1187vlog(const struct vlog_module *module, enum vlog_level level,
1188 const char *message, ...)
064af421
BP
1189{
1190 va_list args;
1191
1192 va_start(args, message);
1193 vlog_valist(module, level, message, args);
1194 va_end(args);
1195}
1196
d41d4b71
BP
1197/* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
1198 * exit code. Always writes the message to stderr, even if the console
d5460484 1199 * destination is disabled.
d41d4b71
BP
1200 *
1201 * Choose this function instead of vlog_abort_valist() if the daemon monitoring
1202 * facility shouldn't automatically restart the current daemon. */
279c9e03 1203void
c1a543a8 1204vlog_fatal_valist(const struct vlog_module *module_,
279c9e03
BP
1205 const char *message, va_list args)
1206{
ebc56baa 1207 struct vlog_module *module = CONST_CAST(struct vlog_module *, module_);
279c9e03
BP
1208
1209 /* Don't log this message to the console to avoid redundancy with the
1210 * message written by the later ovs_fatal_valist(). */
c1a543a8 1211 module->levels[VLF_CONSOLE] = VLL_OFF;
279c9e03 1212
c1a543a8 1213 vlog_valist(module, VLL_EMER, message, args);
279c9e03
BP
1214 ovs_fatal_valist(0, message, args);
1215}
1216
d41d4b71
BP
1217/* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
1218 * exit code. Always writes the message to stderr, even if the console
d5460484 1219 * destination is disabled.
d41d4b71
BP
1220 *
1221 * Choose this function instead of vlog_abort() if the daemon monitoring
1222 * facility shouldn't automatically restart the current daemon. */
279c9e03 1223void
c1a543a8 1224vlog_fatal(const struct vlog_module *module, const char *message, ...)
279c9e03
BP
1225{
1226 va_list args;
1227
1228 va_start(args, message);
c1a543a8 1229 vlog_fatal_valist(module, message, args);
279c9e03
BP
1230 va_end(args);
1231}
1232
d41d4b71 1233/* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
d5460484 1234 * writes the message to stderr, even if the console destination is disabled.
d41d4b71
BP
1235 *
1236 * Choose this function instead of vlog_fatal_valist() if the daemon monitoring
1237 * facility should automatically restart the current daemon. */
1238void
1239vlog_abort_valist(const struct vlog_module *module_,
1240 const char *message, va_list args)
1241{
1242 struct vlog_module *module = (struct vlog_module *) module_;
1243
1244 /* Don't log this message to the console to avoid redundancy with the
1245 * message written by the later ovs_abort_valist(). */
1246 module->levels[VLF_CONSOLE] = VLL_OFF;
1247
1248 vlog_valist(module, VLL_EMER, message, args);
1249 ovs_abort_valist(0, message, args);
1250}
1251
1252/* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
d5460484 1253 * writes the message to stderr, even if the console destination is disabled.
d41d4b71
BP
1254 *
1255 * Choose this function instead of vlog_fatal() if the daemon monitoring
1256 * facility should automatically restart the current daemon. */
1257void
1258vlog_abort(const struct vlog_module *module, const char *message, ...)
1259{
1260 va_list args;
1261
1262 va_start(args, message);
1263 vlog_abort_valist(module, message, args);
1264 va_end(args);
1265}
1266
064af421 1267bool
480ce8ab 1268vlog_should_drop(const struct vlog_module *module, enum vlog_level level,
064af421
BP
1269 struct vlog_rate_limit *rl)
1270{
4958e3ee
BP
1271 if (!module->honor_rate_limits) {
1272 return false;
1273 }
1274
064af421
BP
1275 if (!vlog_is_enabled(module, level)) {
1276 return true;
1277 }
1278
97be1538 1279 ovs_mutex_lock(&rl->mutex);
648f4f1f 1280 if (!token_bucket_withdraw(&rl->token_bucket, VLOG_MSG_TOKENS)) {
064af421 1281 time_t now = time_now();
648f4f1f
BP
1282 if (!rl->n_dropped) {
1283 rl->first_dropped = now;
064af421 1284 }
648f4f1f
BP
1285 rl->last_dropped = now;
1286 rl->n_dropped++;
97be1538 1287 ovs_mutex_unlock(&rl->mutex);
648f4f1f 1288 return true;
064af421 1289 }
064af421 1290
fda28014 1291 if (!rl->n_dropped) {
97be1538 1292 ovs_mutex_unlock(&rl->mutex);
fda28014 1293 } else {
e2eed6a7 1294 time_t now = time_now();
fda28014 1295 unsigned int n_dropped = rl->n_dropped;
e2eed6a7
BP
1296 unsigned int first_dropped_elapsed = now - rl->first_dropped;
1297 unsigned int last_dropped_elapsed = now - rl->last_dropped;
fda28014 1298 rl->n_dropped = 0;
97be1538 1299 ovs_mutex_unlock(&rl->mutex);
e2eed6a7 1300
064af421 1301 vlog(module, level,
e2eed6a7
BP
1302 "Dropped %u log messages in last %u seconds (most recently, "
1303 "%u seconds ago) due to excessive rate",
fda28014 1304 n_dropped, first_dropped_elapsed, last_dropped_elapsed);
064af421 1305 }
fda28014 1306
064af421
BP
1307 return false;
1308}
1309
1310void
480ce8ab 1311vlog_rate_limit(const struct vlog_module *module, enum vlog_level level,
064af421
BP
1312 struct vlog_rate_limit *rl, const char *message, ...)
1313{
1314 if (!vlog_should_drop(module, level, rl)) {
1315 va_list args;
1316
1317 va_start(args, message);
1318 vlog_valist(module, level, message, args);
1319 va_end(args);
1320 }
1321}
1322
1323void
d295e8e9 1324vlog_usage(void)
064af421 1325{
afc9f547
HM
1326 printf("\n\
1327Logging options:\n\
1328 -vSPEC, --verbose=SPEC set logging levels\n\
1329 -v, --verbose set maximum verbosity level\n\
1330 --log-file[=FILE] enable logging to specified FILE\n\
1331 (default: %s/%s.log)\n\
fe089c0d
AA
1332 --syslog-method=(libc|unix:file|udp:ip:port)\n\
1333 specify how to send messages to syslog daemon\n\
afc9f547 1334 --syslog-target=HOST:PORT also send syslog msgs to HOST:PORT via UDP\n",
b43c6fe2 1335 ovs_logdir(), program_name);
064af421 1336}