#include <vlib/log.h>
#include <syslog.h>
-typedef struct
-{
- vlib_log_level_t level;
- vlib_log_class_t class;
- f64 timestamp;
- u8 *string;
-} vlib_log_entry_t;
-
-typedef struct
-{
- u32 index;
- u8 *name;
- // level of log messages kept for this subclass
- vlib_log_level_t level;
- // level of log messages sent to syslog for this subclass
- vlib_log_level_t syslog_level;
- // flag saying whether this subclass is logged to syslog
- f64 last_event_timestamp;
- int last_sec_count;
- int is_throttling;
- int rate_limit;
-} vlib_log_subclass_data_t;
-
-typedef struct
-{
- u32 index;
- u8 *name;
- vlib_log_subclass_data_t *subclasses;
-} vlib_log_class_data_t;
-
-typedef struct
-{
- vlib_log_entry_t *entries;
- vlib_log_class_data_t *classes;
- int size, next, count;
-
- /* our own log class */
- vlib_log_class_t log_class;
-
- int default_rate_limit;
- int default_log_level;
- int default_syslog_log_level;
- int unthrottle_time;
- u32 indent;
-} vlib_log_main_t;
-
vlib_log_main_t log_main = {
.default_log_level = VLIB_LOG_LEVEL_NOTICE,
.default_syslog_log_level = VLIB_LOG_LEVEL_WARNING,
.default_rate_limit = 50,
};
-static int
+int
last_log_entry ()
{
vlib_log_main_t *lm = &log_main;
u8 *s = 0;
bool use_formatted_log_entry = true;
+ vec_validate (lm->entries, lm->size);
/* make sure we are running on the main thread to avoid use in dataplane
code, for dataplane logging consider use of event-logger */
ASSERT (vlib_get_thread_index () == 0);
if (use_formatted_log_entry)
{
syslog (vlib_log_level_to_syslog_priority (level), "%.*s: %.*s",
- vec_len (tmp), tmp,
- vec_len (s) - (vec_c_string_is_terminated (s) ? 1 : 0), s);
+ (int) vec_len (tmp), tmp,
+ (int) (vec_len (s) -
+ (vec_c_string_is_terminated (s) ? 1 : 0)), s);
}
else
{
tmp = va_format (tmp, fmt, &va);
va_end (va);
syslog (vlib_log_level_to_syslog_priority (level), "%.*s",
- vec_len (tmp) - (vec_c_string_is_terminated (tmp) ? 1 : 0),
- tmp);
+ (int) (vec_len (tmp) -
+ (vec_c_string_is_terminated (tmp) ? 1 : 0)), tmp);
}
vec_free (tmp);
}
}
-vlib_log_class_t
-vlib_log_register_class (char *class, char *subclass)
+static vlib_log_class_t
+vlib_log_register_class_internal (char *class, char *subclass, u32 limit)
{
vlib_log_main_t *lm = &log_main;
vlib_log_class_data_t *c = NULL;
vlib_log_class_data_t *tmp;
vec_foreach (tmp, lm->classes)
{
+ if (vec_len (tmp->name) != strlen (class))
+ continue;
if (!memcmp (class, tmp->name, vec_len (tmp->name)))
{
c = tmp;
vec_add2 (c->subclasses, s, 1);
s->index = s - c->subclasses;
s->name = subclass ? format (0, "%s", subclass) : 0;
- s->rate_limit = lm->default_rate_limit;
+ s->rate_limit = (limit == 0) ? lm->default_rate_limit : limit;
s->level = lm->default_log_level;
s->syslog_level = lm->default_syslog_log_level;
return (c->index << 16) | (s->index);
}
+vlib_log_class_t
+vlib_log_register_class (char *class, char *subclass)
+{
+ return vlib_log_register_class_internal (class, subclass,
+ 0 /* default rate limit */ );
+}
+
+vlib_log_class_t
+vlib_log_register_class_rate_limit (char *class, char *subclass, u32 limit)
+{
+ return vlib_log_register_class_internal (class, subclass, limit);
+}
+
+
u8 *
format_vlib_log_level (u8 * s, va_list * args)
{
vlib_log_init (vlib_main_t * vm)
{
vlib_log_main_t *lm = &log_main;
+
+ gettimeofday (&lm->time_zero_timeval, 0);
+ lm->time_zero = vlib_time_now (vm);
+
vec_validate (lm->entries, lm->size);
lm->log_class = vlib_log_register_class ("log", 0);
u8 *tmp = format (NULL, "%U %-10U %-10U ", format_time_float, 0, (f64) 0,
vlib_log_entry_t *e;
int i = last_log_entry ();
int count = lm->count;
+ f64 time_offset;
+
+ time_offset = (f64) lm->time_zero_timeval.tv_sec
+ + (((f64) lm->time_zero_timeval.tv_usec) * 1e-6) - lm->time_zero;
while (count--)
{
e = vec_elt_at_index (lm->entries, i);
- vlib_cli_output (vm, "%U %-10U %-10U %v",
- format_time_float, 0, e->timestamp,
+ vlib_cli_output (vm, "%U %-10U %-14U %v",
+ format_time_float, 0, e->timestamp + time_offset,
format_vlib_log_level, e->level,
format_vlib_log_class, e->class, e->string);
i = (i + 1) % lm->size;
vlib_cli_output (vm, "%-22s %-14s %-14s %s",
"Class/Subclass", "Level", "Syslog Level", "Rate Limit");
+
+ u8 *defstr = format (0, "default");
vec_foreach (c, lm->classes)
{
- vlib_cli_output (vm, "%s", c->name);
+ vlib_cli_output (vm, "%v", c->name);
vec_foreach (sc, c->subclasses)
{
- vlib_cli_output (vm, " %-20s %-14U %-14U %d",
- sc->name ? (char *) sc->name : "default",
+ vlib_cli_output (vm, " %-20v %-14U %-14U %d",
+ sc->name ? sc->name : defstr,
format_vlib_log_level, sc->level,
format_vlib_log_level, sc->syslog_level,
sc->rate_limit);
}
}
+ vec_free (defstr);
return error;
}
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cli_set_log, static) = {
.path = "set logging class",
- .short_help = "set loggging class <class> [rate-limit <int>] "
+ .short_help = "set logging class <class> [rate-limit <int>] "
"[level <level>] [syslog-level <level>]",
.function = set_log_class,
};
/* *INDENT-OFF* */
VLIB_CLI_COMMAND (cli_test_log, static) = {
.path = "test log",
- .short_help = "test log <class> <subclass> <level> <message",
+ .short_help = "test log <level> <class> <subclass> <message>",
.function = test_log_class_subclass,
};
/* *INDENT-ON* */