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