/* -*- c++ -*- */ /* * Copyright 2012 Free Software Foundation, Inc. * * This file is part of GNU Radio * * GNU Radio 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, or (at your option) * any later version. * * GNU Radio 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 GNU Radio; see the file COPYING. If not, write to * the Free Software Foundation, Inc., 51 Franklin Street, * Boston, MA 02110-1301, USA. */ /******************************************************************************* * Author: Mark Plett * Description: * The gr_log module wraps the log4cpp library for logging in gnuradio. *******************************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include #include #ifdef ENABLE_GR_LOG #ifdef HAVE_LOG4CPP namespace gr { bool logger_config::logger_configured(false); /************************ BEGIN LOG4CPP HELPERS ***********************/ /* Logger config class. This is a singleton that controls how * log4cpp is configured If watch_period>0 a thread is started to * watch teh config file for changes. */ // Getters of logger_config logger_config& logger_config::get_instance(void) { static logger_config instance; return instance; } std::string logger_config::get_filename() { logger_config& in=get_instance(); return in.filename; } unsigned int logger_config::get_watch_period() { logger_config& in=get_instance(); return in.watch_period; } // Method to watch config file for changes void logger_config::watch_file(std::string filename, unsigned int watch_period) { std::time_t last_write(boost::filesystem::last_write_time(filename)); std::time_t current_time(0); while(true) { try { current_time = boost::filesystem::last_write_time(filename); if(current_time>last_write) { //std::cout<<"GNURadio Reloading logger configuration:"<0) { instance.watch_thread = new boost::thread(watch_file, instance.filename, instance.watch_period); } } } // Method to stop the watcher thread void logger_config::stop_watch() { logger_config& instance = get_instance(); if(instance.watch_thread) { instance.watch_thread->interrupt(); instance.watch_thread->join(); delete(instance.watch_thread); instance.watch_thread=NULL; } } // Method to reset logger configuration void logger_config::reset_config(void) { logger_config& instance = get_instance(); stop_watch(); std::vector *loggers = log4cpp::Category::getCurrentCategories(); std::vector::iterator logger = loggers->begin(); // We can't destroy categories but we can neuter them by removing all appenders. for(;logger!=loggers->end();logger++) { (*logger)->removeAllAppenders(); } instance.filename = std::string(""); instance.watch_period = 0; logger_configured = false; } /***************** Functions to call log4cpp methods *************************/ logger_ptr logger_get_logger(std::string name) { if(log4cpp::Category::exists(name)) { logger_ptr logger = &log4cpp::Category::getInstance(name); return logger; } else { logger_ptr logger = &log4cpp::Category::getInstance(name); logger->setPriority(log4cpp::Priority::NOTSET); return logger; } } bool logger_load_config(const std::string &config_filename) { if(config_filename.size() != 0) { try { log4cpp::PropertyConfigurator::configure(config_filename); return true; } catch(log4cpp::ConfigureFailure &e) { std::cerr << "Logger config failed :" << e.what() << std::endl; } } return false; } void logger_set_level(logger_ptr logger, const std::string &level) { std::string nocase = level; std::transform(level.begin(), level.end(), nocase.begin(), ::tolower); if(nocase == "off" || nocase == "notset") logger_set_level(logger, log4cpp::Priority::NOTSET); else if(nocase == "all" || nocase == "debug") logger_set_level(logger, log4cpp::Priority::DEBUG); else if(nocase == "info") logger_set_level(logger, log4cpp::Priority::INFO); else if(nocase == "notice") logger_set_level(logger, log4cpp::Priority::NOTICE); else if(nocase == "warn") logger_set_level(logger, log4cpp::Priority::WARN); else if(nocase == "error") logger_set_level(logger, log4cpp::Priority::ERROR); else if(nocase == "crit") logger_set_level(logger, log4cpp::Priority::CRIT); else if(nocase == "alert") logger_set_level(logger, log4cpp::Priority::ALERT); else if(nocase=="fatal") logger_set_level(logger, log4cpp::Priority::FATAL); else if(nocase == "emerg") logger_set_level(logger, log4cpp::Priority::EMERG); else throw std::runtime_error("logger_set_level: Bad level type.\n"); } void logger_set_level(logger_ptr logger, log4cpp::Priority::Value level) { logger->setPriority(level); } void logger_get_level(logger_ptr logger, std::string &level) { log4cpp::Priority::Value levelPtr = logger->getPriority(); if(levelPtr == log4cpp::Priority::NOTSET) level = "noset"; if(levelPtr == log4cpp::Priority::DEBUG) level = "debug"; if(levelPtr == log4cpp::Priority::INFO) level = "info"; if(levelPtr == log4cpp::Priority::NOTICE) level = "notice"; if(levelPtr == log4cpp::Priority::WARN) level = "warn"; if(levelPtr == log4cpp::Priority::ERROR) level = "error"; if(levelPtr == log4cpp::Priority::CRIT) level = "crit"; if(levelPtr == log4cpp::Priority::ALERT) level = "alert"; if(levelPtr == log4cpp::Priority::FATAL) level = "fatal"; if(levelPtr == log4cpp::Priority::EMERG) level = "emerg"; } void logger_get_level(logger_ptr logger,log4cpp::Priority::Value level) { level = logger->getPriority(); } void logger_add_console_appender(logger_ptr logger, std::string target, std::string pattern) { log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); log4cpp::Appender* app; if(target=="stdout") app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cout); else app = new log4cpp::OstreamAppender("ConsoleAppender::",&std::cerr); layout->setConversionPattern(pattern); app->setLayout(layout); logger->setAppender(*app); } void logger_add_file_appender(logger_ptr logger, std::string filename, bool append, std::string pattern) { log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); log4cpp::Appender* app = new log4cpp::FileAppender("FileAppender::"+filename, filename); layout->setConversionPattern(pattern); app->setLayout(layout); logger->setAppender(app); } void logger_add_rollingfile_appender(logger_ptr logger, std::string filename, size_t filesize, int bkup_index, bool append, mode_t mode, std::string pattern) { log4cpp::PatternLayout* layout = new log4cpp::PatternLayout(); log4cpp::Appender* app = new log4cpp::RollingFileAppender("RollFileAppender::" + filename, filename, filesize, bkup_index, append, mode); layout->setConversionPattern(pattern); app->setLayout(layout); logger->setAppender(app); } std::vector logger_get_logger_names(void) { std::vector names; std::vector *loggers = log4cpp::Category::getCurrentCategories(); std::vector::iterator logger = loggers->begin(); for(;logger!=loggers->end();logger++) { names.push_back((*logger)->getName()); } return names; } } /* namespace gr */ #endif /* HAVE_LOG4CPP */ /****** Start Methods to provide Python the capabilities of the macros ********/ void gr_logger_config(const std::string config_filename, unsigned int watch_period) { GR_CONFIG_AND_WATCH_LOGGER(config_filename, watch_period); } std::vector gr_logger_get_logger_names(void) { std::vector names; GR_GET_LOGGER_NAMES(names); return names; } void gr_logger_reset_config(void) { GR_RESET_CONFIGURATION(); } // Remaining capability provided by gr::logger class in gnuradio/logger.h #endif /* ENABLE_GR_LOGGER */