2 * Copyright (c) 2008, 2009, 2010, 2011, 2012, 2013 Nicira, Inc.
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:
8 * http://www.apache.org/licenses/LICENSE-2.0
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.
27 #include <sys/types.h>
31 #include "async-append.h"
34 #include "dynamic-string.h"
36 #include "ovs-thread.h"
43 VLOG_DEFINE_THIS_MODULE(vlog
);
45 COVERAGE_DEFINE(vlog_recursive
);
47 /* ovs_assert() logs the assertion message, so using ovs_assert() in this
48 * source file could cause recursion. */
50 #define ovs_assert use_assert_instead_of_ovs_assert_in_this_module
52 /* Name for each logging level. */
53 static const char *const level_names
[VLL_N_LEVELS
] = {
54 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) #NAME,
59 /* Syslog value for each logging level. */
60 static const int syslog_levels
[VLL_N_LEVELS
] = {
61 #define VLOG_LEVEL(NAME, SYSLOG_LEVEL) SYSLOG_LEVEL,
66 /* The log modules. */
67 #if USE_LINKER_SECTIONS
68 extern struct vlog_module
*__start_vlog_modules
[];
69 extern struct vlog_module
*__stop_vlog_modules
[];
70 #define vlog_modules __start_vlog_modules
71 #define n_vlog_modules (__stop_vlog_modules - __start_vlog_modules)
73 #define VLOG_MODULE VLOG_DEFINE_MODULE__
74 #include "vlog-modules.def"
77 struct vlog_module
*vlog_modules
[] = {
78 #define VLOG_MODULE(NAME) &VLM_##NAME,
79 #include "vlog-modules.def"
82 #define n_vlog_modules ARRAY_SIZE(vlog_modules)
85 /* Information about each facility. */
87 const char *name
; /* Name. */
88 char *pattern
; /* Current pattern (see 'pattern_rwlock'). */
89 bool default_pattern
; /* Whether current pattern is the default. */
91 static struct facility facilities
[VLF_N_FACILITIES
] = {
92 #define VLOG_FACILITY(NAME, PATTERN) {#NAME, PATTERN, true},
97 /* Protects the 'pattern' in all "struct facility"s, so that a race between
98 * changing and reading the pattern does not cause an access to freed
100 static pthread_rwlock_t pattern_rwlock
= PTHREAD_RWLOCK_INITIALIZER
;
102 /* Sequence number for the message currently being composed. */
103 DEFINE_PER_THREAD_DATA(unsigned int, msg_num
, 0);
105 /* VLF_FILE configuration.
107 * All of the following is protected by 'log_file_mutex', which nests inside
109 static pthread_mutex_t log_file_mutex
= PTHREAD_ADAPTIVE_MUTEX_INITIALIZER
;
110 static char *log_file_name
;
111 static int log_fd
= -1;
112 static struct async_append
*log_writer
;
114 static void format_log_message(const struct vlog_module
*, enum vlog_level
,
116 const char *message
, va_list, struct ds
*)
119 /* Searches the 'n_names' in 'names'. Returns the index of a match for
120 * 'target', or 'n_names' if no name matches. */
122 search_name_array(const char *target
, const char *const *names
, size_t n_names
)
126 for (i
= 0; i
< n_names
; i
++) {
128 if (!strcasecmp(names
[i
], target
)) {
135 /* Returns the name for logging level 'level'. */
137 vlog_get_level_name(enum vlog_level level
)
139 assert(level
< VLL_N_LEVELS
);
140 return level_names
[level
];
143 /* Returns the logging level with the given 'name', or VLL_N_LEVELS if 'name'
144 * is not the name of a logging level. */
146 vlog_get_level_val(const char *name
)
148 return search_name_array(name
, level_names
, ARRAY_SIZE(level_names
));
151 /* Returns the name for logging facility 'facility'. */
153 vlog_get_facility_name(enum vlog_facility facility
)
155 assert(facility
< VLF_N_FACILITIES
);
156 return facilities
[facility
].name
;
159 /* Returns the logging facility named 'name', or VLF_N_FACILITIES if 'name' is
160 * not the name of a logging facility. */
162 vlog_get_facility_val(const char *name
)
166 for (i
= 0; i
< VLF_N_FACILITIES
; i
++) {
167 if (!strcasecmp(facilities
[i
].name
, name
)) {
174 /* Returns the name for logging module 'module'. */
176 vlog_get_module_name(const struct vlog_module
*module
)
181 /* Returns the logging module named 'name', or NULL if 'name' is not the name
182 * of a logging module. */
184 vlog_module_from_name(const char *name
)
186 struct vlog_module
**mp
;
188 for (mp
= vlog_modules
; mp
< &vlog_modules
[n_vlog_modules
]; mp
++) {
189 if (!strcasecmp(name
, (*mp
)->name
)) {
196 /* Returns the current logging level for the given 'module' and 'facility'. */
198 vlog_get_level(const struct vlog_module
*module
, enum vlog_facility facility
)
200 assert(facility
< VLF_N_FACILITIES
);
201 return module
->levels
[facility
];
204 static void OVS_MUST_HOLD(log_file_mutex
)
205 update_min_level(struct vlog_module
*module
)
207 enum vlog_facility facility
;
209 module
->min_level
= VLL_OFF
;
210 for (facility
= 0; facility
< VLF_N_FACILITIES
; facility
++) {
211 if (log_fd
>= 0 || facility
!= VLF_FILE
) {
212 enum vlog_level level
= module
->levels
[facility
];
213 if (level
> module
->min_level
) {
214 module
->min_level
= level
;
221 set_facility_level(enum vlog_facility facility
, struct vlog_module
*module
,
222 enum vlog_level level
)
224 assert(facility
>= 0 && facility
< VLF_N_FACILITIES
);
225 assert(level
< VLL_N_LEVELS
);
227 xpthread_mutex_lock(&log_file_mutex
);
229 struct vlog_module
**mp
;
231 for (mp
= vlog_modules
; mp
< &vlog_modules
[n_vlog_modules
]; mp
++) {
232 (*mp
)->levels
[facility
] = level
;
233 update_min_level(*mp
);
236 module
->levels
[facility
] = level
;
237 update_min_level(module
);
239 xpthread_mutex_unlock(&log_file_mutex
);
242 /* Sets the logging level for the given 'module' and 'facility' to 'level'. A
243 * null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
244 * across all modules or facilities, respectively. */
246 vlog_set_levels(struct vlog_module
*module
, enum vlog_facility facility
,
247 enum vlog_level level
)
249 assert(facility
< VLF_N_FACILITIES
|| facility
== VLF_ANY_FACILITY
);
250 if (facility
== VLF_ANY_FACILITY
) {
251 for (facility
= 0; facility
< VLF_N_FACILITIES
; facility
++) {
252 set_facility_level(facility
, module
, level
);
255 set_facility_level(facility
, module
, level
);
260 do_set_pattern(enum vlog_facility facility
, const char *pattern
)
262 struct facility
*f
= &facilities
[facility
];
264 xpthread_rwlock_wrlock(&pattern_rwlock
);
265 if (!f
->default_pattern
) {
268 f
->default_pattern
= false;
270 f
->pattern
= xstrdup(pattern
);
271 xpthread_rwlock_unlock(&pattern_rwlock
);
274 /* Sets the pattern for the given 'facility' to 'pattern'. */
276 vlog_set_pattern(enum vlog_facility facility
, const char *pattern
)
278 assert(facility
< VLF_N_FACILITIES
|| facility
== VLF_ANY_FACILITY
);
279 if (facility
== VLF_ANY_FACILITY
) {
280 for (facility
= 0; facility
< VLF_N_FACILITIES
; facility
++) {
281 do_set_pattern(facility
, pattern
);
284 do_set_pattern(facility
, pattern
);
288 /* Sets the name of the log file used by VLF_FILE to 'file_name', or to the
289 * default file name if 'file_name' is null. Returns 0 if successful,
290 * otherwise a positive errno value. */
292 vlog_set_log_file(const char *file_name
)
294 char *new_log_file_name
;
295 struct vlog_module
**mp
;
296 struct stat old_stat
;
297 struct stat new_stat
;
301 /* Open new log file. */
302 new_log_file_name
= (file_name
304 : xasprintf("%s/%s.log", ovs_logdir(), program_name
));
305 new_log_fd
= open(new_log_file_name
, O_WRONLY
| O_CREAT
| O_APPEND
, 0666);
306 if (new_log_fd
< 0) {
307 VLOG_WARN("failed to open %s for logging: %s",
308 new_log_file_name
, ovs_strerror(errno
));
309 free(new_log_file_name
);
313 /* If the new log file is the same one we already have open, bail out. */
314 xpthread_mutex_lock(&log_file_mutex
);
315 same_file
= (log_fd
>= 0
317 && !fstat(log_fd
, &old_stat
)
318 && !fstat(new_log_fd
, &new_stat
)
319 && old_stat
.st_dev
== new_stat
.st_dev
320 && old_stat
.st_ino
== new_stat
.st_ino
);
321 xpthread_mutex_unlock(&log_file_mutex
);
324 free(new_log_file_name
);
328 /* Log closing old log file (we can't log while holding log_file_mutex). */
330 VLOG_INFO("closing log file");
333 /* Close old log file, if any, and install new one. */
334 xpthread_mutex_lock(&log_file_mutex
);
338 async_append_destroy(log_writer
);
341 log_file_name
= xstrdup(new_log_file_name
);
343 log_writer
= async_append_create(new_log_fd
);
345 for (mp
= vlog_modules
; mp
< &vlog_modules
[n_vlog_modules
]; mp
++) {
346 update_min_level(*mp
);
348 xpthread_mutex_unlock(&log_file_mutex
);
350 /* Log opening new log file (we can't log while holding log_file_mutex). */
351 VLOG_INFO("opened log file %s", new_log_file_name
);
352 free(new_log_file_name
);
357 /* Closes and then attempts to re-open the current log file. (This is useful
358 * just after log rotation, to ensure that the new log file starts being used.)
359 * Returns 0 if successful, otherwise a positive errno value. */
361 vlog_reopen_log_file(void)
365 xpthread_mutex_lock(&log_file_mutex
);
366 fn
= log_file_name
? xstrdup(log_file_name
) : NULL
;
367 xpthread_mutex_unlock(&log_file_mutex
);
370 int error
= vlog_set_log_file(fn
);
378 /* Set debugging levels. Returns null if successful, otherwise an error
379 * message that the caller must free(). */
381 vlog_set_levels_from_string(const char *s_
)
383 char *s
= xstrdup(s_
);
384 char *save_ptr
= NULL
;
388 word
= strtok_r(s
, " ,:\t", &save_ptr
);
389 if (word
&& !strcasecmp(word
, "PATTERN")) {
390 enum vlog_facility facility
;
392 word
= strtok_r(NULL
, " ,:\t", &save_ptr
);
394 msg
= xstrdup("missing facility");
398 facility
= (!strcasecmp(word
, "ANY")
400 : vlog_get_facility_val(word
));
401 if (facility
== VLF_N_FACILITIES
) {
402 msg
= xasprintf("unknown facility \"%s\"", word
);
405 vlog_set_pattern(facility
, save_ptr
);
407 struct vlog_module
*module
= NULL
;
408 enum vlog_level level
= VLL_N_LEVELS
;
409 enum vlog_facility facility
= VLF_N_FACILITIES
;
411 for (; word
!= NULL
; word
= strtok_r(NULL
, " ,:\t", &save_ptr
)) {
412 if (!strcasecmp(word
, "ANY")) {
414 } else if (vlog_get_facility_val(word
) != VLF_N_FACILITIES
) {
415 if (facility
!= VLF_N_FACILITIES
) {
416 msg
= xstrdup("cannot specify multiple facilities");
419 facility
= vlog_get_facility_val(word
);
420 } else if (vlog_get_level_val(word
) != VLL_N_LEVELS
) {
421 if (level
!= VLL_N_LEVELS
) {
422 msg
= xstrdup("cannot specify multiple levels");
425 level
= vlog_get_level_val(word
);
426 } else if (vlog_module_from_name(word
)) {
428 msg
= xstrdup("cannot specify multiple modules");
431 module
= vlog_module_from_name(word
);
433 msg
= xasprintf("no facility, level, or module \"%s\"", word
);
438 if (facility
== VLF_N_FACILITIES
) {
439 facility
= VLF_ANY_FACILITY
;
441 if (level
== VLL_N_LEVELS
) {
444 vlog_set_levels(module
, facility
, level
);
452 /* Set debugging levels. Abort with an error message if 's' is invalid. */
454 vlog_set_levels_from_string_assert(const char *s
)
456 char *error
= vlog_set_levels_from_string(s
);
458 ovs_fatal(0, "%s", error
);
462 /* If 'arg' is null, configure maximum verbosity. Otherwise, sets
463 * configuration according to 'arg' (see vlog_set_levels_from_string()). */
465 vlog_set_verbosity(const char *arg
)
468 char *msg
= vlog_set_levels_from_string(arg
);
470 ovs_fatal(0, "processing \"%s\": %s", arg
, msg
);
473 vlog_set_levels(NULL
, VLF_ANY_FACILITY
, VLL_DBG
);
478 vlog_unixctl_set(struct unixctl_conn
*conn
, int argc
, const char *argv
[],
479 void *aux OVS_UNUSED
)
483 for (i
= 1; i
< argc
; i
++) {
484 char *msg
= vlog_set_levels_from_string(argv
[i
]);
486 unixctl_command_reply_error(conn
, msg
);
491 unixctl_command_reply(conn
, NULL
);
495 vlog_unixctl_list(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
496 const char *argv
[] OVS_UNUSED
, void *aux OVS_UNUSED
)
498 char *msg
= vlog_get_levels();
499 unixctl_command_reply(conn
, msg
);
504 vlog_unixctl_reopen(struct unixctl_conn
*conn
, int argc OVS_UNUSED
,
505 const char *argv
[] OVS_UNUSED
, void *aux OVS_UNUSED
)
508 int error
= vlog_reopen_log_file();
510 unixctl_command_reply_error(conn
, ovs_strerror(errno
));
512 unixctl_command_reply(conn
, NULL
);
515 unixctl_command_reply_error(conn
, "Logging to file not configured");
520 set_all_rate_limits(bool enable
)
522 struct vlog_module
**mp
;
524 for (mp
= vlog_modules
; mp
< &vlog_modules
[n_vlog_modules
]; mp
++) {
525 (*mp
)->honor_rate_limits
= enable
;
530 set_rate_limits(struct unixctl_conn
*conn
, int argc
,
531 const char *argv
[], bool enable
)
536 for (i
= 1; i
< argc
; i
++) {
537 if (!strcasecmp(argv
[i
], "ANY")) {
538 set_all_rate_limits(enable
);
540 struct vlog_module
*module
= vlog_module_from_name(argv
[i
]);
542 unixctl_command_reply_error(conn
, "unknown module");
545 module
->honor_rate_limits
= enable
;
549 set_all_rate_limits(enable
);
551 unixctl_command_reply(conn
, NULL
);
555 vlog_enable_rate_limit(struct unixctl_conn
*conn
, int argc
,
556 const char *argv
[], void *aux OVS_UNUSED
)
558 set_rate_limits(conn
, argc
, argv
, true);
562 vlog_disable_rate_limit(struct unixctl_conn
*conn
, int argc
,
563 const char *argv
[], void *aux OVS_UNUSED
)
565 set_rate_limits(conn
, argc
, argv
, false);
571 static char *program_name_copy
;
574 /* openlog() is allowed to keep the pointer passed in, without making a
575 * copy. The daemonize code sometimes frees and replaces 'program_name',
576 * so make a private copy just for openlog(). (We keep a pointer to the
577 * private copy to suppress memory leak warnings in case openlog() does
578 * make its own copy.) */
579 program_name_copy
= program_name
? xstrdup(program_name
) : NULL
;
580 openlog(program_name_copy
, LOG_NDELAY
, LOG_DAEMON
);
584 char *s
= xastrftime("%a, %d %b %Y %H:%M:%S", now
, true);
585 VLOG_ERR("current time is negative: %s (%ld)", s
, (long int) now
);
589 unixctl_command_register(
590 "vlog/set", "{spec | PATTERN:facility:pattern}",
591 1, INT_MAX
, vlog_unixctl_set
, NULL
);
592 unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list
, NULL
);
593 unixctl_command_register("vlog/enable-rate-limit", "[module]...",
594 0, INT_MAX
, vlog_enable_rate_limit
, NULL
);
595 unixctl_command_register("vlog/disable-rate-limit", "[module]...",
596 0, INT_MAX
, vlog_disable_rate_limit
, NULL
);
597 unixctl_command_register("vlog/reopen", "", 0, 0,
598 vlog_unixctl_reopen
, NULL
);
601 /* Initializes the logging subsystem and registers its unixctl server
606 static pthread_once_t once
= PTHREAD_ONCE_INIT
;
607 pthread_once(&once
, vlog_init__
);
610 /* Print the current logging level for each module. */
612 vlog_get_levels(void)
614 struct ds s
= DS_EMPTY_INITIALIZER
;
615 struct vlog_module
**mp
;
616 struct svec lines
= SVEC_EMPTY_INITIALIZER
;
620 ds_put_format(&s
, " console syslog file\n");
621 ds_put_format(&s
, " ------- ------ ------\n");
623 for (mp
= vlog_modules
; mp
< &vlog_modules
[n_vlog_modules
]; mp
++) {
627 ds_put_format(&line
, "%-16s %4s %4s %4s",
628 vlog_get_module_name(*mp
),
629 vlog_get_level_name(vlog_get_level(*mp
, VLF_CONSOLE
)),
630 vlog_get_level_name(vlog_get_level(*mp
, VLF_SYSLOG
)),
631 vlog_get_level_name(vlog_get_level(*mp
, VLF_FILE
)));
632 if (!(*mp
)->honor_rate_limits
) {
633 ds_put_cstr(&line
, " (rate limiting disabled)");
635 ds_put_char(&line
, '\n');
637 svec_add_nocopy(&lines
, ds_steal_cstr(&line
));
641 SVEC_FOR_EACH (i
, line
, &lines
) {
642 ds_put_cstr(&s
, line
);
644 svec_destroy(&lines
);
649 /* Returns true if a log message emitted for the given 'module' and 'level'
650 * would cause some log output, false if that module and level are completely
653 vlog_is_enabled(const struct vlog_module
*module
, enum vlog_level level
)
655 return module
->min_level
>= level
;
659 fetch_braces(const char *p
, const char *def
, char *out
, size_t out_size
)
662 size_t n
= strcspn(p
+ 1, "}");
663 size_t n_copy
= MIN(n
, out_size
- 1);
664 memcpy(out
, p
+ 1, n_copy
);
668 ovs_strlcpy(out
, def
, out_size
);
674 format_log_message(const struct vlog_module
*module
, enum vlog_level level
,
675 enum vlog_facility facility
,
676 const char *message
, va_list args_
, struct ds
*s
)
683 for (p
= facilities
[facility
].pattern
; *p
!= '\0'; ) {
684 const char *subprogram_name
;
685 enum { LEFT
, RIGHT
} justify
= RIGHT
;
687 size_t length
, field
, used
;
690 ds_put_char(s
, *p
++);
704 while (isdigit((unsigned char)*p
)) {
705 field
= (field
* 10) + (*p
- '0');
712 ds_put_cstr(s
, program_name
);
715 p
= fetch_braces(p
, "", tmp
, sizeof tmp
);
716 ds_put_cstr(s
, vlog_get_module_name(module
));
719 p
= fetch_braces(p
, "%Y-%m-%d %H:%M:%S", tmp
, sizeof tmp
);
720 ds_put_strftime(s
, tmp
, time_wall(), false);
723 p
= fetch_braces(p
, "%Y-%m-%d %H:%M:%S", tmp
, sizeof tmp
);
724 ds_put_strftime(s
, tmp
, time_wall(), true);
727 /* Format user-supplied log message and trim trailing new-lines. */
729 va_copy(args
, args_
);
730 ds_put_format_valist(s
, message
, args
);
732 while (s
->length
> length
&& s
->string
[s
->length
- 1] == '\n') {
737 ds_put_format(s
, "%u", *msg_num_get_unsafe());
740 ds_put_char(s
, '\n');
743 ds_put_cstr(s
, vlog_get_level_name(level
));
746 ds_put_format(s
, "%ld", (long int) getpid());
749 ds_put_format(s
, "%lld", time_msec() - time_boot_msec());
752 subprogram_name
= get_subprogram_name();
753 ds_put_cstr(s
, subprogram_name
[0] ? subprogram_name
: "main");
756 subprogram_name
= get_subprogram_name();
757 if (subprogram_name
[0]) {
758 ds_put_format(s
, "(%s)", subprogram_name
);
762 ds_put_char(s
, p
[-1]);
765 used
= s
->length
- length
;
767 size_t n_pad
= field
- used
;
768 if (justify
== RIGHT
) {
769 ds_put_uninit(s
, n_pad
);
770 memmove(&s
->string
[length
+ n_pad
], &s
->string
[length
], used
);
771 memset(&s
->string
[length
], pad
, n_pad
);
773 ds_put_char_multiple(s
, pad
, n_pad
);
779 /* Writes 'message' to the log at the given 'level' and as coming from the
782 * Guaranteed to preserve errno. */
784 vlog_valist(const struct vlog_module
*module
, enum vlog_level level
,
785 const char *message
, va_list args
)
787 bool log_to_console
= module
->levels
[VLF_CONSOLE
] >= level
;
788 bool log_to_syslog
= module
->levels
[VLF_SYSLOG
] >= level
;
789 bool log_to_file
= module
->levels
[VLF_FILE
] >= level
&& log_fd
>= 0;
790 if (log_to_console
|| log_to_syslog
|| log_to_file
) {
791 int save_errno
= errno
;
797 ds_reserve(&s
, 1024);
800 xpthread_rwlock_rdlock(&pattern_rwlock
);
801 if (log_to_console
) {
802 format_log_message(module
, level
, VLF_CONSOLE
, message
, args
, &s
);
803 ds_put_char(&s
, '\n');
804 fputs(ds_cstr(&s
), stderr
);
808 int syslog_level
= syslog_levels
[level
];
809 char *save_ptr
= NULL
;
812 format_log_message(module
, level
, VLF_SYSLOG
, message
, args
, &s
);
813 for (line
= strtok_r(s
.string
, "\n", &save_ptr
); line
;
814 line
= strtok_r(NULL
, "\n", &save_ptr
)) {
815 syslog(syslog_level
, "%s", line
);
820 format_log_message(module
, level
, VLF_FILE
, message
, args
, &s
);
821 ds_put_char(&s
, '\n');
823 xpthread_mutex_lock(&log_file_mutex
);
825 async_append_write(log_writer
, s
.string
, s
.length
);
826 if (level
== VLL_EMER
) {
827 async_append_flush(log_writer
);
830 xpthread_mutex_unlock(&log_file_mutex
);
832 xpthread_rwlock_unlock(&pattern_rwlock
);
840 vlog(const struct vlog_module
*module
, enum vlog_level level
,
841 const char *message
, ...)
845 va_start(args
, message
);
846 vlog_valist(module
, level
, message
, args
);
850 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
851 * exit code. Always writes the message to stderr, even if the console
852 * facility is disabled.
854 * Choose this function instead of vlog_abort_valist() if the daemon monitoring
855 * facility shouldn't automatically restart the current daemon. */
857 vlog_fatal_valist(const struct vlog_module
*module_
,
858 const char *message
, va_list args
)
860 struct vlog_module
*module
= CONST_CAST(struct vlog_module
*, module_
);
862 /* Don't log this message to the console to avoid redundancy with the
863 * message written by the later ovs_fatal_valist(). */
864 module
->levels
[VLF_CONSOLE
] = VLL_OFF
;
866 vlog_valist(module
, VLL_EMER
, message
, args
);
867 ovs_fatal_valist(0, message
, args
);
870 /* Logs 'message' to 'module' at maximum verbosity, then exits with a failure
871 * exit code. Always writes the message to stderr, even if the console
872 * facility is disabled.
874 * Choose this function instead of vlog_abort() if the daemon monitoring
875 * facility shouldn't automatically restart the current daemon. */
877 vlog_fatal(const struct vlog_module
*module
, const char *message
, ...)
881 va_start(args
, message
);
882 vlog_fatal_valist(module
, message
, args
);
886 /* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
887 * writes the message to stderr, even if the console facility is disabled.
889 * Choose this function instead of vlog_fatal_valist() if the daemon monitoring
890 * facility should automatically restart the current daemon. */
892 vlog_abort_valist(const struct vlog_module
*module_
,
893 const char *message
, va_list args
)
895 struct vlog_module
*module
= (struct vlog_module
*) module_
;
897 /* Don't log this message to the console to avoid redundancy with the
898 * message written by the later ovs_abort_valist(). */
899 module
->levels
[VLF_CONSOLE
] = VLL_OFF
;
901 vlog_valist(module
, VLL_EMER
, message
, args
);
902 ovs_abort_valist(0, message
, args
);
905 /* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
906 * writes the message to stderr, even if the console facility is disabled.
908 * Choose this function instead of vlog_fatal() if the daemon monitoring
909 * facility should automatically restart the current daemon. */
911 vlog_abort(const struct vlog_module
*module
, const char *message
, ...)
915 va_start(args
, message
);
916 vlog_abort_valist(module
, message
, args
);
921 vlog_should_drop(const struct vlog_module
*module
, enum vlog_level level
,
922 struct vlog_rate_limit
*rl
)
924 if (!module
->honor_rate_limits
) {
928 if (!vlog_is_enabled(module
, level
)) {
932 xpthread_mutex_lock(&rl
->mutex
);
933 if (!token_bucket_withdraw(&rl
->token_bucket
, VLOG_MSG_TOKENS
)) {
934 time_t now
= time_now();
935 if (!rl
->n_dropped
) {
936 rl
->first_dropped
= now
;
938 rl
->last_dropped
= now
;
940 xpthread_mutex_unlock(&rl
->mutex
);
944 if (!rl
->n_dropped
) {
945 xpthread_mutex_unlock(&rl
->mutex
);
947 time_t now
= time_now();
948 unsigned int n_dropped
= rl
->n_dropped
;
949 unsigned int first_dropped_elapsed
= now
- rl
->first_dropped
;
950 unsigned int last_dropped_elapsed
= now
- rl
->last_dropped
;
952 xpthread_mutex_unlock(&rl
->mutex
);
955 "Dropped %u log messages in last %u seconds (most recently, "
956 "%u seconds ago) due to excessive rate",
957 n_dropped
, first_dropped_elapsed
, last_dropped_elapsed
);
964 vlog_rate_limit(const struct vlog_module
*module
, enum vlog_level level
,
965 struct vlog_rate_limit
*rl
, const char *message
, ...)
967 if (!vlog_should_drop(module
, level
, rl
)) {
970 va_start(args
, message
);
971 vlog_valist(module
, level
, message
, args
);
979 printf("\nLogging options:\n"
980 " -v, --verbose=[SPEC] set logging levels\n"
981 " -v, --verbose set maximum verbosity level\n"
982 " --log-file[=FILE] enable logging to specified FILE\n"
983 " (default: %s/%s.log)\n",
984 ovs_logdir(), program_name
);