75
78
BUILD_ASSERT_DECL(LOG_LOCAL0 == (16 << 3));
77
80
/* The log modules. */
78
struct list vlog_modules = LIST_INITIALIZER(&vlog_modules);
81
struct ovs_list vlog_modules = OVS_LIST_INITIALIZER(&vlog_modules);
80
/* Protects the 'pattern' in all "struct facility"s, so that a race between
83
/* Protects the 'pattern' in all "struct destination"s, so that a race between
81
84
* changing and reading the pattern does not cause an access to freed
83
86
static struct ovs_rwlock pattern_rwlock = OVS_RWLOCK_INITIALIZER;
85
/* Information about each facility. */
88
/* Information about each destination. */
87
90
const char *name; /* Name. */
88
91
char *pattern OVS_GUARDED_BY(pattern_rwlock); /* Current pattern. */
89
92
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},
94
static struct destination destinations[VLF_N_DESTINATIONS] = {
95
#define VLOG_DESTINATION(NAME, PATTERN) {#NAME, PATTERN, true},
97
#undef VLOG_DESTINATION
97
100
/* Sequence number for the message currently being composed. */
106
109
static int log_fd OVS_GUARDED_BY(log_file_mutex) = -1;
107
110
static struct async_append *log_writer OVS_GUARDED_BY(log_file_mutex);
108
111
static bool log_async OVS_GUARDED_BY(log_file_mutex);
112
static struct syslogger *syslogger = NULL;
110
114
/* Syslog export configuration. */
111
115
static int syslog_fd OVS_GUARDED_BY(pattern_rwlock) = -1;
117
/* Log facility configuration. */
118
static atomic_int log_facility = ATOMIC_VAR_INIT(0);
120
/* Facility name and its value. */
121
struct vlog_facility {
122
char *name; /* Name. */
123
unsigned int value; /* Facility associated with 'name'. */
125
static struct vlog_facility vlog_facilities[] = {
129
{"daemon", LOG_DAEMON},
131
{"syslog", LOG_SYSLOG},
141
{"local0", LOG_LOCAL0},
142
{"local1", LOG_LOCAL1},
143
{"local2", LOG_LOCAL2},
144
{"local3", LOG_LOCAL3},
145
{"local4", LOG_LOCAL4},
146
{"local5", LOG_LOCAL5},
147
{"local6", LOG_LOCAL6},
148
{"local7", LOG_LOCAL7}
150
static bool vlog_facility_exists(const char* facility, int *value);
113
152
static void format_log_message(const struct vlog_module *, enum vlog_level,
114
153
const char *pattern,
115
154
const char *message, va_list, struct ds *)
155
OVS_PRINTF_FORMAT(4, 0);
118
157
/* Searches the 'n_names' in 'names'. Returns the index of a match for
119
158
* 'target', or 'n_names' if no name matches. */
147
186
return search_name_array(name, level_names, ARRAY_SIZE(level_names));
150
/* Returns the name for logging facility 'facility'. */
189
/* Returns the name for logging destination 'destination'. */
152
vlog_get_facility_name(enum vlog_facility facility)
191
vlog_get_destination_name(enum vlog_destination destination)
154
assert(facility < VLF_N_FACILITIES);
155
return facilities[facility].name;
193
assert(destination < VLF_N_DESTINATIONS);
194
return destinations[destination].name;
158
/* Returns the logging facility named 'name', or VLF_N_FACILITIES if 'name' is
159
* not the name of a logging facility. */
161
vlog_get_facility_val(const char *name)
197
/* Returns the logging destination named 'name', or VLF_N_DESTINATIONS if
198
* 'name' is not the name of a logging destination. */
199
enum vlog_destination
200
vlog_get_destination_val(const char *name)
165
for (i = 0; i < VLF_N_FACILITIES; i++) {
166
if (!strcasecmp(facilities[i].name, name)) {
204
for (i = 0; i < VLF_N_DESTINATIONS; i++) {
205
if (!strcasecmp(destinations[i].name, name)) {
212
void vlog_insert_module(struct ovs_list *vlog)
214
list_insert(&vlog_modules, vlog);
173
217
/* Returns the name for logging module 'module'. */
175
219
vlog_get_module_name(const struct vlog_module *module)
196
/* Returns the current logging level for the given 'module' and 'facility'. */
240
/* Returns the current logging level for the given 'module' and
198
vlog_get_level(const struct vlog_module *module, enum vlog_facility facility)
243
vlog_get_level(const struct vlog_module *module,
244
enum vlog_destination destination)
200
assert(facility < VLF_N_FACILITIES);
201
return module->levels[facility];
246
assert(destination < VLF_N_DESTINATIONS);
247
return module->levels[destination];
205
251
update_min_level(struct vlog_module *module) OVS_REQUIRES(&log_file_mutex)
207
enum vlog_facility facility;
253
enum vlog_destination destination;
209
255
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];
256
for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
257
if (log_fd >= 0 || destination != VLF_FILE) {
258
enum vlog_level level = module->levels[destination];
213
259
if (level > module->min_level) {
214
260
module->min_level = level;
221
set_facility_level(enum vlog_facility facility, struct vlog_module *module,
222
enum vlog_level level)
267
set_destination_level(enum vlog_destination destination,
268
struct vlog_module *module, enum vlog_level level)
224
assert(facility >= 0 && facility < VLF_N_FACILITIES);
270
assert(destination >= 0 && destination < VLF_N_DESTINATIONS);
225
271
assert(level < VLL_N_LEVELS);
227
273
ovs_mutex_lock(&log_file_mutex);
229
275
struct vlog_module *mp;
230
276
LIST_FOR_EACH (mp, list, &vlog_modules) {
231
mp->levels[facility] = level;
277
mp->levels[destination] = level;
232
278
update_min_level(mp);
235
module->levels[facility] = level;
281
module->levels[destination] = level;
236
282
update_min_level(module);
238
284
ovs_mutex_unlock(&log_file_mutex);
241
/* Sets the logging level for the given 'module' and 'facility' to 'level'. A
242
* null 'module' or a 'facility' of VLF_ANY_FACILITY is treated as a wildcard
243
* across all modules or facilities, respectively. */
287
/* Sets the logging level for the given 'module' and 'destination' to 'level'.
288
* A null 'module' or a 'destination' of VLF_ANY_DESTINATION is treated as a
289
* wildcard across all modules or destinations, respectively. */
245
vlog_set_levels(struct vlog_module *module, enum vlog_facility facility,
291
vlog_set_levels(struct vlog_module *module, enum vlog_destination destination,
246
292
enum vlog_level level)
248
assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
249
if (facility == VLF_ANY_FACILITY) {
250
for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
251
set_facility_level(facility, module, level);
294
assert(destination < VLF_N_DESTINATIONS ||
295
destination == VLF_ANY_DESTINATION);
296
if (destination == VLF_ANY_DESTINATION) {
297
for (destination = 0; destination < VLF_N_DESTINATIONS;
299
set_destination_level(destination, module, level);
254
set_facility_level(facility, module, level);
302
set_destination_level(destination, module, level);
259
do_set_pattern(enum vlog_facility facility, const char *pattern)
307
do_set_pattern(enum vlog_destination destination, const char *pattern)
261
struct facility *f = &facilities[facility];
309
struct destination *f = &destinations[destination];
263
311
ovs_rwlock_wrlock(&pattern_rwlock);
264
312
if (!f->default_pattern) {
270
318
ovs_rwlock_unlock(&pattern_rwlock);
273
/* Sets the pattern for the given 'facility' to 'pattern'. */
321
/* Sets the pattern for the given 'destination' to 'pattern'. */
275
vlog_set_pattern(enum vlog_facility facility, const char *pattern)
323
vlog_set_pattern(enum vlog_destination destination, const char *pattern)
277
assert(facility < VLF_N_FACILITIES || facility == VLF_ANY_FACILITY);
278
if (facility == VLF_ANY_FACILITY) {
279
for (facility = 0; facility < VLF_N_FACILITIES; facility++) {
280
do_set_pattern(facility, pattern);
325
assert(destination < VLF_N_DESTINATIONS ||
326
destination == VLF_ANY_DESTINATION);
327
if (destination == VLF_ANY_DESTINATION) {
328
for (destination = 0; destination < VLF_N_DESTINATIONS;
330
do_set_pattern(destination, pattern);
283
do_set_pattern(facility, pattern);
333
do_set_pattern(destination, pattern);
393
443
word = strtok_r(s, " ,:\t", &save_ptr);
394
444
if (word && !strcasecmp(word, "PATTERN")) {
395
enum vlog_facility facility;
445
enum vlog_destination destination;
397
447
word = strtok_r(NULL, " ,:\t", &save_ptr);
399
msg = xstrdup("missing facility");
403
facility = (!strcasecmp(word, "ANY")
405
: vlog_get_facility_val(word));
406
if (facility == VLF_N_FACILITIES) {
407
msg = xasprintf("unknown facility \"%s\"", word);
410
vlog_set_pattern(facility, save_ptr);
449
msg = xstrdup("missing destination");
453
destination = (!strcasecmp(word, "ANY")
454
? VLF_ANY_DESTINATION
455
: vlog_get_destination_val(word));
456
if (destination == VLF_N_DESTINATIONS) {
457
msg = xasprintf("unknown destination \"%s\"", word);
460
vlog_set_pattern(destination, save_ptr);
461
} else if (word && !strcasecmp(word, "FACILITY")) {
464
if (!vlog_facility_exists(save_ptr, &value)) {
465
msg = xstrdup("invalid facility");
468
atomic_store_explicit(&log_facility, value, memory_order_relaxed);
412
470
struct vlog_module *module = NULL;
413
471
enum vlog_level level = VLL_N_LEVELS;
414
enum vlog_facility facility = VLF_N_FACILITIES;
472
enum vlog_destination destination = VLF_N_DESTINATIONS;
416
474
for (; word != NULL; word = strtok_r(NULL, " ,:\t", &save_ptr)) {
417
475
if (!strcasecmp(word, "ANY")) {
419
} else if (vlog_get_facility_val(word) != VLF_N_FACILITIES) {
420
if (facility != VLF_N_FACILITIES) {
421
msg = xstrdup("cannot specify multiple facilities");
477
} else if (vlog_get_destination_val(word) != VLF_N_DESTINATIONS) {
478
if (destination != VLF_N_DESTINATIONS) {
479
msg = xstrdup("cannot specify multiple destinations");
424
facility = vlog_get_facility_val(word);
482
destination = vlog_get_destination_val(word);
425
483
} else if (vlog_get_level_val(word) != VLL_N_LEVELS) {
426
484
if (level != VLL_N_LEVELS) {
427
485
msg = xstrdup("cannot specify multiple levels");
436
494
module = vlog_module_from_name(word);
438
msg = xasprintf("no facility, level, or module \"%s\"", word);
496
msg = xasprintf("no destination, level, or module \"%s\"",
443
if (facility == VLF_N_FACILITIES) {
444
facility = VLF_ANY_FACILITY;
502
if (destination == VLF_N_DESTINATIONS) {
503
destination = VLF_ANY_DESTINATION;
446
505
if (level == VLL_N_LEVELS) {
449
vlog_set_levels(module, facility, level);
508
vlog_set_levels(module, destination, level);
475
534
ovs_fatal(0, "processing \"%s\": %s", arg, msg);
478
vlog_set_levels(NULL, VLF_ANY_FACILITY, VLL_DBG);
537
vlog_set_levels(NULL, VLF_ANY_DESTINATION, VLL_DBG);
542
vlog_set_syslog_method(const char *method)
545
/* Set syslogger only, if one is not already set. This effectively
546
* means that only the first --syslog-method argument is honored. */
550
if (!strcmp(method, "libc")) {
551
syslogger = syslog_libc_create();
552
} else if (!strncmp(method, "udp:", 4) || !strncmp(method, "unix:", 5)) {
553
syslogger = syslog_direct_create(method);
555
ovs_fatal(0, "unsupported syslog method '%s'", method);
495
572
ovs_rwlock_unlock(&pattern_rwlock);
575
/* Returns 'false' if 'facility' is not a valid string. If 'facility'
576
* is a valid string, sets 'value' with the integer value of 'facility'
577
* and returns 'true'. */
579
vlog_facility_exists(const char* facility, int *value)
582
for (i = 0; i < ARRAY_SIZE(vlog_facilities); i++) {
583
if (!strcasecmp(vlog_facilities[i].name, facility)) {
584
*value = vlog_facilities[i].value;
499
592
vlog_unixctl_set(struct unixctl_conn *conn, int argc, const char *argv[],
500
593
void *aux OVS_UNUSED)
618
vlog_unixctl_list_pattern(struct unixctl_conn *conn, int argc OVS_UNUSED,
619
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
623
msg = vlog_get_patterns();
624
unixctl_command_reply(conn, msg);
525
629
vlog_unixctl_reopen(struct unixctl_conn *conn, int argc OVS_UNUSED,
526
630
const char *argv[] OVS_UNUSED, void *aux OVS_UNUSED)
600
704
static struct ovsthread_once once = OVSTHREAD_ONCE_INITIALIZER;
602
706
if (ovsthread_once_start(&once)) {
603
static char *program_name_copy;
604
707
long long int now;
606
710
/* Do initialization work that needs to be done before any logging
607
711
* occurs. We want to keep this really minimal because any attempt to
608
712
* log anything before calling ovsthread_once_done() will deadlock. */
610
/* openlog() is allowed to keep the pointer passed in, without making a
611
* copy. The daemonize code sometimes frees and replaces
612
* 'program_name', so make a private copy just for openlog(). (We keep
613
* a pointer to the private copy to suppress memory leak warnings in
614
* case openlog() does make its own copy.) */
615
program_name_copy = program_name ? xstrdup(program_name) : NULL;
616
openlog(program_name_copy, LOG_NDELAY, LOG_DAEMON);
713
atomic_read_explicit(&log_facility, &facility, memory_order_relaxed);
715
syslogger = syslog_libc_create();
717
syslogger->class->openlog(syslogger, facility ? facility : LOG_DAEMON);
617
718
ovsthread_once_done(&once);
619
720
/* Now do anything that we want to happen only once but doesn't have to
629
730
unixctl_command_register(
630
"vlog/set", "{spec | PATTERN:facility:pattern}",
731
"vlog/set", "{spec | PATTERN:destination:pattern}",
631
732
1, INT_MAX, vlog_unixctl_set, NULL);
632
733
unixctl_command_register("vlog/list", "", 0, 0, vlog_unixctl_list,
735
unixctl_command_register("vlog/list-pattern", "", 0, 0,
736
vlog_unixctl_list_pattern, NULL);
634
737
unixctl_command_register("vlog/enable-rate-limit", "[module]...",
635
738
0, INT_MAX, vlog_enable_rate_limit, NULL);
636
739
unixctl_command_register("vlog/disable-rate-limit", "[module]...",
695
798
return ds_cstr(&s);
801
/* Returns as a string current logging patterns for each destination.
802
* This string must be released by caller. */
804
vlog_get_patterns(void)
806
struct ds ds = DS_EMPTY_INITIALIZER;
807
enum vlog_destination destination;
809
ovs_rwlock_rdlock(&pattern_rwlock);
810
ds_put_format(&ds, " prefix format\n");
811
ds_put_format(&ds, " ------ ------\n");
813
for (destination = 0; destination < VLF_N_DESTINATIONS; destination++) {
814
struct destination *f = &destinations[destination];;
815
const char *prefix = "none";
817
if (destination == VLF_SYSLOG && syslogger) {
818
prefix = syslog_get_prefix(syslogger);
820
ds_put_format(&ds, "%-7s %-32s %s\n", f->name, prefix, f->pattern);
822
ovs_rwlock_unlock(&pattern_rwlock);
698
827
/* Returns true if a log message emitted for the given 'module' and 'level'
699
828
* would cause some log output, false if that module and level are completely
761
891
ds_put_cstr(s, program_name);
764
ds_put_format(s, "%d", LOG_LOCAL0 + syslog_levels[level]);
894
atomic_read_explicit(&log_facility, &facility,
895
memory_order_relaxed);
896
facility = facility ? facility : LOG_LOCAL0;
897
ds_put_format(s, "%d", facility + syslog_levels[level]);
767
900
p = fetch_braces(p, "", tmp, sizeof tmp);
875
1008
ovs_rwlock_rdlock(&pattern_rwlock);
876
1009
if (log_to_console) {
877
format_log_message(module, level, facilities[VLF_CONSOLE].pattern,
1010
format_log_message(module, level,
1011
destinations[VLF_CONSOLE].pattern, message,
879
1013
ds_put_char(&s, '\n');
880
1014
fputs(ds_cstr(&s), stderr);
884
1018
int syslog_level = syslog_levels[level];
885
1019
char *save_ptr = NULL;
888
format_log_message(module, level, facilities[VLF_SYSLOG].pattern,
1023
format_log_message(module, level, destinations[VLF_SYSLOG].pattern,
889
1024
message, args, &s);
890
1025
for (line = strtok_r(s.string, "\n", &save_ptr); line;
891
1026
line = strtok_r(NULL, "\n", &save_ptr)) {
892
syslog(syslog_level, "%s", line);
1027
atomic_read_explicit(&log_facility, &facility,
1028
memory_order_relaxed);
1029
syslogger->class->syslog(syslogger, syslog_level|facility, line);
895
1032
if (syslog_fd >= 0) {
976
1113
/* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
977
* writes the message to stderr, even if the console facility is disabled.
1114
* writes the message to stderr, even if the console destination is disabled.
979
1116
* Choose this function instead of vlog_fatal_valist() if the daemon monitoring
980
1117
* facility should automatically restart the current daemon. */
995
1132
/* Logs 'message' to 'module' at maximum verbosity, then calls abort(). Always
996
* writes the message to stderr, even if the console facility is disabled.
1133
* writes the message to stderr, even if the console destination is disabled.
998
1135
* Choose this function instead of vlog_fatal() if the daemon monitoring
999
1136
* facility should automatically restart the current daemon. */
1072
1209
-v, --verbose set maximum verbosity level\n\
1073
1210
--log-file[=FILE] enable logging to specified FILE\n\
1074
1211
(default: %s/%s.log)\n\
1212
--syslog-method=(libc|unix:file|udp:ip:port)\n\
1213
specify how to send messages to syslog daemon\n\
1075
1214
--syslog-target=HOST:PORT also send syslog msgs to HOST:PORT via UDP\n",
1076
1215
ovs_logdir(), program_name);