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


ocl
Author(s): OCL Development Team
autogenerated on Thu Jan 2 2014 11:38:08