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
00038
00039 PropertyBag bag = levels_prop.value();
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
00057
00058
00059
00060
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
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
00088
00089 bag = appenders_prop.value();
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
00101 else
00102 {
00103 std::string categoryName = association->getName();
00104 std::string appenderName = association->value();
00105
00106
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
00125 RTT::TaskContext* appender = getPeer(appenderName);
00126 if (appender)
00127 {
00128
00129 RTT::base::PortInterface* appenderPort = 0;
00130
00131 appenderPort = appender->ports()->getPort("LogPort");
00132 if (appenderPort)
00133 {
00134
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
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
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
00195 }
00196 }
00197
00198 ORO_CREATE_COMPONENT_TYPE();
00199 ORO_LIST_COMPONENT_TYPE(OCL::logging::LoggingService);