/* * Copyright (c) 2018 Cisco and/or its affiliates. * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at: * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include #include #include #include vlib_log_main_t log_main = { .default_log_level = VLIB_LOG_LEVEL_NOTICE, .default_syslog_log_level = VLIB_LOG_LEVEL_WARNING, .unthrottle_time = 3, .size = 512, .default_rate_limit = 50, }; int last_log_entry () { vlib_log_main_t *lm = &log_main; int i; i = lm->next - lm->count; if (i < 0) i += lm->size; return i; } static vlib_log_class_data_t * get_class_data (vlib_log_class_t ci) { vlib_log_main_t *lm = &log_main; return vec_elt_at_index (lm->classes, (ci >> 16)); } static vlib_log_subclass_data_t * get_subclass_data (vlib_log_class_t ci) { vlib_log_class_data_t *c = get_class_data (ci); return vec_elt_at_index (c->subclasses, (ci & 0xffff)); } static int vlib_log_level_to_syslog_priority (vlib_log_level_t level) { switch (level) { #define LOG_DISABLED LOG_DEBUG #define _(n,uc,lc) \ case VLIB_LOG_LEVEL_##uc:\ return LOG_##uc; foreach_vlib_log_level #undef _ #undef LOG_DISABLED } return LOG_DEBUG; } u8 * format_vlib_log_class (u8 * s, va_list * args) { vlib_log_class_t ci = va_arg (*args, vlib_log_class_t); vlib_log_class_data_t *c = get_class_data (ci); vlib_log_subclass_data_t *sc = get_subclass_data (ci); if (sc->name) return format (s, "%v/%v", c->name, sc->name); else return format (s, "%v", c->name, 0); } void vlib_log (vlib_log_level_t level, vlib_log_class_t class, char *fmt, ...) { vlib_main_t *vm = vlib_get_main (); vlib_log_main_t *lm = &log_main; vlib_log_entry_t *e; vlib_log_subclass_data_t *sc = get_subclass_data (class); va_list va; f64 t = vlib_time_now (vm); f64 delta = t - sc->last_event_timestamp; 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 (level > sc->level) { use_formatted_log_entry = false; goto syslog; } if ((delta > lm->unthrottle_time) || (sc->is_throttling == 0 && (delta > 1))) { sc->last_event_timestamp = t; sc->last_sec_count = 0; sc->is_throttling = 0; } else { sc->last_sec_count++; if (sc->last_sec_count > sc->rate_limit) return; else if (sc->last_sec_count == sc->rate_limit) { vec_reset_length (s); s = format (0, "--- message(s) throttled ---"); sc->is_throttling = 1; } } if (s == 0) { va_start (va, fmt); s = va_format (s, fmt, &va); va_end (va); } e = vec_elt_at_index (lm->entries, lm->next); vec_free (e->string); e->level = level; e->class = class; e->string = s; e->timestamp = t; lm->next = (lm->next + 1) % lm->size; if (lm->size > lm->count) lm->count++; syslog: if (sc->syslog_level != VLIB_LOG_LEVEL_DISABLED && level <= sc->syslog_level) { u8 *tmp = format (NULL, "%U", format_vlib_log_class, class); if (use_formatted_log_entry) { syslog (vlib_log_level_to_syslog_priority (level), "%.*s: %.*s", (int) vec_len (tmp), tmp, (int) (vec_len (s) - (vec_c_string_is_terminated (s) ? 1 : 0)), s); } else { tmp = format (tmp, ": "); va_start (va, fmt); tmp = va_format (tmp, fmt, &va); va_end (va); syslog (vlib_log_level_to_syslog_priority (level), "%.*s", (int) (vec_len (tmp) - (vec_c_string_is_terminated (tmp) ? 1 : 0)), tmp); } vec_free (tmp); } } 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_subclass_data_t *s; 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; break; } } if (!c) { vec_add2 (lm->classes, c, 1); c->index = c - lm->classes; c->name = format (0, "%s", class); } vec_add2 (c->subclasses, s, 1); s->index = s - c->subclasses; s->name = subclass ? format (0, "%s", subclass) : 0; 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_level_t i = va_arg (*args, vlib_log_level_t); char *t = 0; switch (i) { #define _(v,uc,lc) case VLIB_LOG_LEVEL_##uc: t = #lc; break; foreach_vlib_log_level #undef _ default: return format (s, "unknown"); }
import gc
import pprint
import vpp_papi
from vpp_papi_provider import VppPapiProvider
import objgraph
from pympler import tracker
tr = tracker.SummaryTracker()

"""
  Internal debug module

  The module provides functions for debugging test framework
"""


def on_tear_down_class(cls):
    gc.collect()
    tr.print_diff()
    objects = gc.get_objects()
    counter = 0
    with open(cls.tempdir + '/python_objects.txt', 'w') as f:
        interesting = [
            o for o in objects
            if isinstance(o, (VppPapiProvider, vpp_papi.VPP))]
        del objects
        gc.