OrocosComponentLibrary
2.7.0
|
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);