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