FD.io VPP  v21.01.1
Vector Packet Processing
log.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2018 Cisco and/or its affiliates.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at:
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include <stdbool.h>
17 #include <vlib/vlib.h>
18 #include <vlib/log.h>
19 #include <vlib/unix/unix.h>
20 #include <syslog.h>
21 #include <vppinfra/elog.h>
22 
23 vlib_log_main_t log_main = {
24  .default_log_level = VLIB_LOG_LEVEL_NOTICE,
25  .default_syslog_log_level = VLIB_LOG_LEVEL_WARNING,
26  .unthrottle_time = 3,
27  .size = 512,
28  .add_to_elog = 1,
29  .default_rate_limit = 50,
30 };
31 
32 /* *INDENT-OFF* */
33 VLIB_REGISTER_LOG_CLASS (log_log, static) = {
34  .class_name = "log",
35 };
36 /* *INDENT-ON* */
37 
38 static const int colors[] = {
39  [VLIB_LOG_LEVEL_EMERG] = 1, /* red */
40  [VLIB_LOG_LEVEL_ALERT] = 1, /* red */
41  [VLIB_LOG_LEVEL_CRIT] = 1, /* red */
42  [VLIB_LOG_LEVEL_ERR] = 1, /* red */
43  [VLIB_LOG_LEVEL_WARNING] = 3, /* yellow */
44  [VLIB_LOG_LEVEL_NOTICE] = 2, /* green */
45  [VLIB_LOG_LEVEL_INFO] = 4, /* blue */
46  [VLIB_LOG_LEVEL_DEBUG] = 6, /* cyan */
47 };
48 
49 static const int log_level_to_syslog_priority[] = {
50  [VLIB_LOG_LEVEL_EMERG] = LOG_EMERG,
51  [VLIB_LOG_LEVEL_ALERT] = LOG_ALERT,
52  [VLIB_LOG_LEVEL_CRIT] = LOG_CRIT,
53  [VLIB_LOG_LEVEL_ERR] = LOG_ERR,
54  [VLIB_LOG_LEVEL_WARNING] = LOG_WARNING,
55  [VLIB_LOG_LEVEL_NOTICE] = LOG_NOTICE,
56  [VLIB_LOG_LEVEL_INFO] = LOG_INFO,
57  [VLIB_LOG_LEVEL_DEBUG] = LOG_DEBUG,
58  [VLIB_LOG_LEVEL_DISABLED] = LOG_DEBUG,
59 };
60 
61 int
63 {
65  int i;
66 
67  i = lm->next - lm->count;
68 
69  if (i < 0)
70  i += lm->size;
71  return i;
72 }
73 
74 static vlib_log_class_data_t *
76 {
78  return vec_elt_at_index (lm->classes, (ci >> 16));
79 }
80 
83 {
85  return vec_elt_at_index (c->subclasses, (ci & 0xffff));
86 }
87 
88 u8 *
89 format_vlib_log_class (u8 * s, va_list * args)
90 {
91  vlib_log_class_t ci = va_arg (*args, vlib_log_class_t);
94 
95  if (sc->name)
96  return format (s, "%v/%v", c->name, sc->name);
97  else
98  return format (s, "%v", c->name, 0);
99 }
100 
101 u8 *
102 format_indent (u8 * s, va_list * args)
103 {
104  u8 *v = va_arg (*args, u8 *);
105  u32 indent = va_arg (*args, u32);
106  u8 *c;
107 
108  /* *INDENT-OFF* */
109  vec_foreach (c, v)
110  {
111  vec_add (s, c, 1);
112  if (c[0] == '\n')
113  for (u32 i = 0; i < indent; i++)
114  vec_add1 (s, (u8) ' ');
115  }
116  /* *INDENT-ON* */
117  return s;
118 }
119 
120 static int
122 {
123  if (configured == VLIB_LOG_LEVEL_DISABLED)
124  return 0;
125  if (level > configured)
126  return 0;
127  return 1;
128 }
129 
130 void
131 vlib_log (vlib_log_level_t level, vlib_log_class_t class, char *fmt, ...)
132 {
134  vlib_log_main_t *lm = &log_main;
135  vlib_log_entry_t *e;
137  va_list va;
138  f64 t = vlib_time_now (vm);
139  f64 delta = t - sc->last_event_timestamp;
140  int log_enabled = log_level_is_enabled (level, sc->level);
141  int syslog_enabled = log_level_is_enabled (level, sc->syslog_level);
142  u8 *s = 0;
143 
144  /* make sure we are running on the main thread to avoid use in dataplane
145  code, for dataplane logging consider use of event-logger */
146  ASSERT (vlib_get_thread_index () == 0);
147 
148  if ((log_enabled || syslog_enabled) == 0)
149  return;
150 
151  vec_validate (lm->entries, lm->size);
152 
153  if ((delta > lm->unthrottle_time) ||
154  (sc->is_throttling == 0 && (delta > 1)))
155  {
156  sc->last_event_timestamp = t;
157  sc->last_sec_count = 0;
158  sc->is_throttling = 0;
159  }
160  else
161  {
162  sc->last_sec_count++;
163  if (sc->last_sec_count > sc->rate_limit)
164  return;
165  else if (sc->last_sec_count == sc->rate_limit)
166  {
167  vec_reset_length (s);
168  s = format (s, "--- message(s) throttled ---");
169  sc->is_throttling = 1;
170  }
171  }
172 
173  if (s == 0)
174  {
175  va_start (va, fmt);
176  s = va_format (s, fmt, &va);
177  va_end (va);
178  }
179 
180  if (syslog_enabled)
181  {
182  u8 *l = 0;
184  {
185  int indent = 0;
186  int with_colors = (unix_main.flags & UNIX_FLAG_NOCOLOR) == 0;
187  u8 *fmt;
188  if (with_colors)
189  {
190  l = format (l, "\x1b[%um", 90 + colors[level]);
191  indent = vec_len (l);
192  }
193  fmt = format (0, "%%-%uU [%%-6U]: ", lm->max_class_name_length);
195  l = format (l, (char *) fmt, format_vlib_log_class, class,
196  format_vlib_log_level, level);
197  vec_free (fmt);
198  indent = vec_len (l) - indent;
199  if (with_colors)
200  l = format (l, "\x1b[0m");
201  l = format (l, "%U", format_indent, s, indent);
202  fformat (stderr, "%v\n", l);
203  fflush (stderr);
204  }
205  else
206  {
207  l = format (l, "%U", format_vlib_log_class, class);
208  int prio = log_level_to_syslog_priority[level];
209  int is_term = vec_c_string_is_terminated (l) ? 1 : 0;
210 
211  syslog (prio, "%.*s: %.*s", (int) vec_len (l), l,
212  (int) vec_len (s) - is_term, s);
213  }
214  vec_free (l);
215  }
216 
217  if (log_enabled)
218  {
219  e = vec_elt_at_index (lm->entries, lm->next);
220  vec_free (e->string);
221  e->level = level;
222  e->class = class;
223  e->string = s;
224  e->timestamp = t;
225  s = 0;
226 
227  if (lm->add_to_elog)
228  {
229  /* *INDENT-OFF* */
230  ELOG_TYPE_DECLARE(ee) =
231  {
232  .format = "log-%s: %s",
233  .format_args = "t4T4",
234  .n_enum_strings = 9,
235  .enum_strings = {
236  "emerg",
237  "alert",
238  "crit",
239  "err",
240  "warn",
241  "notice",
242  "info",
243  "debug",
244  "disabled",
245  },
246  };
247  struct {
248  u32 log_level;
249  u32 string_index;
250  } *ed;
251  /* *INDENT-ON* */
252  ed = ELOG_DATA (&vm->elog_main, ee);
253  ed->log_level = level;
254  ed->string_index = elog_string (&vm->elog_main, "%v", e->string);
255  }
256 
257  lm->next = (lm->next + 1) % lm->size;
258  if (lm->size > lm->count)
259  lm->count++;
260  }
261 
262  vec_free (s);
263 }
264 
265 static vlib_log_class_t
266 vlib_log_register_class_internal (char *class, char *subclass, u32 limit)
267 {
268  vlib_log_main_t *lm = &log_main;
269  vlib_log_class_data_t *c = NULL;
272  vlib_log_class_config_t *cc = 0, *scc = 0;
273  uword *p;
274  u8 *str;
275  u32 length = 0;
276 
277  if ((p = hash_get_mem (lm->config_index_by_name, class)))
278  cc = vec_elt_at_index (lm->configs, p[0]);
279 
280  str = format (0, "%s/%s%c", class, subclass, 0);
281  if ((p = hash_get_mem (lm->config_index_by_name, (char *) str)))
282  scc = vec_elt_at_index (lm->configs, p[0]);
283  vec_free (str);
284 
285  vec_foreach (tmp, lm->classes)
286  {
287  if (vec_len (tmp->name) != strlen (class))
288  continue;
289  if (!memcmp (class, tmp->name, vec_len (tmp->name)))
290  {
291  c = tmp;
292  break;
293  }
294  }
295  if (!c)
296  {
297  vec_add2 (lm->classes, c, 1);
298  c->index = c - lm->classes;
299  c->name = format (0, "%s", class);
300  }
301  length = vec_len (c->name);
302 
303  vec_add2 (c->subclasses, s, 1);
304  s->index = s - c->subclasses;
305  s->name = subclass ? format (0, "%s", subclass) : 0;
306 
307  if (scc && scc->rate_limit != ~0)
308  s->rate_limit = scc->rate_limit;
309  else if (cc && cc->rate_limit != ~0)
310  s->rate_limit = cc->rate_limit;
311  else if (limit)
312  s->rate_limit = limit;
313  else
315 
316  if (scc && scc->level != ~0)
317  s->level = scc->level;
318  else if (cc && cc->level != ~0)
319  s->level = cc->level;
320  else
321  s->level = lm->default_log_level;
322 
323  if (scc && scc->syslog_level != ~0)
324  s->syslog_level = scc->syslog_level;
325  else if (cc && cc->syslog_level != ~0)
326  s->syslog_level = cc->syslog_level;
327  else
329 
330  if (subclass)
331  length += 1 + vec_len (s->name);
332  if (length > lm->max_class_name_length)
334  return (c->index << 16) | (s->index);
335 }
336 
338 vlib_log_register_class (char *class, char *subclass)
339 {
340  return vlib_log_register_class_internal (class, subclass,
341  0 /* default rate limit */ );
342 }
343 
345 vlib_log_register_class_rate_limit (char *class, char *subclass, u32 limit)
346 {
347  return vlib_log_register_class_internal (class, subclass, limit);
348 }
349 
350 
351 u8 *
352 format_vlib_log_level (u8 * s, va_list * args)
353 {
354  vlib_log_level_t i = va_arg (*args, vlib_log_level_t);
355  char *t = 0;
356 
357  switch (i)
358  {
359 #define _(uc,lc) case VLIB_LOG_LEVEL_##uc: t = #lc; break;
361 #undef _
362  default:
363  return format (s, "unknown");
364  }
365  return format (s, "%s", t);
366 }
367 
368 static clib_error_t *
370 {
371  vlib_log_main_t *lm = &log_main;
373 
374  gettimeofday (&lm->time_zero_timeval, 0);
375  lm->time_zero = vlib_time_now (vm);
376 
377  vec_validate (lm->entries, lm->size);
378 
379  while (r)
380  {
382  if (r->default_level)
384  if (r->default_syslog_level)
386  r = r->next;
387  }
388 
389  r = lm->registrations;
390  while (r)
391  {
392  vlib_log_debug (r->class, "initialized");
393  r = r->next;
394  }
395  return 0;
396 }
397 
399 
400 
401 static clib_error_t *
403  unformat_input_t * input, vlib_cli_command_t * cmd)
404 {
405  clib_error_t *error = 0;
406  vlib_log_main_t *lm = &log_main;
407  vlib_log_entry_t *e;
408  int i = last_log_entry ();
409  int count = lm->count;
410  f64 time_offset;
411 
412  time_offset = (f64) lm->time_zero_timeval.tv_sec
413  + (((f64) lm->time_zero_timeval.tv_usec) * 1e-6) - lm->time_zero;
414 
415  while (count--)
416  {
417  e = vec_elt_at_index (lm->entries, i);
418  vlib_cli_output (vm, "%U %-10U %-14U %v",
419  format_time_float, 0, e->timestamp + time_offset,
422  i = (i + 1) % lm->size;
423  }
424 
425  return error;
426 }
427 
428 /* *INDENT-OFF* */
429 VLIB_CLI_COMMAND (cli_show_log, static) = {
430  .path = "show logging",
431  .short_help = "show logging",
432  .function = show_log,
433 };
434 /* *INDENT-ON* */
435 
436 static clib_error_t *
438  unformat_input_t * input, vlib_cli_command_t * cmd)
439 {
440  clib_error_t *error = 0;
441  vlib_log_main_t *lm = &log_main;
444 
445  vlib_cli_output (vm, "%-20s %u entries", "Buffer Size:", lm->size);
446  vlib_cli_output (vm, "Defaults:\n");
447  vlib_cli_output (vm, "%-20s %U", " Log Level:",
449  vlib_cli_output (vm, "%-20s %U", " Syslog Log Level:",
451  vlib_cli_output (vm, "%-20s %u msgs/sec", " Rate Limit:",
452  lm->default_rate_limit);
453  vlib_cli_output (vm, "\n");
454  vlib_cli_output (vm, "%-22s %-14s %-14s %s",
455  "Class/Subclass", "Level", "Syslog Level", "Rate Limit");
456 
457 
458  u8 *defstr = format (0, "default");
459  vec_foreach (c, lm->classes)
460  {
461  vlib_cli_output (vm, "%v", c->name);
462  vec_foreach (sc, c->subclasses)
463  {
464  vlib_cli_output (vm, " %-20v %-14U %-14U %d",
465  sc->name ? sc->name : defstr,
468  sc->rate_limit);
469  }
470  }
471  vec_free (defstr);
472 
473  return error;
474 }
475 
476 /* *INDENT-OFF* */
477 VLIB_CLI_COMMAND (cli_show_log_config, static) = {
478  .path = "show logging configuration",
479  .short_help = "show logging configuration",
480  .function = show_log_config,
481 };
482 /* *INDENT-ON* */
483 
484 static clib_error_t *
486  unformat_input_t * input, vlib_cli_command_t * cmd)
487 {
488  clib_error_t *error = 0;
489  vlib_log_main_t *lm = &log_main;
490  vlib_log_entry_t *e;
491  int i = last_log_entry ();
492  int count = lm->count;
493 
494  while (count--)
495  {
496  e = vec_elt_at_index (lm->entries, i);
497  vec_free (e->string);
498  i = (i + 1) % lm->size;
499  }
500 
501  lm->count = 0;
502  lm->next = 0;
503  vlib_log_info (log_log.class, "log cleared");
504  return error;
505 }
506 
507 /* *INDENT-OFF* */
508 VLIB_CLI_COMMAND (cli_clear_log, static) = {
509  .path = "clear logging",
510  .short_help = "clear logging",
511  .function = clear_log,
512 };
513 /* *INDENT-ON* */
514 
515 static uword
516 unformat_vlib_log_level (unformat_input_t * input, va_list * args)
517 {
518  vlib_log_level_t *level = va_arg (*args, vlib_log_level_t *);
519  u8 *level_str = NULL;
520  uword rv = 1;
521  if (unformat (input, "%s", &level_str))
522  {
523 #define _(uc, lc) \
524  const char __##uc[] = #lc; \
525  if (!strcmp ((const char *) level_str, __##uc)) \
526  { \
527  *level = VLIB_LOG_LEVEL_##uc; \
528  rv = 1; \
529  goto done; \
530  }
532  rv = 0;
533 #undef _
534  }
535 done:
536  vec_free (level_str);
537  return rv;
538 }
539 
540 static uword
541 unformat_vlib_log_class (unformat_input_t * input, va_list * args)
542 {
543  vlib_log_class_data_t **class = va_arg (*args, vlib_log_class_data_t **);
544  uword rv = 0;
545  u8 *class_str = NULL;
546  vlib_log_main_t *lm = &log_main;
547  if (unformat (input, "%v", &class_str))
548  {
549  vlib_log_class_data_t *cdata;
550  vec_foreach (cdata, lm->classes)
551  {
552  if (vec_is_equal (cdata->name, class_str))
553  {
554  *class = cdata;
555  rv = 1;
556  break;
557  }
558  }
559  }
560  vec_free (class_str);
561  return rv;
562 }
563 
564 static clib_error_t *
566  unformat_input_t * input, vlib_cli_command_t * cmd)
567 {
568  unformat_input_t _line_input, *line_input = &_line_input;
569  clib_error_t *rv = NULL;
570  int rate_limit;
571  bool set_rate_limit = false;
572  bool set_level = false;
573  bool set_syslog_level = false;
574  vlib_log_level_t level;
575  vlib_log_level_t syslog_level;
576 
577  /* Get a line of input. */
578  if (!unformat_user (input, unformat_line_input, line_input))
579  return 0;
580 
581  vlib_log_class_data_t *class = NULL;
582  if (!unformat (line_input, "%U", unformat_vlib_log_class, &class))
583  {
584  return clib_error_return (0, "unknown log class `%U'",
585  format_unformat_error, line_input);
586  }
587  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
588  {
589  if (unformat (line_input, "rate-limit %d", &rate_limit))
590  {
591  set_rate_limit = true;
592  }
593  else
594  if (unformat
595  (line_input, "level %U", unformat_vlib_log_level, &level))
596  {
597  set_level = true;
598  }
599  else
600  if (unformat
601  (line_input, "syslog-level %U", unformat_vlib_log_level,
602  &syslog_level))
603  {
604  set_syslog_level = true;
605  }
606  else
607  {
608  return clib_error_return (0, "unknown input `%U'",
609  format_unformat_error, line_input);
610  }
611  }
612 
613  if (set_level)
614  {
615  vlib_log_subclass_data_t *subclass;
616  vec_foreach (subclass, class->subclasses)
617  {
618  subclass->level = level;
619  }
620  }
621  if (set_syslog_level)
622  {
623  vlib_log_subclass_data_t *subclass;
624  vec_foreach (subclass, class->subclasses)
625  {
626  subclass->syslog_level = syslog_level;
627  }
628  }
629  if (set_rate_limit)
630  {
631  vlib_log_subclass_data_t *subclass;
632  vec_foreach (subclass, class->subclasses)
633  {
634  subclass->rate_limit = rate_limit;
635  }
636  }
637 
638  return rv;
639 }
640 
641 /* *INDENT-OFF* */
642 VLIB_CLI_COMMAND (cli_set_log, static) = {
643  .path = "set logging class",
644  .short_help = "set logging class <class> [rate-limit <int>] "
645  "[level <level>] [syslog-level <level>]",
646  .function = set_log_class,
647 };
648 /* *INDENT-ON* */
649 
650 static clib_error_t *
652  unformat_input_t * input, vlib_cli_command_t * cmd)
653 {
654  unformat_input_t _line_input, *line_input = &_line_input;
655  clib_error_t *rv = NULL;
656  int unthrottle_time;
657  vlib_log_main_t *lm = &log_main;
658 
659  /* Get a line of input. */
660  if (!unformat_user (input, unformat_line_input, line_input))
661  return 0;
662 
663  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
664  {
665  if (unformat (line_input, "%d", &unthrottle_time))
666  lm->unthrottle_time = unthrottle_time;
667  else
668  return clib_error_return (0, "unknown input `%U'",
669  format_unformat_error, line_input);
670  }
671 
672  return rv;
673 }
674 
675 /* *INDENT-OFF* */
676 VLIB_CLI_COMMAND (cli_set_log_params, static) = {
677  .path = "set logging unthrottle-time",
678  .short_help = "set logging unthrottle-time <int>",
679  .function = set_log_unth_time,
680 };
681 /* *INDENT-ON* */
682 
683 static clib_error_t *
685  unformat_input_t * input, vlib_cli_command_t * cmd)
686 {
687  unformat_input_t _line_input, *line_input = &_line_input;
688  clib_error_t *rv = NULL;
689  int size;
690  vlib_log_main_t *lm = &log_main;
691 
692  /* Get a line of input. */
693  if (!unformat_user (input, unformat_line_input, line_input))
694  return 0;
695 
696  while (unformat_check_input (line_input) != UNFORMAT_END_OF_INPUT)
697  {
698  if (unformat (line_input, "%d", &size))
699  {
700  lm->size = size;
701  vec_validate (lm->entries, lm->size);
702  }
703  else
704  return clib_error_return (0, "unknown input `%U'",
705  format_unformat_error, line_input);
706  }
707 
708  return rv;
709 }
710 
711 /* *INDENT-OFF* */
712 VLIB_CLI_COMMAND (cli_set_log_size, static) = {
713  .path = "set logging size",
714  .short_help = "set logging size <int>",
715  .function = set_log_size,
716 };
717 /* *INDENT-ON* */
718 
719 static uword
721 {
722  vlib_log_class_data_t *class = va_arg (*args, vlib_log_class_data_t *);
723  vlib_log_subclass_data_t **subclass =
724  va_arg (*args, vlib_log_subclass_data_t **);
725  uword rv = 0;
726  u8 *subclass_str = NULL;
727  if (unformat (input, "%v", &subclass_str))
728  {
729  vlib_log_subclass_data_t *scdata;
730  vec_foreach (scdata, class->subclasses)
731  {
732  if (vec_is_equal (scdata->name, subclass_str))
733  {
734  rv = 1;
735  *subclass = scdata;
736  break;
737  }
738  }
739  }
740  vec_free (subclass_str);
741  return rv;
742 }
743 
744 static clib_error_t *
746  unformat_input_t * input, vlib_cli_command_t * cmd)
747 {
748  unformat_input_t _line_input, *line_input = &_line_input;
749  /* Get a line of input. */
750  if (!unformat_user (input, unformat_line_input, line_input))
751  return 0;
752 
753  vlib_log_class_data_t *class = NULL;
754  vlib_log_subclass_data_t *subclass = NULL;
755  vlib_log_level_t level;
756  if (unformat (line_input, "%U", unformat_vlib_log_level, &level))
757  {
758  if (unformat (line_input, "%U", unformat_vlib_log_class, &class))
759  {
760  if (unformat
761  (line_input, "%U", unformat_vlib_log_subclass, class,
762  &subclass))
763  {
764  vlib_log (level,
765  (class->index << 16) | (subclass->index), "%U",
766  format_unformat_input, line_input);
767  }
768  else
769  {
770  return clib_error_return (0,
771  "unknown log subclass near beginning of `%U'",
772  format_unformat_error, line_input);
773  }
774  }
775  else
776  {
777  return clib_error_return (0,
778  "unknown log class near beginning of `%U'",
779  format_unformat_error, line_input);
780  }
781  }
782  else
783  {
784  return clib_error_return (0, "unknown log level near beginning of `%U'",
785  format_unformat_error, line_input);
786  }
787  return 0;
788 }
789 
790 /* *INDENT-OFF* */
791 VLIB_CLI_COMMAND (cli_test_log, static) = {
792  .path = "test log",
793  .short_help = "test log <level> <class> <subclass> <message>",
794  .function = test_log_class_subclass,
795 };
796 /* *INDENT-ON* */
797 
798 static clib_error_t *
800 {
801  vlib_log_main_t *lm = &log_main;
802  vlib_log_class_config_t *cc, tmp;
803  uword *p;
804 
805  if (lm->config_index_by_name == 0)
806  lm->config_index_by_name = hash_create_string (0, sizeof (uword));
807 
808  p = hash_get_mem (lm->config_index_by_name, name);
809 
810  if (p)
811  return clib_error_return (0, "logging class '%s' already configured",
812  name);
813 
814  clib_memset_u8 (&tmp, 0xff, sizeof (vlib_log_class_config_t));
815 
817  {
818  if (unformat (input, "level %U", unformat_vlib_log_level, &tmp.level))
819  ;
820  else if (unformat (input, "syslog-level %U", unformat_vlib_log_level,
821  &tmp.syslog_level))
822  ;
823  else if (unformat (input, "rate-limit %u", &tmp.rate_limit))
824  ;
825  else
826  return clib_error_return (0, "unknown input '%U'",
827  format_unformat_error, input);
828  }
829 
830  vec_add2 (lm->configs, cc, 1);
831  clib_memcpy_fast (cc, &tmp, sizeof (vlib_log_class_config_t));
832  cc->name = name;
833  hash_set_mem (lm->config_index_by_name, name, cc - lm->configs);
834  return 0;
835 }
836 
837 static clib_error_t *
839 {
840  vlib_log_main_t *lm = &log_main;
841  unformat_input_t sub_input;
842  u8 *class = 0;
843 
845  {
846  if (unformat (input, "size %d", &lm->size))
847  vec_validate (lm->entries, lm->size);
848  else if (unformat (input, "unthrottle-time %d", &lm->unthrottle_time))
849  ;
850  else if (unformat (input, "default-log-level %U",
852  ;
853  else if (unformat (input, "default-syslog-log-level %U",
856  ;
857  else if (unformat (input, "add-to-elog"))
858  lm->add_to_elog = 1;
859  else if (unformat (input, "class %s %U", &class,
860  unformat_vlib_cli_sub_input, &sub_input))
861  {
862  clib_error_t *err;
863  err = log_config_class (vm, (char *) class, &sub_input);
864  class = 0;
865  unformat_free (&sub_input);
866  if (err)
867  return err;
868  }
869  else
870  {
871  return unformat_parse_error (input);
872  }
873  }
874 
875  return 0;
876 }
877 
879 
880 /*
881  * fd.io coding-style-patch-verification: ON
882  *
883  * Local Variables:
884  * eval: (c-set-style "gnu")
885  * End:
886  */
vlib_log_class_t vlib_log_register_class(char *class, char *subclass)
Definition: log.c:338
#define vec_validate(V, I)
Make sure vector is long enough for given index (no header, unspecified alignment) ...
Definition: vec.h:509
static clib_error_t * show_log_config(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:437
__clib_export u8 * va_format(u8 *s, const char *fmt, va_list *va)
Definition: format.c:387
vlib_log_class_t class
Definition: log.h:84
unix_main_t unix_main
Definition: main.c:62
static clib_error_t * show_log(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:402
static const int colors[]
Definition: log.c:38
#define UNIX_FLAG_NOSYSLOG
Definition: unix.h:62
static clib_error_t * log_config_class(vlib_main_t *vm, char *name, unformat_input_t *input)
Definition: log.c:799
u8 * format_time_float(u8 *s, va_list *args)
Definition: unix-formats.c:846
#define vec_c_string_is_terminated(V)
Test whether a vector is a NULL terminated c-string.
Definition: vec.h:1082
u8 * format_vlib_log_level(u8 *s, va_list *args)
Definition: log.c:352
vlib_log_entry_t * entries
Definition: log.h:94
vlib_log_level_t level
Definition: log.h:54
u32 flags
Definition: unix.h:58
VLIB_REGISTER_LOG_CLASS(log_log, static)
static vlib_log_class_data_t * get_class_data(vlib_log_class_t ci)
Definition: log.c:75
int last_log_entry()
Definition: log.c:62
#define clib_memcpy_fast(a, b, c)
Definition: string.h:81
vlib_log_level_t syslog_level
Definition: log.h:56
static f64 vlib_time_now(vlib_main_t *vm)
Definition: main.h:334
static clib_error_t * clear_log(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:485
#define vec_terminate_c_string(V)
(If necessary) NULL terminate a vector containing a c-string.
Definition: vec.h:1090
#define vec_add1(V, E)
Add 1 element to end of vector (unspecified alignment).
Definition: vec.h:592
vlib_log_class_data_t * classes
Definition: log.h:95
#define vec_add2(V, P, N)
Add N elements to end of vector V, return pointer to new elements in P.
Definition: vec.h:630
uword unformat_user(unformat_input_t *input, unformat_function_t *func,...)
Definition: unformat.c:989
f64 timestamp
Definition: log.h:45
#define hash_set_mem(h, key, value)
Definition: hash.h:275
int add_to_elog
Definition: log.h:111
vlib_main_t * vm
Definition: in2out_ed.c:1580
vlib_log_level_t level
Definition: log.h:73
vlib_log_class_registration_t * registrations
Definition: log.h:114
unsigned char u8
Definition: types.h:56
static uword unformat_vlib_log_subclass(unformat_input_t *input, va_list *args)
Definition: log.c:720
#define vec_reset_length(v)
Reset vector length to zero NULL-pointer tolerant.
double f64
Definition: types.h:142
#define vec_add(V, E, N)
Add N elements to end of vector V (no header, unspecified alignment)
Definition: vec.h:668
__clib_export word fformat(FILE *f, char *fmt,...)
Definition: format.c:462
static clib_error_t * vlib_log_init(vlib_main_t *vm)
Definition: log.c:369
log_level
Definition: vpe_types.api:33
u32 vlib_log_class_t
Definition: vlib.h:51
static clib_error_t * log_config(vlib_main_t *vm, unformat_input_t *input)
Definition: log.c:838
#define VLIB_INIT_FUNCTION(x)
Definition: init.h:173
struct timeval time_zero_timeval
Definition: log.h:105
description fragment has unexpected format
Definition: map.api:433
struct vlib_log_registration * next
Definition: log.h:89
#define vec_elt_at_index(v, i)
Get vector value at index i checking that i is in bounds.
#define clib_error_return(e, args...)
Definition: error.h:99
#define UNIX_FLAG_NOCOLOR
Definition: unix.h:63
char * subclass_name
Definition: log.h:83
static vlib_log_class_t vlib_log_register_class_internal(char *class, char *subclass, u32 limit)
Definition: log.c:266
u8 * format_indent(u8 *s, va_list *args)
Definition: log.c:102
unsigned int u32
Definition: types.h:88
#define vlib_log_debug(...)
Definition: log.h:136
vlib_log_class_t vlib_log_register_class_rate_limit(char *class, char *subclass, u32 limit)
Definition: log.c:345
static const int log_level_to_syslog_priority[]
Definition: log.c:49
int default_log_level
Definition: log.h:99
#define hash_create_string(elts, value_bytes)
Definition: hash.h:690
unformat_function_t unformat_line_input
Definition: format.h:282
Definition: cJSON.c:84
static clib_error_t * set_log_class(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:565
struct _unformat_input_t unformat_input_t
#define foreach_vlib_log_level
Definition: log.h:21
u32 size
Definition: vhost_user.h:106
int default_syslog_log_level
Definition: log.h:100
#define ELOG_DATA(em, f)
Definition: elog.h:484
int size
Definition: log.h:96
static clib_error_t * set_log_unth_time(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:651
vlib_log_main_t log_main
Definition: log.c:23
vlib_log_level_t syslog_level
Definition: log.h:74
static clib_error_t * test_log_class_subclass(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:745
int next
Definition: log.h:96
int cJSON_bool fmt
Definition: cJSON.h:160
RFC5424 syslog protocol declarations.
The fine-grained event logger allows lightweight, thread-safe event logging at minimum cost...
u8 * format_unformat_input(u8 *s, va_list *va)
Definition: unformat.c:143
#define VLIB_EARLY_CONFIG_FUNCTION(x, n,...)
Definition: init.h:226
#define UNFORMAT_END_OF_INPUT
Definition: format.h:144
svmdb_client_t * c
static_always_inline uword vlib_get_thread_index(void)
Definition: threads.h:219
sll srl srl sll sra u16x4 i
Definition: vector_sse42.h:317
#define vec_free(V)
Free vector&#39;s memory (no header).
Definition: vec.h:380
void vlib_log(vlib_log_level_t level, vlib_log_class_t class, char *fmt,...)
Definition: log.c:131
static vlib_log_subclass_data_t * get_subclass_data(vlib_log_class_t ci)
Definition: log.c:82
elog_main_t elog_main
Definition: main.h:224
vlib_log_subclass_data_t * subclasses
Definition: log.h:68
#define ELOG_TYPE_DECLARE(f)
Definition: elog.h:442
#define vec_is_equal(v1, v2)
Compare two vectors, not NULL-pointer tolerant.
Definition: vec.h:981
string name[64]
Definition: ip.api:44
int default_rate_limit
Definition: log.h:98
#define VLIB_CLI_COMMAND(x,...)
Definition: cli.h:158
uword unformat_vlib_cli_sub_input(unformat_input_t *i, va_list *args)
Definition: cli.c:163
Definition: log.h:41
#define ASSERT(truth)
void vlib_cli_output(vlib_main_t *vm, char *fmt,...)
Definition: cli.c:696
vlib_log_class_t class
Definition: log.h:44
#define UNIX_FLAG_INTERACTIVE
Definition: unix.h:60
int count
Definition: log.h:96
vlib_log_level_t
Definition: log.h:32
static uword unformat_vlib_log_class(unformat_input_t *input, va_list *args)
Definition: log.c:541
static uword unformat_vlib_log_level(unformat_input_t *input, va_list *args)
Definition: log.c:516
char const int length
Definition: cJSON.h:163
vlib_log_level_t default_syslog_level
Definition: log.h:86
char * class_name
Definition: log.h:82
static_always_inline void clib_memset_u8(void *p, u8 val, uword count)
Definition: string.h:424
vlib_log_level_t level
Definition: log.h:43
f64 time_zero
Definition: log.h:106
static vlib_main_t * vlib_get_main(void)
Definition: global_funcs.h:23
vlib_log_class_config_t * configs
Definition: log.h:109
#define unformat_parse_error(input)
Definition: format.h:268
vlib_log_level_t default_level
Definition: log.h:85
u32 max_class_name_length
Definition: log.h:102
u8 * format_vlib_log_class(u8 *s, va_list *args)
Definition: log.c:89
#define vec_len(v)
Number of elements in vector (rvalue-only, NULL tolerant)
static clib_error_t * set_log_size(vlib_main_t *vm, unformat_input_t *input, vlib_cli_command_t *cmd)
Definition: log.c:684
#define vlib_log_info(...)
Definition: log.h:135
u64 uword
Definition: types.h:112
static void unformat_free(unformat_input_t *i)
Definition: format.h:162
__clib_export u32 elog_string(elog_main_t *em, char *fmt,...)
add a string to the event-log string table
Definition: elog.c:582
#define hash_get_mem(h, key)
Definition: hash.h:269
f64 last_event_timestamp
Definition: log.h:58
u8 * format_unformat_error(u8 *s, va_list *va)
Definition: unformat.c:91
uword * config_index_by_name
Definition: log.h:110
static int log_level_is_enabled(vlib_log_level_t level, vlib_log_level_t configured)
Definition: log.c:121
#define vec_foreach(var, vec)
Vector iterator.
u8 count
Definition: dhcp.api:208
u8 * string
Definition: log.h:46
int unthrottle_time
Definition: log.h:101
uword unformat(unformat_input_t *i, const char *fmt,...)
Definition: unformat.c:978
static uword unformat_check_input(unformat_input_t *i)
Definition: format.h:170