$search
00001 #include "logging/Log4cxxAppender.hpp" 00002 #include "log4cxx/spi/loggingevent.h" 00003 #include "rtt/Component.hpp" 00004 #include <rtt/Logger.hpp> 00005 00006 using namespace RTT; 00007 00008 namespace OCL { 00009 namespace logging { 00010 using namespace log4cxx; 00011 00012 log4cxx::LevelPtr tolog4cxxLevel( log4cpp::Priority::Value priority) { 00013 switch (priority) { 00014 //case log4cpp::Priority::EMERG : EMERG and FATAL are both zero 00015 //return Level::getFatal(); 00016 case log4cpp::Priority::FATAL : 00017 return Level::getFatal(); 00018 case log4cpp::Priority::ALERT : 00019 return Level::getError(); 00020 case log4cpp::Priority::CRIT : 00021 return Level::getError(); 00022 case log4cpp::Priority::ERROR : 00023 return Level::getError(); 00024 case log4cpp::Priority::WARN : 00025 return Level::getWarn(); 00026 case log4cpp::Priority::NOTICE : 00027 return Level::getInfo(); 00028 case log4cpp::Priority::INFO : 00029 return Level::getInfo(); 00030 case log4cpp::Priority::DEBUG : 00031 return Level::getDebug(); 00032 case log4cpp::Priority::NOTSET : 00033 return Level::getDebug(); 00034 } 00035 return Level::getDebug(); 00036 } 00037 00038 spi::LoggingEventPtr tolog4cxx(logging::LoggingEvent const& e, log4cxx::helpers::Pool & pool) 00039 { 00040 return spi::LoggingEventPtr(new spi::LoggingEvent(makeString( e.categoryName ), tolog4cxxLevel(e.priority), makeString( e.message ), log4cxx::spi::LocationInfo("filename", "functionname", 0))); 00041 } 00042 00043 Log4cxxAppender::Log4cxxAppender(std::string name) : 00044 RTT::TaskContext(name), 00045 socketAppender(0), 00046 hostname_prop("localhost"), port_prop(4560), 00047 maxEventsPerCycle_prop(0), 00048 maxEventsPerCycle(1) 00049 { 00050 00051 ports()->addEventPort("LogPort", log_port ); 00052 properties()->addProperty("Hostname",hostname_prop).doc("Host name where ChainSaw or other logging server runs."); 00053 properties()->addProperty("MaxEventsPerCycle",maxEventsPerCycle_prop).doc("Maximum number of log events to pop per cycle"); 00054 properties()->addProperty("Port", port_prop).doc("Logging server port to use on Hostname. ChainSaw uses port 4560."); 00055 } 00056 00057 Log4cxxAppender::~Log4cxxAppender() 00058 { 00059 } 00060 00061 bool Log4cxxAppender::configureHook() 00062 { 00063 // verify valid limits 00064 int m = maxEventsPerCycle_prop; 00065 if ((0 > m)) 00066 { 00067 log(Error) << "Invalid maxEventsPerCycle value of " 00068 << m << ". Value must be >= 0." 00069 << endlog(); 00070 return false; 00071 } 00072 maxEventsPerCycle = m; 00073 00074 // \todo error checking 00075 if ( hostname_prop == "localhost") 00076 address = helpers::InetAddress::getLocalHost(); 00077 else 00078 address = helpers::InetAddress::getByName( hostname_prop ); 00079 00080 if ( socketAppender ) { 00081 socketAppender->close(); 00082 delete socketAppender; 00083 } 00084 00085 net::SocketAppender::DEFAULT_RECONNECTION_DELAY = 3000; // 3s 00086 00087 socketAppender = new 00088 log4cxx::net::SocketAppender( address, port_prop ); 00089 00090 socketAppender->activateOptions(p); 00091 00092 return true; 00093 } 00094 00095 void Log4cxxAppender::updateHook() 00096 { 00097 if (!log_port.connected()) return; // no category connected to us 00098 00099 /* Consume waiting events until 00100 a) the buffer is empty 00101 b) we consume too many events on one cycle 00102 */ 00103 OCL::logging::LoggingEvent event; 00104 assert(socketAppender); 00105 assert(0 <= maxEventsPerCycle); 00106 if (0 == maxEventsPerCycle) 00107 { 00108 // consume infinite events 00109 for (;;) 00110 { 00111 if (log_port.read( event ) == NewData) 00112 { 00113 spi::LoggingEventPtr e2 = tolog4cxx( event, p ); 00114 socketAppender->doAppend(e2, p); 00115 } 00116 else 00117 { 00118 break; // nothing to do 00119 } 00120 } 00121 } 00122 else 00123 { 00124 00125 // consume up to maxEventsPerCycle events 00126 int n = maxEventsPerCycle; 00127 do 00128 { 00129 if (log_port.read( event ) == NewData) 00130 { 00131 spi::LoggingEventPtr e2 = tolog4cxx( event, p ); 00132 socketAppender->doAppend(e2, p); 00133 } 00134 else 00135 { 00136 break; // nothing to do 00137 } 00138 --n; 00139 } 00140 while (0 < n); 00141 } 00142 } 00143 00144 void Log4cxxAppender::cleanupHook() 00145 { 00146 /* normally in log4cpp the category owns the appenders and deletes them 00147 itself, however we don't associate appenders and categories in the 00148 same manner. Hence, you have to manually manage appenders. 00149 */ 00150 socketAppender->close(); 00151 delete socketAppender; 00152 socketAppender = 0; 00153 } 00154 00155 // namespaces 00156 } 00157 } 00158 00159 ORO_CREATE_COMPONENT(OCL::logging::Log4cxxAppender);