diff --git a/common/include/villas/graph/directed.hpp b/common/include/villas/graph/directed.hpp index d94acaf95..d4c4c9ab4 100644 --- a/common/include/villas/graph/directed.hpp +++ b/common/include/villas/graph/directed.hpp @@ -52,7 +52,7 @@ public: DirectedGraph(const std::string& name = "DirectedGraph") : lastVertexId(0), lastEdgeId(0) { - logger = loggerGetOrCreate(name); + logger = logging.get(name); } std::shared_ptr getVertex(VertexIdentifier vertexId) const @@ -290,7 +290,7 @@ protected: std::map> vertices; std::map> edges; - SpdLogger logger; + Logger logger; }; } // namespacae graph diff --git a/common/include/villas/log.h b/common/include/villas/log.h index 96bdac568..1966ce254 100644 --- a/common/include/villas/log.h +++ b/common/include/villas/log.h @@ -23,18 +23,14 @@ #pragma once +#include + +#include + #ifdef __cplusplus extern "C" { #endif -#include -#include -#include -#include - -#include -#include - /* The log level which is passed as first argument to print() */ enum log_level { LOG_LVL_DEBUG, @@ -44,8 +40,6 @@ enum log_level { LOG_LVL_STATS, }; -typedef void (*log_cb_t)(struct log *l, enum log_level lvl, const char *fmt, va_list va); - /** Debug facilities. * * To be or-ed with the debug level @@ -77,7 +71,7 @@ enum log_facilities { LOG_WEBSOCKET = (1L << 29), LOG_OPAL = (1L << 30), LOG_COMEDI = (1L << 31), - LOG_IB = (1L << 32), + LOG_IB = (1LL << 32), /* Classes */ LOG_NODES = LOG_NODE | LOG_SOCKET | LOG_FILE | LOG_FPGA | LOG_NGSI | LOG_WEBSOCKET | LOG_OPAL | LOG_COMEDI | LOG_IB, @@ -85,78 +79,10 @@ enum log_facilities { LOG_ALL = ~0xFF }; -struct log { - enum state state; - - const char *name; - - struct timespec epoch; /**< A global clock used to prefix the log messages. */ - - struct winsize window; /**< Size of the terminal window. */ - int width; /**< The real usable log output width which fits into one line. */ - - /** Debug level used by the debug() macro. - * It defaults to V (defined by the Makefile) and can be - * overwritten by the 'debug' setting in the configuration file. */ - int level; - long facilities; /**< Debug facilities used by the debug() macro. */ - const char *path; /**< Path of the log file. */ - char *prefix; /**< Prefix each line with this string. */ - int syslog; /**< Whether or not to log to syslogd. */ - bool tty; /**< Is the log file a tty? */ - - log_cb_t callback; - - FILE *file; /**< Send all log output to this file / stdout / stderr. */ -}; - -/** The global log instance. */ -extern struct log *global_log; - -/** Initialize log object */ -int log_init(struct log *l, const char *name, int level, long faciltities); - -void log_set_callback(struct log *l, log_cb_t cb); - -int log_open(struct log *l); - -int log_close(struct log *l); - -/** Destroy log object */ -int log_destroy(struct log *l); - -/** Set logging facilities based on expression. - * - * Currently we support two types of expressions: - * 1. A comma seperated list of logging facilities - * 2. A comma seperated list of logging facilities which is prefixes with an exclamation mark '!' - * - * The first case enables only faciltities which are in the list. - * The second case enables all faciltities with exception of those which are in the list. - * - * @param expression The expression - * @return The new facilties mask (see enum log_faciltities) - */ -int log_set_facility_expression(struct log *l, const char *expression); - -/** Logs variadic messages to stdout. - * - * @param lvl The log level - * @param fmt The format string (printf alike) - */ -void log_print(struct log *l, enum log_level lvl, const char *fmt, ...) - __attribute__ ((format(printf, 3, 4))); - -/** Logs variadic messages to stdout. - * - * @param lvl The log level - * @param fmt The format string (printf alike) - * @param va The variadic argument list (see stdarg.h) - */ -void log_vprint(struct log *l, enum log_level lvl, const char *fmt, va_list va); +int log_get_width(); /** Printf alike debug message with level. */ -void debug(long lvl, const char *fmt, ...) +void debug(long long lvl, const char *fmt, ...) __attribute__ ((format(printf, 2, 3))); /** Printf alike info message. */ @@ -179,6 +105,10 @@ void error(const char *fmt, ...) void serror(const char *fmt, ...) __attribute__ ((format(printf, 1, 2))); +/** Print configuration error and exit. */ +void jerror(json_error_t *err, const char *fmt, ...) + __attribute__ ((format(printf, 2, 3))); + #ifdef __cplusplus } #endif diff --git a/common/include/villas/log.hpp b/common/include/villas/log.hpp index dffb22e24..bdf172668 100644 --- a/common/include/villas/log.hpp +++ b/common/include/villas/log.hpp @@ -25,33 +25,51 @@ #include -#define SPDLOG_LEVEL_NAMES { "trace", "debug", "info ", "warn ", "error", "crit ", "off " } -#define SPDLOG_NAME_WIDTH 17 #define SPDLOG_FMT_EXTERNAL #include -#include +#include #include -#define _ESCAPE "\x1b" -#define TXT_RESET_ALL _ESCAPE "[0m" +#include -#define TXT_RESET_BOLD _ESCAPE "[21m" -#define TXT_BOLD(s) _ESCAPE "[1m" + std::string(s) + TXT_RESET_BOLD +#include -#define TXT_RESET_COLOR _ESCAPE "[39m" -#define TXT_RED(s) _ESCAPE "[31m" + std::string(s) + TXT_RESET_COLOR -#define TXT_GREEN(s) _ESCAPE "[32m" + std::string(s) + TXT_RESET_COLOR -#define TXT_YELLOW(s) _ESCAPE "[33m" + std::string(s) + TXT_RESET_COLOR -#define TXT_BLUE(s) _ESCAPE "[34m" + std::string(s) + TXT_RESET_COLOR +namespace villas { -using SpdLogger = std::shared_ptr; +/* Forward declarations */ +class Log; -inline SpdLogger loggerGetOrCreate(const std::string& logger_name) -{ - auto logger = spdlog::get(logger_name); - if(not logger) { - logger = spdlog::stdout_color_mt(logger_name); - } - return logger; -} +using Logger = std::shared_ptr; + +extern Log logging; + +class Log { + +public: + using DistSink = std::shared_ptr; + using Level = spdlog::level::level_enum; + +protected: + Logger logger = logging.get("log"); + DistSink sinks; + + std::string pattern; /**< Logging format. */ + std::string prefix; /**< Prefix each line with this string. */ + +public: + + Log(Level level = Level::info); + + /**< Get the real usable log output width which fits into one line. */ + int getWidth(); + + void parse(json_t *cfg); + + Logger get(const std::string &name); + + void setLevel(Level lvl); + void setLevel(const std::string &lvl); +}; + +} // namespace villas diff --git a/common/include/villas/log_config.h b/common/include/villas/log_config.h deleted file mode 100644 index 982754322..000000000 --- a/common/include/villas/log_config.h +++ /dev/null @@ -1,37 +0,0 @@ -/** Logging routines that depend on jansson. - * - * @file - * @author Steffen Vogel - * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLAScommon - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#pragma once - -struct log; - -#include - -#include - -/** Parse logging configuration. */ -int log_parse(struct log *l, json_t *cfg); - -/** Print configuration error and exit. */ -void jerror(json_error_t *err, const char *fmt, ...) - __attribute__ ((format(printf, 2, 3))); diff --git a/common/tests/main.cpp b/common/include/villas/log_opal_sink.hpp similarity index 51% rename from common/tests/main.cpp rename to common/include/villas/log_opal_sink.hpp index ea1e4ae78..56410e866 100644 --- a/common/tests/main.cpp +++ b/common/include/villas/log_opal_sink.hpp @@ -1,7 +1,8 @@ -/** Main Unit Test entry point. +/** Log sink for OPAL-RTs OpalPrint(). * + * @file * @author Steffen Vogel - * @copyright 2017-2018, Steffen Vogel + * @copyright 2018, Institute for Automation of Complex Power Systems, EONERC * @license GNU General Public License (version 3) * * VILLAScommon @@ -20,29 +21,45 @@ * along with this program. If not, see . *********************************************************************************/ -#include -#include +#pragma once + +#include #include -#include +#include +#include -void init_logging(); +namespace villas { +namespace node { -int main(int argc, char *argv[]) +template +class OpalSink : public spdlog::sinks::base_sink { - int ret; - init_logging(); +protected: + void sink_it_(const spdlog::details::log_msg& msg) override + { +#ifdef ENABLE_OPAL_ASYNC + fmt::memory_buffer formatted; - /* Run criterion tests */ - auto tests = criterion_initialize(); + sink::formatter_->format(msg, formatted); - ret = criterion_handle_args(argc, argv, true); - if (ret) - ret = !criterion_run_all_tests(tests); + auto str = fmt::to_string(formatted).c_str(); - criterion_finalize(tests); + OpalPrint(PROJECT_NAME ": %s\n", str); +#endif + } - return ret; -} + void flush_() override + { + /* nothing to do */ + } +}; + +using OpalSink_mt = OpalSink; +using OpalSink_st = OpalSink; + + +} // namespace node +} // namespace villas diff --git a/common/include/villas/memory.hpp b/common/include/villas/memory.hpp index 9a766eaa2..9a509d65e 100644 --- a/common/include/villas/memory.hpp +++ b/common/include/villas/memory.hpp @@ -135,7 +135,7 @@ public: { // CRTP derivedAlloc = static_cast(this); - logger = loggerGetOrCreate(derivedAlloc->getName()); + logger = logging.get(derivedAlloc->getName()); // default deallocation callback free = [&](MemoryBlock* mem) { @@ -207,7 +207,7 @@ protected: protected: MemoryBlock::deallocator_fn free; - SpdLogger logger; + Logger logger; // optional, if allocator should own the memory block std::unique_ptr memoryBlock; diff --git a/common/include/villas/memory_manager.hpp b/common/include/villas/memory_manager.hpp index dc87293d4..80a6667c8 100644 --- a/common/include/villas/memory_manager.hpp +++ b/common/include/villas/memory_manager.hpp @@ -97,7 +97,7 @@ private: // This is a singleton, so private constructor ... MemoryManager() : memoryGraph("MemoryGraph"), - logger(loggerGetOrCreate("MemoryManager")) + logger(logging.get("MemoryManager")) { pathCheckFunc = [&](const MemoryGraph::Path& path) { return this->pathCheck(path); @@ -262,7 +262,7 @@ private: std::map addrSpaceLookup; /// Logger for universal access in this class - SpdLogger logger; + Logger logger; MemoryGraph::check_path_fn pathCheckFunc; diff --git a/common/include/villas/plugin.hpp b/common/include/villas/plugin.hpp index 094cfb511..9bfb1c96d 100644 --- a/common/include/villas/plugin.hpp +++ b/common/include/villas/plugin.hpp @@ -47,9 +47,11 @@ protected: public: - static SpdLogger + static Logger getLogger() - { return loggerGetOrCreate("plugin:registry"); } + { + return logging.get("plugin:registry"); + } static void add(Plugin *p) { @@ -126,9 +128,11 @@ protected: std::string description; std::string path; - SpdLogger + Logger getLogger() - { return loggerGetOrCreate("plugin:" + name); } + { + return logging.get("plugin:" + name); + } }; } // namespace plugin diff --git a/common/lib/CMakeLists.txt b/common/lib/CMakeLists.txt index 05f78f285..52e7a5c98 100644 --- a/common/lib/CMakeLists.txt +++ b/common/lib/CMakeLists.txt @@ -32,9 +32,8 @@ add_library(villas-common SHARED kernel/kernel.c kernel/rt.c list.c - log.c - log_config.c - log_helper.c + log.cpp + log_legacy.cpp memory.cpp memory_manager.cpp plugin.cpp diff --git a/common/lib/kernel/vfio.cpp b/common/lib/kernel/vfio.cpp index fb1e535e3..7c222478a 100644 --- a/common/lib/kernel/vfio.cpp +++ b/common/lib/kernel/vfio.cpp @@ -44,7 +44,9 @@ #include #include -static auto logger = loggerGetOrCreate("Vfio"); +using namespace villas; + +static auto logger = logging.get("kernel:vfio"); static const char *vfio_pci_region_names[] = { "PCI_BAR0", // VFIO_PCI_BAR0_REGION_INDEX, diff --git a/common/lib/log.c b/common/lib/log.c deleted file mode 100644 index 54a6e0b04..000000000 --- a/common/lib/log.c +++ /dev/null @@ -1,332 +0,0 @@ -/** Logging and debugging routines - * - * @author Steffen Vogel - * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLAScommon - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include -#include -#include -#include -#include - -#ifdef ENABLE_OPAL_ASYNC -/* Define RTLAB before including OpalPrint.h for messages to be sent - * to the OpalDisplay. Otherwise stdout will be used. */ - #define RTLAB - #include "OpalPrint.h" -#endif - -struct log *global_log; -struct log default_log; - -/* We register a default log instance */ -__attribute__((constructor)) -void register_default_log() -{ - int ret; - - ret = log_init(&default_log, "default", V, LOG_ALL); - if (ret) - error("Failed to initalize log"); - - ret = log_open(&default_log); - if (ret) - error("Failed to start log"); - - global_log = &default_log; -} - -static const char *level_strs[] = { - CLR_GRY("Debug"), /* LOG_LVL_DEBUG */ - CLR_WHT("Info "), /* LOG_LVL_INFO */ - CLR_YEL("Warn "), /* LOG_LVL_WARN */ - CLR_RED("Error"), /* LOG_LVL_ERROR */ - CLR_MAG("Stats") /* LOG_LVL_STATS */ -}; - -/** List of debug facilities as strings */ -static const char *facilities_strs[] = { - "pool", /* LOG_POOL */ - "queue", /* LOG_QUEUE */ - "config", /* LOG_CONFIG */ - "hook", /* LOG_HOOK */ - "path", /* LOG_PATH */ - "node", /* LOG_NODE */ - "mem", /* LOG_MEM */ - "web", /* LOG_WEB */ - "api", /* LOG_API */ - "log", /* LOG_LOG */ - "vfio", /* LOG_VFIO */ - "pci", /* LOG_PCI */ - "xil", /* LOG_XIL */ - "tc", /* LOG_TC */ - "if", /* LOG_IF */ - "advio", /* LOG_ADVIO */ - "io", /* LOG_IO */ - - /* Node-types */ - "socket", /* LOG_SOCKET */ - "file", /* LOG_FILE */ - "fpga", /* LOG_FPGA */ - "ngsi", /* LOG_NGSI */ - "websocket", /* LOG_WEBSOCKET */ - "opal", /* LOG_OPAL */ - "comedi", /* LOG_COMEDI */ - "ib", /* LOG_IB */ -}; - -static void log_resize(int signal, siginfo_t *sinfo, void *ctx) -{ - int ret; - - ret = ioctl(STDOUT_FILENO, TIOCGWINSZ, &global_log->window); - if (ret) - return; - - global_log->width = global_log->window.ws_col - 25; - if (global_log->prefix) - global_log->width -= strlenp(global_log->prefix); - - debug(LOG_LOG | 15, "New terminal size: %dx%x", global_log->window.ws_row, global_log->window.ws_col); -} - -int log_init(struct log *l, const char *name, int level, long facilitites) -{ - int ret; - - /* Register this log instance globally */ - global_log = l; - - l->name = name; - l->level = level; - l->syslog = 0; - l->facilities = facilitites; - l->file = stderr; - l->path = NULL; - l->callback = NULL; - - l->epoch = time_now(); - l->prefix = getenv("VILLAS_LOG_PREFIX"); - - /* Register signal handler which is called whenever the - * terminal size changes. */ - if (l->file == stderr) { - struct sigaction sa_resize = { - .sa_flags = SA_SIGINFO, - .sa_sigaction = log_resize - }; - - sigemptyset(&sa_resize.sa_mask); - - ret = sigaction(SIGWINCH, &sa_resize, NULL); - if (ret) - return ret; - - /* Try to get initial window size */ - ioctl(STDERR_FILENO, TIOCGWINSZ, &l->window); - - /* Fallback if for some reason we can not determine a prober window size */ - if (l->window.ws_col == 0) - l->window.ws_col = 150; - if (l->window.ws_row == 0) - l->window.ws_row = 50; - } - else { - l->window.ws_col = LOG_WIDTH; - l->window.ws_row = LOG_HEIGHT; - } - - l->width = l->window.ws_col - 25; - if (l->prefix) - l->width -= strlenp(l->prefix); - - l->state = STATE_INITIALIZED; - - return 0; -} - -void log_set_callback(struct log *l, log_cb_t cb) -{ - l->callback = cb; -} - -int log_open(struct log *l) -{ - if (l->path) { - l->file = fopen(l->path, "a+");; - if (!l->file) { - l->file = stderr; - error("Failed to open log file '%s'", l->path); - } - } - else - l->file = stderr; - - l->tty = isatty(fileno(l->file)); - - if (l->syslog) { - openlog(NULL, LOG_PID, LOG_DAEMON); - } - - l->state = STATE_OPENED; - - debug(LOG_LOG | 5, "Log sub-system started: level=%d, faciltities=%#lx, path=%s", l->level, l->facilities, l->path); - - return 0; -} - -int log_close(struct log *l) -{ - if (l->state != STATE_OPENED) - return 0; - - if (l->file != stderr && l->file != stdout) { - fclose(l->file); - } - - if (l->syslog) { - closelog(); - } - - l->state = STATE_CLOSED; - - return 0; -} - -int log_destroy(struct log *l) -{ - default_log.epoch = l->epoch; - - global_log = &default_log; - - l->state = STATE_DESTROYED; - - return 0; -} - -int log_set_facility_expression(struct log *l, const char *expression) -{ - bool negate; - char *copy, *token; - long mask = 0, facilities = 0; - - copy = strdup(expression); - token = strtok(copy, ","); - - while (token != NULL) { - if (token[0] == '!') { - token++; - negate = true; - } - else - negate = false; - - /* Check for some classes */ - if (!strcmp(token, "all")) - mask = LOG_ALL; - else if (!strcmp(token, "nodes")) - mask = LOG_NODES; - else if (!strcmp(token, "kernel")) - mask = LOG_KERNEL; - else { - for (int ind = 0; ind < ARRAY_LEN(facilities_strs); ind++) { - if (!strcmp(token, facilities_strs[ind])) { - mask = (1 << (ind+8)); - goto found; - } - } - - error("Invalid log class '%s'", token); - } - -found: if (negate) - facilities &= ~mask; - else - facilities |= mask; - - token = strtok(NULL, ","); - } - - l->facilities = facilities; - - free(copy); - - return l->facilities; -} - -void log_print(struct log *l, enum log_level lvl, const char *fmt, ...) -{ - va_list ap; - - va_start(ap, fmt); - log_vprint(l, lvl, fmt, ap); - va_end(ap); -} - -void log_vprint(struct log *l, enum log_level lvl, const char *fmt, va_list ap) -{ - struct timespec ts = time_now(); - static __thread char buf[1024]; - - if (l->callback) { - l->callback(l, lvl, fmt, ap); - return; - } - - int off = 0; - int len = sizeof(buf); - - /* Optional prefix */ - if (l->prefix) - off += snprintf(buf + off, len - off, "%s", l->prefix); - - /* Timestamp & Severity */ - off += snprintf(buf + off, len - off, "%10.3f %-5s ", time_delta(&l->epoch, &ts), level_strs[lvl]); - - /* Format String */ - off += vsnprintf(buf + off, len - off, fmt, ap); - - /* Output */ -#ifdef ENABLE_OPAL_ASYNC - OpalPrint(PROJECT_NAME ": %s\n", buf); -#endif - if (l->file) { - if (l->tty == false) - decolor(buf); - - fprintf(l->file, "%s\n", buf); - } - - if (l->syslog) { - if (l->tty == true) // Only decolor if not done before - decolor(buf); - - vsyslog(LOG_INFO, fmt, ap); - } -} diff --git a/common/lib/log.cpp b/common/lib/log.cpp new file mode 100644 index 000000000..a0cb2713b --- /dev/null +++ b/common/lib/log.cpp @@ -0,0 +1,146 @@ +/** Logging and debugging routines + * + * @author Steffen Vogel + * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC + * @license GNU General Public License (version 3) + * + * VILLAScommon + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + *********************************************************************************/ + +#include +#include +#include + +#include +#include + +using namespace villas; + +/** The global log instance */ +Log villas::logging; + +Log::Log(Level level) : + sinks(std::make_shared()), + pattern("%H:%M:%S %P %^%l%$: %v") +{ + char *p = getenv("VILLAS_LOG_PREFIX"); + if (p) + prefix = p; + + spdlog::set_level(level); + spdlog::set_pattern(pattern, spdlog::pattern_time_type::utc); + + auto sink = std::make_shared(); + + sink->set_pattern(prefix + pattern); + sinks->add_sink(sink); +} + +int Log::getWidth() +{ + int width = Terminal::getCols() - 25; + + if (!prefix.empty()) + width -= prefix.length(); + + return width; +} + +Logger Log::get(const std::string &name) +{ + auto logger = spdlog::get(name); + + if (not logger) + logger = std::make_shared(name, sinks); + + return logger; +} + +void Log::parse(json_t *cfg) +{ + const char *level = NULL; + const char *path = NULL; + const char *pattern = NULL; + + int syslog; + int ret; + + json_error_t err; + json_t *json_expressions; + + ret = json_unpack_ex(cfg, &err, 0, "{ s?: s, s?: s, s?: s, s?: b, s?: s }", + "level", &level, + "file", &path, + "expressions", &json_expressions, + "syslog", &syslog, + "pattern", &pattern + ); + if (ret) + throw new JsonError(err); + + if (level) + setLevel(level); + + if (path) { + auto sink = std::make_shared(path); + + sinks->add_sink(sink); + } + + if (syslog) { + auto sink = std::make_shared("villas", LOG_PID, LOG_DAEMON); + + sinks->add_sink(sink); + } + + if (json_expressions) { + if (!json_is_array(json_expressions)) + throw new ConfigError(json_expressions, "node-config.html#node-config-logging-expressions", "The 'expressions' setting must be a list of objects."); + + size_t i; + json_t *json_expression; + json_array_foreach(json_expressions, i, json_expression) { + const char *name; + const char *lvl; + + ret = json_unpack_ex(json_expression, &err, 0, "{ s: s, s: s }", + "name", &name, + "level", &lvl + ); + if (ret) + throw new JsonError(err); + + auto logger = get(name); + auto level = spdlog::level::from_str(lvl); + + logger->set_level(level); + } + } +} + +void Log::setLevel(Level lvl) +{ + spdlog::set_level(lvl); +} + +void Log::setLevel(const std::string &lvl) +{ + auto level = spdlog::level::from_str(lvl); + + setLevel(level); +} + + diff --git a/common/lib/log_config.c b/common/lib/log_config.c deleted file mode 100644 index ab97dac4e..000000000 --- a/common/lib/log_config.c +++ /dev/null @@ -1,98 +0,0 @@ -/** Logging routines that depend on jansson. - * - * @author Steffen Vogel - * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLASconfig - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#include -#include -#include -#include -#include - -#include -#include -#include -#include - -int log_parse_wrapper(struct log *l, json_t *cfg) -{ - int ret; - json_t *json_logging = NULL; - json_error_t err; - - if (cfg) { - ret = json_unpack_ex(cfg, &err, 0, "{s?: o}", - "logging", &json_logging - ); - if (ret) - jerror(&err, "Failed to parse logging from global configuration"); - - if (json_logging) - log_parse(l, json_logging); - } - - return 0; -} - -int log_parse(struct log *l, json_t *cfg) -{ - const char *facilities = NULL; - const char *path = NULL; - int ret; - - json_error_t err; - - ret = json_unpack_ex(cfg, &err, 0, "{ s?: i, s?: s, s?: s, s?: b }", - "level", &l->level, - "file", &path, - "facilities", &facilities, - "syslog", &l->syslog - ); - if (ret) - jerror(&err, "Failed to parse logging configuration"); - - if (path) - l->path = strdup(path); - - if (facilities) - log_set_facility_expression(l, facilities); - - l->state = STATE_PARSED; - - return 0; -} - -void jerror(json_error_t *err, const char *fmt, ...) -{ - va_list ap; - char *buf = NULL; - - va_start(ap, fmt); - vstrcatf(&buf, fmt, ap); - va_end(ap); - - log_print(global_log, LOG_LVL_ERROR, "%s:", buf); - log_print(global_log, LOG_LVL_ERROR, " %s in %s:%d:%d", err->text, err->source, err->line, err->column); - - free(buf); - - killme(SIGABRT); - pause(); -} diff --git a/common/lib/log_helper.c b/common/lib/log_legacy.cpp similarity index 56% rename from common/lib/log_helper.c rename to common/lib/log_legacy.cpp index 535f92c1e..5e8a1d00e 100644 --- a/common/lib/log_helper.c +++ b/common/lib/log_legacy.cpp @@ -20,97 +20,99 @@ * along with this program. If not, see . *********************************************************************************/ -#include #include -#include +#include +#include #include -#include +#include -void debug(long class, const char *fmt, ...) +using namespace villas; + +int log_get_width() +{ + return logging.getWidth(); +} + +void debug(long long, const char *fmt, ...) { va_list ap; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; - int lvl = class & 0xFF; - int fac = class & ~0xFF; + va_start(ap, fmt); + vasprintf(&buf, fmt, ap); + va_end(ap); - if (((fac == 0) || (fac & l->facilities)) && (lvl <= l->level)) { - va_start(ap, fmt); + logger->debug(buf); - log_vprint(l, LOG_LVL_DEBUG, fmt, ap); - - if (l->syslog) - syslog(LOG_DEBUG, fmt, ap); - - va_end(ap); - } + free(buf); } void info(const char *fmt, ...) { va_list ap; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; va_start(ap, fmt); - - log_vprint(l, LOG_LVL_INFO, fmt, ap); - - if (l->syslog) - syslog(LOG_INFO, fmt, ap); - + vasprintf(&buf, fmt, ap); va_end(ap); + + logger->info(buf); + + free(buf); } void warn(const char *fmt, ...) { va_list ap; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; va_start(ap, fmt); - - log_vprint(l, LOG_LVL_WARN, fmt, ap); - - if (l->syslog) - syslog(LOG_WARNING, fmt, ap); - + vasprintf(&buf, fmt, ap); va_end(ap); + + logger->warn(buf); + + free(buf); } void stats(const char *fmt, ...) { va_list ap; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; va_start(ap, fmt); - - log_vprint(l, LOG_LVL_STATS, fmt, ap); - - if (l->syslog) - syslog(LOG_INFO, fmt, ap); - + vasprintf(&buf, fmt, ap); va_end(ap); + + logger->info(buf); + + free(buf); } void error(const char *fmt, ...) { va_list ap; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; va_start(ap, fmt); - - log_vprint(l, LOG_LVL_ERROR, fmt, ap); - - if (l->syslog) - syslog(LOG_ERR, fmt, ap); - + vasprintf(&buf, fmt, ap); va_end(ap); + logger->error(buf); + + free(buf); + killme(SIGABRT); pause(); } @@ -118,18 +120,35 @@ void error(const char *fmt, ...) void serror(const char *fmt, ...) { va_list ap; - char *buf = NULL; - struct log *l = global_log; + auto logger = logging.get("default"); + char *buf; va_start(ap, fmt); - vstrcatf(&buf, fmt, ap); + vasprintf(&buf, fmt, ap); va_end(ap); - log_print(l, LOG_LVL_ERROR, "%s: %m (%u)", buf, errno); - - if (l->syslog) - syslog(LOG_ERR, "%s: %m (%u)", buf, errno); + logger->error(buf); + + free(buf); + + killme(SIGABRT); + pause(); +} + +void jerror(json_error_t *err, const char *fmt, ...) +{ + va_list ap; + + auto logger = logging.get("default"); + char *buf; + + va_start(ap, fmt); + vasprintf(&buf, fmt, ap); + va_end(ap); + + logger->error("{}:", buf); + logger->error(" {} in {}:{}:{}", err->text, err->source, err->line, err->column); free(buf); diff --git a/common/lib/memory.cpp b/common/lib/memory.cpp index 8c0390b39..de06de27d 100644 --- a/common/lib/memory.cpp +++ b/common/lib/memory.cpp @@ -192,7 +192,7 @@ HostDmaRam::HostDmaRamAllocator::HostDmaRamAllocator(int num) : num(num) { auto& mm = MemoryManager::get(); - logger = loggerGetOrCreate(getName()); + logger = logging.get(getName()); if(getSize() == 0) { logger->error("Zero-sized DMA buffer not supported, is the kernel module loaded?"); diff --git a/common/lib/memory_manager.cpp b/common/lib/memory_manager.cpp index 284bcee13..40affa547 100644 --- a/common/lib/memory_manager.cpp +++ b/common/lib/memory_manager.cpp @@ -189,7 +189,7 @@ MemoryTranslation::getForeignAddr(uintptr_t addrInLocalAddrSpace) const MemoryTranslation& MemoryTranslation::operator+=(const MemoryTranslation& other) { - auto logger = loggerGetOrCreate("MemoryTranslation"); + auto logger = logging.get("MemoryTranslation"); // set level to debug to enable debug output logger->set_level(spdlog::level::info); diff --git a/common/tests/CMakeLists.txt b/common/tests/CMakeLists.txt index 3b8e930ce..27a190988 100644 --- a/common/tests/CMakeLists.txt +++ b/common/tests/CMakeLists.txt @@ -21,7 +21,6 @@ ############################################################################## add_executable(unit-tests-common - main.cpp logging.cpp advio.cpp diff --git a/common/tests/advio.cpp b/common/tests/advio.cpp index c2a3a6814..f0364c765 100644 --- a/common/tests/advio.cpp +++ b/common/tests/advio.cpp @@ -23,7 +23,6 @@ #include #include -#include #include #include @@ -32,14 +31,10 @@ * The Sciebo share is read/write accessible via WebDAV. */ #define BASE_URI "https://1Nrd46fZX8HbggT:badpass@rwth-aachen.sciebo.de/public.php/webdav/node/tests" -void init_logging(); - TestSuite(advio, - .description = "Advanced file IO", - .init = init_logging + .description = "Advanced file IO" ); - Test(advio, islocal) { int ret; diff --git a/common/tests/bitset.cpp b/common/tests/bitset.cpp index ad0ae7e37..30bc6e9ad 100644 --- a/common/tests/bitset.cpp +++ b/common/tests/bitset.cpp @@ -27,11 +27,8 @@ #define LEN 1027 -void init_logging(); - TestSuite(bitset, - .description = "Bitset datastructure", - .init = init_logging + .description = "Bitset datastructure" ); Test(bitset, simple) diff --git a/common/tests/graph.cpp b/common/tests/graph.cpp index 22b5a91d3..d0bf50973 100644 --- a/common/tests/graph.cpp +++ b/common/tests/graph.cpp @@ -27,16 +27,13 @@ #include #include -void init_logging(); +using namespace villas; -TestSuite(graph, - .init = init_logging, - .description = "Graph library" -); +TestSuite(graph, .description = "Graph library"); Test(graph, basic, .description = "DirectedGraph") { - auto logger = loggerGetOrCreate("test:graph:basic"); + auto logger = logging.get("test:graph:basic"); villas::graph::DirectedGraph<> g("test:graph:basic"); logger->info("Testing basic graph construction and modification"); @@ -67,7 +64,7 @@ Test(graph, basic, .description = "DirectedGraph") Test(graph, path, .description = "Find path") { - auto logger = loggerGetOrCreate("test:graph:path"); + auto logger = logging.get("test:graph:path"); logger->info("Testing path finding algorithm"); using Graph = villas::graph::DirectedGraph<>; @@ -131,7 +128,7 @@ Test(graph, path, .description = "Find path") Test(graph, memory_manager, .description = "Global Memory Manager") { - auto logger = loggerGetOrCreate("test:graph:mm"); + auto logger = logging.get("test:graph:mm"); auto& mm = villas::MemoryManager::get(); logger->info("Create address spaces"); diff --git a/common/tests/hash_table.cpp b/common/tests/hash_table.cpp index 660b1dc3b..c83939d43 100644 --- a/common/tests/hash_table.cpp +++ b/common/tests/hash_table.cpp @@ -28,12 +28,7 @@ static const char *keys[] = { "able", "achieve", "acoustics", "action", "activity", "aftermath", "afternoon", "afterthought", "apparel", "appliance", "beginner", "believe", "bomb", "border", "boundary", "breakfast", "cabbage", "cable", "calculator", "calendar", "caption", "carpenter", "cemetery", "channel", "circle", "creator", "creature", "education", "faucet", "feather", "friction", "fruit", "fuel", "galley", "guide", "guitar", "health", "heart", "idea", "kitten", "laborer", "language" }; static const char *values[] = { "lawyer", "linen", "locket", "lumber", "magic", "minister", "mitten", "money", "mountain", "music", "partner", "passenger", "pickle", "picture", "plantation", "plastic", "pleasure", "pocket", "police", "pollution", "railway", "recess", "reward", "route", "scene", "scent", "squirrel", "stranger", "suit", "sweater", "temper", "territory", "texture", "thread", "treatment", "veil", "vein", "volcano", "wealth", "weather", "wilderness", "wren" }; -void init_logging(); - -TestSuite(hash_table, - .description = "Hash table datastructure", - .init = init_logging -); +TestSuite(hash_table, .description = "Hash table datastructure"); Test(hash_table, hash_table_lookup) { diff --git a/common/tests/hist.cpp b/common/tests/hist.cpp index cfbd9d2a6..14db2ddee 100644 --- a/common/tests/hist.cpp +++ b/common/tests/hist.cpp @@ -30,12 +30,7 @@ const double test_data[] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; /* Histogram of test_data with 200 buckets between -100 and 100 */ const int hist_result[] = {}; -void init_logging(); - -TestSuite(hist, - .description = "Histogram", - .init = init_logging -); +TestSuite(hist, .description = "Histogram"); Test(hist, simple) { struct hist h; diff --git a/common/tests/json_buffer.cpp b/common/tests/json_buffer.cpp index eeb602ee4..c7d54147b 100644 --- a/common/tests/json_buffer.cpp +++ b/common/tests/json_buffer.cpp @@ -30,14 +30,9 @@ using namespace villas; -void init_logging(); - using villas::Buffer; -TestSuite(buffer, - .description = "Buffer datastructure", - .init = init_logging -); +TestSuite(buffer, .description = "Buffer datastructure"); Test(json_buffer, decode) { diff --git a/common/tests/kernel.cpp b/common/tests/kernel.cpp index 00ac24eeb..b3c1c27ba 100644 --- a/common/tests/kernel.cpp +++ b/common/tests/kernel.cpp @@ -25,12 +25,7 @@ #include #include -void init_logging(); - -TestSuite(kernel, - .description = "Kernel features", - .init = init_logging -); +TestSuite(kernel, .description = "Kernel features"); #ifdef __linux__ diff --git a/common/tests/list.cpp b/common/tests/list.cpp index 7714d5d6b..97c2a0717 100644 --- a/common/tests/list.cpp +++ b/common/tests/list.cpp @@ -34,12 +34,7 @@ struct data { int data; }; -void init_logging(); - -TestSuite(list, - .description = "List datastructure", - .init = init_logging -); +TestSuite(list, .description = "List datastructure"); Test(list, list_lookup) { diff --git a/common/tests/log.cpp b/common/tests/log.cpp deleted file mode 100644 index 3f2a47fbf..000000000 --- a/common/tests/log.cpp +++ /dev/null @@ -1,77 +0,0 @@ -/** Unit tests for log functions - * - * @author Steffen Vogel - * @copyright 2017-2018, Institute for Automation of Complex Power Systems, EONERC - * @license GNU General Public License (version 3) - * - * VILLAScommon - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - *********************************************************************************/ - -#include -#include - -#include -#include - -struct param { - const char *expression; - long expected; -}; - -static struct log log; - -void init_logging(); - -static void init() -{ - log_init(&log, "test_logger", V, LOG_ALL); - - init_logging(); -} - -static void fini() -{ - log_destroy(&log); -} - -TestSuite(log, - .description = "Log system", - .init = init, - .fini = fini -); - -ParameterizedTestParameters(log, facility_expression) -{ - static struct param params[] = { - { "all,!pool", LOG_ALL & ~LOG_POOL }, - { "pool,!pool", LOG_POOL & ~LOG_POOL }, - { "pool,nodes,!socket", (LOG_POOL | LOG_NODES) & ~LOG_SOCKET }, - { "kernel", LOG_KERNEL }, - { "ngsi", LOG_NGSI }, - { "all", LOG_ALL }, - { "!all", 0 }, - { "", 0 } - }; - - return cr_make_param_array(struct param, params, ARRAY_LEN(params)); -} - -ParameterizedTest(struct param *p, log, facility_expression) -{ - log_set_facility_expression(&log, p->expression); - - cr_assert_eq(log.facilities, p->expected, "log.faciltities is %#lx not %#lx", log.facilities, p->expected); -} diff --git a/common/tests/logging.cpp b/common/tests/logging.cpp index f8cb8b23e..8f8cf88be 100644 --- a/common/tests/logging.cpp +++ b/common/tests/logging.cpp @@ -26,9 +26,9 @@ #include #include -#include #include -#include + +using namespace villas; extern "C" { /* We override criterions function here */ @@ -40,8 +40,8 @@ extern "C" { static const char *color_reset = "\e[0m"; struct criterion_prefix_data { - const char *prefix; - const char *color; + const char *prefix; + const char *color; }; static int format_msg(char *buf, size_t buflen, const char *msg, va_list args) @@ -58,7 +58,7 @@ static int format_msg(char *buf, size_t buflen, const char *msg, va_list args) void criterion_log_noformat(enum criterion_severity severity, const char *msg) { - auto logger = loggerGetOrCreate("criterion"); + auto logger = logging.get("criterion"); switch (severity) { case CR_LOG_WARNING: @@ -84,7 +84,7 @@ void criterion_vlog(enum criterion_logging_level /* level */, const char *msg, v format_msg(formatted_msg, sizeof(formatted_msg), msg, args); - auto logger = loggerGetOrCreate("tests"); + auto logger = logging.get("test"); logger->info(formatted_msg); } @@ -101,7 +101,7 @@ void criterion_plog(enum criterion_logging_level /* level */, const struct crite format_msg(formatted_msg, sizeof(formatted_msg), msg, args); va_end(args); - auto logger = loggerGetOrCreate("tests"); + auto logger = logging.get("test"); if (!strcmp(prefix->prefix, "----") && !strcmp(prefix->color, "\33[0;34m")) logger->info(formatted_msg); @@ -124,46 +124,3 @@ void criterion_plog(enum criterion_logging_level /* level */, const struct crite else logger->info(formatted_msg); } - -extern "C" -void log_cb(struct log *l, enum log_level lvl, const char *fmt, va_list args) -{ - char formatted_msg[1024]; - - auto logger = loggerGetOrCreate(l->name); - - //if (level < criterion_options.logging_threshold) - // return; - - format_msg(formatted_msg, sizeof(formatted_msg), fmt, args); - - switch (lvl) { - case LOG_LVL_DEBUG: - logger->debug(formatted_msg); - break; - - case LOG_LVL_INFO: - logger->info(formatted_msg); - break; - - case LOG_LVL_WARN: - logger->warn(formatted_msg); - break; - - case LOG_LVL_ERROR: - logger->error(formatted_msg); - break; - - case LOG_LVL_STATS: - logger->info("Stats: {}", formatted_msg); - break; - } -} - -void init_logging() -{ - log_set_callback(global_log, log_cb); - - spdlog::set_level(spdlog::level::trace); - spdlog::set_pattern("[%T] [%^%l%$] [%n] %v"); -} diff --git a/common/tests/task.cpp b/common/tests/task.cpp index f74059127..a7a052094 100644 --- a/common/tests/task.cpp +++ b/common/tests/task.cpp @@ -27,12 +27,7 @@ #include #include -void init_logging(); - -TestSuite(task, - .description = "Periodic timer tasks", - .init = init_logging -); +TestSuite(task, .description = "Periodic timer tasks"); Test(task, rate, .timeout = 10) { diff --git a/common/tests/timing.cpp b/common/tests/timing.cpp index ff860b9d7..1d989eb2d 100644 --- a/common/tests/timing.cpp +++ b/common/tests/timing.cpp @@ -26,12 +26,7 @@ #include -void init_logging(); - -TestSuite(timing, - .description = "Time measurements", - .init = init_logging -); +TestSuite(timing, .description = "Time measurements"); Test(timing, time_now) { diff --git a/common/tests/tsc.cpp b/common/tests/tsc.cpp index 771cc8e78..1b0aa0e7a 100644 --- a/common/tests/tsc.cpp +++ b/common/tests/tsc.cpp @@ -28,12 +28,7 @@ #define CNT (1 << 18) -void init_logging(); - -TestSuite(tsc, - .description = "Timestamp counters", - .init = init_logging -); +TestSuite(tsc, .description = "Timestamp counters"); Test(tsc, increasing) { diff --git a/common/tests/utils.cpp b/common/tests/utils.cpp index f8cb80f9d..d7a09708a 100644 --- a/common/tests/utils.cpp +++ b/common/tests/utils.cpp @@ -25,12 +25,8 @@ #include #include -void init_logging(); -TestSuite(utils, - .description = "Utilities", - .init = init_logging -); +TestSuite(utils, .description = "Utilities"); /* Simple normality test for 1,2,3s intervals */ Test(utils, box_muller)