OrocosComponentLibrary
2.7.0
|
00001 #include "logging/Appender.hpp" 00002 #include "ocl/Component.hpp" 00003 00004 #include <log4cpp/Appender.hh> 00005 #include <log4cpp/BasicLayout.hh> 00006 #include <log4cpp/SimpleLayout.hh> 00007 #include <log4cpp/PatternLayout.hh> 00008 00009 namespace OCL { 00010 namespace logging { 00011 00012 Appender::Appender(std::string name) : 00013 RTT::TaskContext(name, RTT::TaskContext::PreOperational), 00014 appender(0), 00015 layoutName_prop("LayoutName", "Layout name (e.g. 'simple', 'pattern')"), 00016 layoutPattern_prop("LayoutPattern", "Layout conversion pattern (for those layouts that use a pattern)"), 00017 countMaxPopped(0) 00018 { 00019 ports()->addEventPort("LogPort", log_port ); 00020 00021 properties()->addProperty(layoutName_prop); 00022 properties()->addProperty(layoutPattern_prop); 00023 } 00024 00025 Appender::~Appender() 00026 { 00027 } 00028 00029 bool Appender::configureLayout() 00030 { 00031 bool rc; 00032 const std::string& layoutName = layoutName_prop.rvalue(); 00033 const std::string& layoutPattern = layoutPattern_prop.rvalue(); 00034 00035 rc = true; // prove otherwise 00036 if (appender && 00037 (!layoutName.empty())) 00038 { 00039 // \todo layout factory?? 00040 if (0 == layoutName.compare("basic")) 00041 { 00042 appender->setLayout(new log4cpp::BasicLayout()); 00043 } 00044 else if (0 == layoutName.compare("simple")) 00045 { 00046 appender->setLayout(new log4cpp::SimpleLayout()); 00047 } 00048 else if (0 == layoutName.compare("pattern")) 00049 { 00050 log4cpp::PatternLayout *layout = new log4cpp::PatternLayout(); 00052 layout->setConversionPattern(layoutPattern); 00053 appender->setLayout(layout); 00054 // the layout is now owned by the appender, and will be deleted 00055 // by it when the appender is destroyed 00056 } 00057 else 00058 { 00059 RTT::log(RTT::Error) << "Invalid layout '" << layoutName 00060 << "' in configuration for category: " 00061 << getName() << RTT::endlog(); 00062 rc = false; 00063 } 00064 } 00065 00066 return rc; 00067 } 00068 00069 bool Appender::startHook() 00070 { 00072 // return log_port.ready(); 00073 00074 return true; 00075 } 00076 00077 void Appender::stopHook() 00078 { 00079 drainBuffer(); 00080 00081 // introduce event to log diagnostics 00082 if (0 != appender) 00083 { 00084 /* place a "#" at the front of the message, for appenders that are 00085 reporting data for post-processing. These particular appenders 00086 don't prepend the time data (it's one at time of sampling). 00087 This way gnuplot, etc., ignore this diagnostic data. 00088 */ 00089 std::stringstream ss; 00090 ss << "# countMaxPopped=" << countMaxPopped; 00091 log4cpp::LoggingEvent event("OCL.logging.Appender", 00092 ss.str(), 00093 "", 00094 log4cpp::Priority::DEBUG); 00095 appender->doAppend(event); 00096 } 00097 } 00098 00099 void Appender::drainBuffer() 00100 { 00101 processEvents(0); 00102 } 00103 00104 void Appender::processEvents(int n) 00105 { 00106 if (!log_port.connected()) return; // no category connected to us 00107 if (!appender) return; // no appender!? 00108 00109 // check pre-conditions 00110 if (0 > n) n = 1; 00111 00112 /* Consume waiting events until 00113 a) the buffer is empty 00114 b) we consume enough events 00115 */ 00116 OCL::logging::LoggingEvent event; 00117 bool again = false; 00118 int count = 0; 00119 00120 do 00121 { 00122 if (log_port.read( event ) == RTT::NewData) 00123 { 00124 ++count; 00125 00126 appender->doAppend( event.toLog4cpp() ); 00127 00128 // Consume infinite events OR up to n events 00129 again = (0 == n) || (count < n); 00130 if ((0 != n) && (count == n)) ++countMaxPopped; 00131 } 00132 else 00133 { 00134 break; // nothing to do 00135 } 00136 } 00137 while (again); 00138 } 00139 00140 // namespaces 00141 } 00142 } 00143 00144 ORO_LIST_COMPONENT_TYPE(OCL::logging::Appender);