summaryrefslogtreecommitdiff
path: root/gnuradio-runtime/lib/gr_logger.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gnuradio-runtime/lib/gr_logger.cc')
-rw-r--r--gnuradio-runtime/lib/gr_logger.cc295
1 files changed, 295 insertions, 0 deletions
diff --git a/gnuradio-runtime/lib/gr_logger.cc b/gnuradio-runtime/lib/gr_logger.cc
new file mode 100644
index 0000000000..82737128bb
--- /dev/null
+++ b/gnuradio-runtime/lib/gr_logger.cc
@@ -0,0 +1,295 @@
+/* -*- 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.
+*******************************************************************************/
+
+#ifndef ENABLE_GR_LOG
+#include "config.h"
+#endif
+
+#include <gr_logger.h>
+#include <stdexcept>
+#include <algorithm>
+
+#ifdef ENABLE_GR_LOG
+#ifdef HAVE_LOG4CPP
+
+/**************************** 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_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(instance.filename!=filename || watch_period!=instance.watch_period){
+ 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_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;
+}
+
+/***************** Functions to call log4cpp methods *************************/
+
+gr_logger_ptr
+logger_get_logger(std::string name)
+{
+ if(log4cpp::Category::exists(name)){
+ gr_logger_ptr logger = &log4cpp::Category::getInstance(name);
+ return logger;
+ }
+ else
+ {
+ gr_logger_ptr logger = &log4cpp::Category::getInstance(name);
+ logger->setPriority(log4cpp::Priority::NOTSET);
+ return logger;
+ };
+};
+
+void
+logger_load_config(const std::string &config_filename)
+{
+ if(config_filename.size() != 0) {
+ try
+ {
+ log4cpp::PropertyConfigurator::configure(config_filename);
+ }
+ catch( log4cpp::ConfigureFailure &e )
+ {
+ std::cout << "Logger config failed :" << e.what() << std::endl;
+ }
+ };
+}
+
+void
+logger_set_level(gr_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(gr_logger_ptr logger, log4cpp::Priority::Value level)
+{
+ logger->setPriority(level);
+}
+
+void
+logger_get_level(gr_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(gr_logger_ptr logger,log4cpp::Priority::Value level)
+{
+ level = logger->getPriority();
+}
+
+void
+logger_add_console_appender(gr_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(gr_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(gr_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;
+
+}
+
+#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 gr_logger.h
+
+#endif /* ENABLE_GR_LOGGER */