LoggingService.cpp
Go to the documentation of this file.
00001 #include "logging/LoggingService.hpp"
00002 #include "logging/Category.hpp"
00003 #include "ocl/Component.hpp"
00004 
00005 #include <boost/algorithm/string.hpp>
00006 #include <log4cpp/Category.hh>
00007 #include <log4cpp/Priority.hh>
00008 #include <log4cpp/HierarchyMaintainer.hh>
00009 
00010 #include <rtt/Logger.hpp>
00011 #include <typeinfo>
00012 
00013 using namespace RTT;
00014 using namespace std;
00015 
00016 namespace OCL {
00017 namespace logging {
00018 
00019 LoggingService::LoggingService(std::string name) :
00020                 RTT::TaskContext(name),
00021         levels_prop("Levels","A PropertyBag defining the level of each category of interest."),
00022         additivity_prop("Additivity","A PropertyBag defining the additivity of each category of interest."),
00023         appenders_prop("Appenders","A PropertyBag defining the appenders for each category of interest."),
00024         logCategories_mtd("logCategories", &LoggingService::logCategories, this)
00025 {
00026     this->properties()->addProperty( levels_prop );
00027     this->properties()->addProperty( additivity_prop );
00028     this->properties()->addProperty( appenders_prop );
00029     this->provides()->addOperation( logCategories_mtd ).doc("Log category hierarchy (not realtime!)");
00030 }
00031 
00032 LoggingService::~LoggingService()
00033 {
00034 }
00035 
00036 bool LoggingService::configureHook()
00037 {
00038     log(Debug) << "Configuring LoggingService" << endlog();
00039 
00040     // set the priority/level for each category
00041 
00042     PropertyBag bag = levels_prop.value();  // an empty bag is ok
00043 
00044     bool ok = true;
00045     PropertyBag::const_iterator it;
00046     for (it=bag.getProperties().begin(); it != bag.getProperties().end(); ++it)
00047     {
00048         Property<std::string>* category = dynamic_cast<Property<std::string>* >( *it );
00049         if ( !category )
00050         {
00051             log(Error) << "Expected Property '"
00052                        << (*it)->getName() << "' to be of type string." << endlog();
00053         }
00054         else 
00055         {
00056             std::string categoryName = category->getName();
00057             std::string levelName    = category->value();
00058 
00059             // "" == categoryName implies the root category.
00060 
00061             // \todo else if level is empty
00062             
00063             // log4cpp only takes upper case
00064             boost::algorithm::to_upper(levelName);
00065             
00066             log4cpp::Priority::Value priority = log4cpp::Priority::NOTSET;
00067             try
00068             {
00069                 priority = log4cpp::Priority::getPriorityValue(levelName);
00070                 
00071             }
00072             catch (std::invalid_argument)
00073             {
00074                 // \todo more descriptive
00075                 log(Error) << "Bad level name: " << levelName << endlog();
00076                 return false;
00077             }
00078             
00079             log(Debug) << "Getting category '" << categoryName << "'" << endlog();
00080             log4cpp::Category& category =
00081                 log4cpp::Category::getInstance(categoryName);
00082 
00083             category.setPriority(priority);
00084             log(Info) << "Category '" << categoryName 
00085                       << "' has priority '" << levelName << "'"
00086                       << endlog();
00087         }
00088     }
00089 
00090     // first clear all existing appenders in order to avoid double connects:
00091     for(vector<string>::iterator it = active_appenders.begin(); it != active_appenders.end(); ++it) {
00092         base::PortInterface* port = 0;
00093         TaskContext* appender   = getPeer(*it);
00094         if (appender && (port = appender->ports()->getPort("LogPort")) )
00095             port->disconnect();
00096     }
00097     if ( !active_appenders.empty() ) 
00098         log(Warning) <<"Reconfiguring LoggingService '"<<getName() << "': I've removed all existing Appender connections and will now rebuild them."<<endlog();
00099     active_appenders.clear();
00100 
00101         // set the additivity of each category
00102 
00103     bag = additivity_prop.value();  // an empty bag is ok
00104 
00105     for (it=bag.getProperties().begin(); it != bag.getProperties().end(); ++it)
00106     {
00107         Property<bool>* category = dynamic_cast<Property<bool>* >( *it );
00108         if ( !category )
00109         {
00110             log(Error) << "Expected Property '"
00111                        << (*it)->getName() << "' to be of type boolean." << endlog();
00112         }
00113         else
00114         {
00115             std::string categoryName    = category->getName();
00116             bool                additivity              = category->value();
00117 
00118             // "" == categoryName implies the root category.
00119 
00120             log(Debug) << "Getting category '" << categoryName << "'" << endlog();
00121             log4cpp::Category& category =
00122             log4cpp::Category::getInstance(categoryName);
00123 
00124             category.setAdditivity(additivity);
00125             log(Info) << "Category '" << categoryName
00126                       << "' has additivity '" << std::string(additivity ? "on":"off") << "'"
00127                       << endlog();
00128         }
00129     }
00130 
00131     // create a port for each appender, and associate category/appender
00132 
00133     bag = appenders_prop.value();           // an empty bag is ok
00134 
00135     ok = true;
00136     for (it=bag.getProperties().begin(); it != bag.getProperties().end(); ++it)
00137     {
00138         Property<std::string>* association = dynamic_cast<Property<std::string>* >( *it );
00139         if ( !association )
00140         {
00141             log(Error) << "Expected Property '"
00142                        << (*it)->getName() << "' to be of type string." << endlog();
00143         }
00144         // \todo else if name or level are empty
00145         else 
00146         {
00147             std::string categoryName    = association->getName();
00148             std::string appenderName    = association->value();
00149             
00150             // find category 
00151             log4cpp::Category* p = log4cpp::HierarchyMaintainer::getDefaultMaintainer().getExistingInstance(categoryName);
00152             OCL::logging::Category* category =
00153                 dynamic_cast<OCL::logging::Category*>(p);
00154             if (0 == category)
00155             {
00156                 if (0 != p)
00157                 {
00158                     log(Error) << "Category '" << categoryName << "' is not an OCL category: type is '" << typeid(*p).name() << "'" << endlog();
00159                 }
00160                 else
00161                 {
00162                     log(Error) << "Category '" << categoryName << "' does not exist!" << endlog();
00163                 }
00164                 ok = false;
00165                 break;
00166             }
00167             
00168             // find appender
00169             RTT::TaskContext* appender  = getPeer(appenderName);
00170             if (appender)
00171             {
00172                 // connect category port with appender port
00173                 RTT::base::PortInterface* appenderPort = 0;
00174 
00175                 appenderPort    = appender->ports()->getPort("LogPort");
00176                 if (appenderPort)
00177                 {
00178                     // \todo make connection policy configurable (from xml).
00179                     ConnPolicy cp = ConnPolicy::buffer(100,ConnPolicy::LOCK_FREE,false,false);
00180                     if ( appenderPort->connectTo( &(category->log_port), cp) )
00181                     {
00182                         std::stringstream   str;
00183                         str << "Category '" << categoryName
00184                             << "' has appender '" << appenderName << "'" 
00185                             << " with level "
00186                             << log4cpp::Priority::getPriorityName(category->getPriority());
00187                         log(Info) << str.str() << endlog();
00188 //                        std::cout << str.str() << std::endl;
00189                         active_appenders.push_back(appenderName);
00190                     }
00191                     else
00192                     {
00193                         log(Error) << "Failed to connect port to appender '" << appenderName << "'" << endlog();
00194                         ok = false;
00195                         break;
00196                     }
00197                 }
00198                 else
00199                 {
00200                     log(Error) << "Failed to find log port in appender" << endlog();
00201                     ok = false;
00202                     break;
00203                 }
00204             }
00205             else
00206             {
00207                 log(Error) << "Could not find appender '" << appenderName << "'" << endlog();
00208                 ok = false;
00209                 break;
00210             }
00211         }
00212     }
00213     
00214     return ok;
00215 }
00216 
00217 // NOT realtime
00218 void LoggingService::logCategories()
00219 {
00220     std::vector<log4cpp::Category*>*            categories =
00221         log4cpp::Category::getCurrentCategories();
00222     assert(categories);
00223     std::vector<log4cpp::Category*>::iterator   iter;
00224     log(Info) << "Number categories = " << (int)categories->size() << endlog();
00225     for (iter = categories->begin(); iter != categories->end(); ++iter)
00226     {
00227         log(Info)
00228             << "Category '" << (*iter)->getName() << "', level="
00229             << log4cpp::Priority::getPriorityName((*iter)->getPriority())
00230             << ", typeid='"
00231             << typeid(*iter).name()
00232             << "', type really is '" 
00233             << std::string(0 != dynamic_cast<OCL::logging::Category*>(*iter)
00234                            ? "OCL::Category" : "log4cpp::Category")
00235             << "'" << endlog();
00236     }
00237 }
00238    
00239 // namespaces
00240 }
00241 }
00242 
00243 ORO_CREATE_COMPONENT_TYPE();
00244 ORO_LIST_COMPONENT_TYPE(OCL::logging::LoggingService);


ocl
Author(s): OCL Development Team
autogenerated on Mon Sep 14 2015 14:21:46