summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/logger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/lib/logger.cc')
-rw-r--r--gnuradio-runtime/lib/logger.cc323
1 files changed, 323 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/logger.cc b/gnuradio-runtime/lib/logger.cc
new file mode 100644
index 0000000000..dceb18471f
--- /dev/null
+++ b/gnuradio-runtime/lib/logger.cc
@@ -0,0 +1,323 @@
+/* -*- 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 <gnuradio/logger.h>
+#include <stdexcept>
+#include <algorithm>
+
+
+#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:"<<filename<<std::endl;
+ last_write = current_time;
+ // Should we wipe out all old configuration or just add the
+ // new? Just adding... logger_reset_config();
+ logger_configured = logger_load_config(filename);
+ }
+ boost::this_thread::sleep(boost::posix_time::time_duration(0,0,watch_period,0));
+ }
+ catch(const boost::thread_interrupted&) {
+ std::cout<<"GNURadio leaving logger config file watch."<<std::endl;
+ break;
+ }
+ }
+ }
+
+ // Method to load the confifuration. It only loads if the filename
+ // or watch has changed
+ void
+ logger_config::load_config(std::string filename,unsigned int watch_period)
+ {
+ logger_config& instance = get_instance();
+ // Only reconfigure if filename or watch has changed
+ if(!logger_configured) {
+ instance.filename = filename;
+ instance.watch_period = watch_period;
+ // Stop any file watching thread
+ if(instance.watch_thread!=NULL)
+ stop_watch();
+ // Load configuration
+ std::cout<<"GNURadio Loading logger configuration:"<<instance.filename<<std::endl;
+ logger_configured = logger_load_config(instance.filename);
+ // Start watch if required
+ if(instance.watch_period>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<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
+ std::vector<log4cpp::Category*>::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::cout << "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<std::string>
+ logger_get_logger_names(void)
+ {
+ std::vector<std::string> names;
+ std::vector<log4cpp::Category*> *loggers = log4cpp::Category::getCurrentCategories();
+ std::vector<log4cpp::Category*>::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<std::string>
+gr_logger_get_logger_names(void)
+{
+ std::vector<std::string> 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 */