aboutsummaryrefslogtreecommitdiffstats
path: root/host/lib/utils/log.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'host/lib/utils/log.cpp')
-rw-r--r--host/lib/utils/log.cpp325
1 files changed, 182 insertions, 143 deletions
diff --git a/host/lib/utils/log.cpp b/host/lib/utils/log.cpp
index 42219e925..1d87a0b3d 100644
--- a/host/lib/utils/log.cpp
+++ b/host/lib/utils/log.cpp
@@ -18,17 +18,17 @@
#include <uhd/utils/log.hpp>
#include <uhd/utils/static.hpp>
#include <uhd/utils/paths.hpp>
-#include <boost/filesystem.hpp>
-#include <boost/thread/mutex.hpp>
+#include <uhd/utils/tasks.hpp>
+#include <uhd/transport/bounded_buffer.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
+#include <boost/make_shared.hpp>
#include <boost/thread/locks.hpp>
-#include <boost/interprocess/sync/file_lock.hpp>
+#include <boost/thread/mutex.hpp>
#include <fstream>
#include <cctype>
+#include <atomic>
-namespace fs = boost::filesystem;
namespace pt = boost::posix_time;
-namespace ip = boost::interprocess;
static const std::string PURPLE = "\033[35;1m"; // purple
static const std::string BLUE = "\033[34;1m"; // blue
@@ -38,7 +38,9 @@ static const std::string RED = "\033[31;0m"; // red
static const std::string BRED = "\033[31;1m"; // bright red
static const std::string RESET_COLORS = "\033[39;0m"; // reset colors
-
+/***********************************************************************
+ * Helpers
+ **********************************************************************/
static const std::string verbosity_color(const uhd::log::severity_level &level){
switch(level){
case (uhd::log::trace):
@@ -58,86 +60,178 @@ static const std::string verbosity_color(const uhd::log::severity_level &level){
}
}
+//! get the relative file path from the host directory
+inline std::string path_to_filename(std::string path)
+{
+ return path.substr(path.find_last_of("/\\") + 1);
+}
/***********************************************************************
- * Global resources for the logger
+ * Logger backends
**********************************************************************/
-class log_resource_type{
+
+
+void console_log(
+ const uhd::log::logging_info &log_info
+) {
+ std::clog
+#ifdef UHD_LOG_CONSOLE_COLOR
+ << verbosity_color(log_info.verbosity)
+#endif
+#ifdef UHD_LOG_CONSOLE_TIME
+ << "[" << pt::to_simple_string(log_info.time) << "] "
+#endif
+#ifdef UHD_LOG_CONSOLE_THREAD
+ << "[0x" << log_info.thread_id << "] "
+#endif
+#ifdef UHD_LOG_CONSOLE_SRC
+ << "[" << path_to_filename(log_info.file) << ":" << log_info.line << "] "
+#endif
+ << "[" << log_info.verbosity << "] "
+ << "[" << log_info.component << "] "
+#ifdef UHD_LOG_CONSOLE_COLOR
+ << RESET_COLORS
+#endif
+ << log_info.message
+ << std::endl
+ ;
+}
+
+class file_logger_backend
+{
public:
- uhd::log::severity_level level;
- uhd::log::severity_level file_level;
- uhd::log::severity_level console_level;
+ file_logger_backend(const std::string &file_path)
+ {
+ _file_stream.exceptions(std::ofstream::failbit | std::ofstream::badbit);
+ if (!file_path.empty()){
+ try {
+ _file_stream.open(file_path.c_str(), std::fstream::out | std::fstream::app);
+ } catch (const std::ofstream::failure& fail){
+ std::cerr << "Error opening log file: " << fail.what() << std::endl;
+ }
+ }
+
+ }
- log_resource_type(void): level(uhd::log::info), file_level(uhd::log::info), console_level(uhd::log::info){
+ void log(const uhd::log::logging_info &log_info)
+ {
+ if (_file_stream.is_open()){
+ _file_stream
+ << pt::to_simple_string(log_info.time) << ","
+ << "0x" << log_info.thread_id << ","
+ << path_to_filename(log_info.file) << ":" << log_info.line << ","
+ << log_info.verbosity << ","
+ << log_info.component << ","
+ << log_info.message
+ << std::endl;
+ ;
+ }
+ }
- //file lock pointer must be null
- _file_lock = NULL;
- //default to no file logging
- this->file_logging = false;
+ ~file_logger_backend()
+ {
+ if (_file_stream.is_open()){
+ _file_stream.close();
+ }
+ }
- //set the default log level
- this->level = uhd::log::off;
- this->file_level = uhd::log::off;
- this->console_level = uhd::log::off;
+private:
+ std::ofstream _file_stream;
+};
+
+/***********************************************************************
+ * Global resources for the logger
+ **********************************************************************/
+
+#define UHD_CONSOLE_LOGGER_KEY "console"
+#define UHD_FILE_LOGGER_KEY "file"
+
+class log_resource {
+public:
+ uhd::log::severity_level global_level;
+ std::map<std::string, uhd::log::severity_level> logger_level;
+
+ log_resource(void):
+ global_level(uhd::log::off),
+ _exit(false),
+ _log_queue(10)
+ {
//allow override from macro definition
#ifdef UHD_LOG_MIN_LEVEL
- this->level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_MIN_LEVEL), this->level);
-#endif
-#if defined(UHD_LOG_FILE_LEVEL) && defined(UHD_LOG_FILE_PATH)
- this->file_level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_FILE_LEVEL), this->file_level);
-#endif
-#ifdef UHD_LOG_CONSOLE_LEVEL
- this->console_level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_CONSOLE_LEVEL), this->console_level);
+ this->global_level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_MIN_LEVEL), this->global_level);
#endif
-#ifdef UHD_LOG_FILE
- this->log_file_target = BOOST_STRINGIZE(UHD_LOG_FILE);
- this->file_logging = true;
-#endif
-
- //allow override from environment variables
+ //allow override from environment variables
const char * log_level_env = std::getenv("UHD_LOG_LEVEL");
- if (log_level_env != NULL && log_level_env[0] != '\0') this->level = _get_log_level(log_level_env, this->level);
+ if (log_level_env != NULL && log_level_env[0] != '\0') this->global_level = _get_log_level(log_level_env, this->global_level);
- const char * log_file_level_env = std::getenv("UHD_LOG_FILE_LEVEL");
- if (log_file_level_env != NULL && log_file_level_env[0] != '\0') this->file_level = _get_log_level(log_file_level_env, this->file_level);
+// console logging support
+#ifndef UHD_LOG_CONSOLE_DISABLE
+ uhd::log::severity_level console_level = uhd::log::trace;
+#ifdef UHD_LOG_CONSOLE_LEVEL
+ console_level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_CONSOLE_LEVEL), console_level);
+#endif
const char * log_console_level_env = std::getenv("UHD_LOG_CONSOLE_LEVEL");
- if (log_console_level_env != NULL && log_console_level_env[0] != '\0') this->console_level = _get_log_level(log_console_level_env, this->console_level);
+ if (log_console_level_env != NULL && log_console_level_env[0] != '\0') console_level = _get_log_level(log_console_level_env, console_level);
+ logger_level[UHD_CONSOLE_LOGGER_KEY] = console_level;
+ _loggers[UHD_CONSOLE_LOGGER_KEY] = &console_log;
+#endif
+ uhd::log::severity_level file_level = uhd::log::trace;
+ std::string log_file_target;
+#if defined(UHD_LOG_FILE_LEVEL) && defined(UHD_LOG_FILE_PATH)
+ file_level = _get_log_level(BOOST_STRINGIZE(UHD_LOG_FILE_LEVEL), file_level);
+ log_file_target = BOOST_STRINGIZE(UHD_LOG_FILE);
+#endif
+ const char * log_file_level_env = std::getenv("UHD_LOG_FILE_LEVEL");
+ if (log_file_level_env != NULL && log_file_level_env[0] != '\0'){
+ file_level = _get_log_level(log_file_level_env, file_level);
+ }
const char* log_file_env = std::getenv("UHD_LOG_FILE");
if ((log_file_env != NULL) && (log_file_env[0] != '\0')) {
- this->log_file_target = log_file_env;
- this->file_logging = true;
+ log_file_target = std::string(log_file_env);
}
+ if (!log_file_target.empty()){
+ logger_level[UHD_FILE_LOGGER_KEY] = file_level;
+ auto F = boost::make_shared<file_logger_backend>(log_file_target);
+ _loggers[UHD_FILE_LOGGER_KEY] = [F](const uhd::log::logging_info& log_info){F->log(log_info);};
+ }
+ _pop_task = uhd::task::make([this](){this->pop_task();});
+
}
- ~log_resource_type(void){
- if (this->file_logging){
- boost::lock_guard<boost::mutex> lock(_mutex);
- _file_stream.close();
- if (_file_lock != NULL) delete _file_lock;
- }
+ ~log_resource(void){
+ _exit = true;
+ _pop_task.reset();
}
- void log_to_file(const std::string &log_msg){
- if ( this->file_logging ){
- boost::lock_guard<boost::mutex> lock(_mutex);
- if (_file_lock == NULL){
- _file_stream.open(this->log_file_target.c_str(), std::fstream::out | std::fstream::app);
- _file_lock = new ip::file_lock(this->log_file_target.c_str());
+ void push(const uhd::log::logging_info& log_info)
+ {
+
+ _log_queue.push_with_haste(log_info);
+ }
+
+ void pop_task()
+ {
+ while (!_exit) {
+ uhd::log::logging_info log_info;
+ if (_log_queue.pop_with_timed_wait(log_info, 1)){
+ for (const auto &logger : _loggers) {
+ auto level = logger_level.find(logger.first);
+ if(level != logger_level.end() && log_info.verbosity < level->second){
+ UHD_VAR(level->second)
+ continue;
+ }
+ logger.second(log_info);
+ }
}
- _file_lock->lock();
- _file_stream << log_msg << std::flush;
- _file_lock->unlock();
}
}
private:
- //! set the log level from a string that is either a digit or an enum name
- bool file_logging;
- std::string log_file_target;
+ uhd::task::sptr _pop_task;
uhd::log::severity_level _get_log_level(const std::string &log_level_str,
const uhd::log::severity_level &previous_level){
if (std::isdigit(log_level_str[0])) {
@@ -147,6 +241,7 @@ private:
log_level_num <= uhd::log::fatal) {
return log_level_num;
}else{
+ UHD_LOGGER_ERROR("LOG") << "Failed to set log level to: " << log_level_str;
return previous_level;
}
}
@@ -163,118 +258,62 @@ private:
return previous_level;
}
- //file stream and lock:
- std::ofstream _file_stream;
- ip::file_lock *_file_lock;
- boost::mutex _mutex;
+ std::atomic<bool> _exit;
+ std::map<std::string, uhd::log::log_fn_t> _loggers;
+ uhd::transport::bounded_buffer<uhd::log::logging_info> _log_queue; // Init auf size 10 oder so
};
-UHD_SINGLETON_FCN(log_resource_type, log_rs);
+UHD_SINGLETON_FCN(log_resource, log_rs);
/***********************************************************************
* The logger object implementation
**********************************************************************/
-//! get the relative file path from the host directory
-
-inline std::string path_to_filename(std::string path)
-{
- return path.substr(path.find_last_of("/\\") + 1);
-}
-
uhd::_log::log::log(
const uhd::log::severity_level verbosity,
const std::string &file,
const unsigned int line,
const std::string &component,
- const boost::thread::id id
- )
+ const boost::thread::id thread_id
+ ) :
+ _log_it(verbosity >= log_rs().global_level)
{
- _log_it = (verbosity >= log_rs().level);
- _log_file =(verbosity >= log_rs().file_level);
- _log_console = (verbosity >= log_rs().console_level);
- if (_log_it)
- {
- if (_log_file){
- const std::string time = pt::to_simple_string(pt::microsec_clock::local_time());
- _file
- << time << ","
- << "0x" << id << ","
- << path_to_filename(file) << ":" << line << ","
- << verbosity << ","
- << component << ","
- ;
+ if (_log_it){
+ this->_log_info = uhd::log::logging_info(
+ pt::microsec_clock::local_time(),
+ verbosity,
+ file,
+ line,
+ component,
+ thread_id);
}
-#ifndef UHD_LOG_CONSOLE_DISABLE
- if (_log_console){
-#ifdef UHD_LOG_CONSOLE_TIME
- const std::string time = pt::to_simple_string(pt::microsec_clock::local_time());
-#endif
- _console
-#ifdef UHD_LOG_CONSOLE_COLOR
- << verbosity_color(verbosity)
-#endif
-#ifdef UHD_LOG_CONSOLE_TIME
- << "[" << time << "] "
-#endif
-#ifdef UHD_LOG_CONSOLE_THREAD
- << "[0x" << id << "] "
-#endif
-#ifdef UHD_LOG_CONSOLE_SRC
- << "[" << path_to_filename(file) << ":" << line << "] "
-#endif
- << "[" << verbosity << "] "
- << "[" << component << "] "
-#ifdef UHD_LOG_CONSOLE_COLOR
- << RESET_COLORS
-#endif
- ;
- }
-#endif
- }
}
uhd::_log::log::~log(void)
{
- if (not _log_it)
- return;
-#ifndef UHD_LOG_CONSOLE_DISABLE
- if ( _log_console ){
- std::clog << _console.str() << _ss.str() << std::endl;
- }
-#endif
- if ( _log_file){
- _file << _ss.str() << std::endl;
- try{
- log_rs().log_to_file(_file.str());
- }
- catch(const std::exception &e){
- /*!
- * Critical behavior below.
- * The following steps must happen in order to avoid a lock-up condition.
- * This is because the message facility will call into the logging facility.
- * Therefore we must disable the logger (level = never) before messaging.
- */
- log_rs().level = uhd::log::off;
- std::cerr
- << "Logging failed: " << e.what() << std::endl
- << "Logging has been disabled for this process" << std::endl
- ;
- }
+ if (_log_it) {
+ this->_log_info.message = _ss.str();
+ log_rs().push(this->_log_info);
}
}
void
-uhd::_log::log::set_log_level(uhd::log::severity_level level){
- log_rs().level = level;
+uhd::log::set_log_level(uhd::log::severity_level level){
+ log_rs().global_level = level;
+}
+
+void
+uhd::log::set_logger_level(const std::string &key, uhd::log::severity_level level){
+ log_rs().logger_level[key] = level;
}
void
-uhd::_log::log::set_console_level(uhd::log::severity_level level){
- log_rs().console_level = level;
+uhd::log::set_console_level(uhd::log::severity_level level){
+ set_logger_level(UHD_CONSOLE_LOGGER_KEY, level);
}
void
-uhd::_log::log::set_file_level(uhd::log::severity_level level){
- log_rs().file_level = level;
+uhd::log::set_file_level(uhd::log::severity_level level){
+ set_logger_level(UHD_FILE_LOGGER_KEY, level);
}
+