OrocosComponentLibrary  2.9.0
Log4cxxAppender.cpp
1 #include "logging/Log4cxxAppender.hpp"
2 #include "log4cxx/spi/loggingevent.h"
3 #include "rtt/Component.hpp"
4 #include <rtt/Logger.hpp>
5 
6 using namespace RTT;
7 
8 namespace OCL {
9 namespace logging {
10  using namespace log4cxx;
11 
12  log4cxx::LevelPtr tolog4cxxLevel( log4cpp::Priority::Value priority) {
13  switch (priority) {
14  //case log4cpp::Priority::EMERG : EMERG and FATAL are both zero
15  //return Level::getFatal();
16  case log4cpp::Priority::FATAL :
17  return Level::getFatal();
18  case log4cpp::Priority::ALERT :
19  return Level::getError();
20  case log4cpp::Priority::CRIT :
21  return Level::getError();
22  case log4cpp::Priority::ERROR :
23  return Level::getError();
24  case log4cpp::Priority::WARN :
25  return Level::getWarn();
26  case log4cpp::Priority::NOTICE :
27  return Level::getInfo();
28  case log4cpp::Priority::INFO :
29  return Level::getInfo();
30  case log4cpp::Priority::DEBUG :
31  return Level::getDebug();
32  case log4cpp::Priority::NOTSET :
33  return Level::getDebug();
34  }
35  return Level::getDebug();
36  }
37 
38  spi::LoggingEventPtr tolog4cxx(logging::LoggingEvent const& e, log4cxx::helpers::Pool & pool)
39  {
40  return spi::LoggingEventPtr(new spi::LoggingEvent(makeString( e.categoryName ), tolog4cxxLevel(e.priority), makeString( e.message ), log4cxx::spi::LocationInfo("filename", "functionname", 0)));
41  }
42 
43 Log4cxxAppender::Log4cxxAppender(std::string name) :
44  RTT::TaskContext(name,RTT::TaskContext::PreOperational),
45  socketAppender(0),
46  hostname_prop("localhost"), port_prop(4560),
47  maxEventsPerCycle_prop(0),
48  maxEventsPerCycle(0)
49 {
50 
51  ports()->addEventPort("LogPort", log_port );
52  properties()->addProperty("Hostname",hostname_prop).doc("Host name where ChainSaw or other logging server runs.");
53  properties()->addProperty("MaxEventsPerCycle",maxEventsPerCycle_prop).doc("Maximum number of log events to pop per cycle");
54  properties()->addProperty("Port", port_prop).doc("Logging server port to use on Hostname. ChainSaw uses port 4560.");
55 }
56 
57 Log4cxxAppender::~Log4cxxAppender()
58 {
59 }
60 
61 bool Log4cxxAppender::configureHook()
62 {
63  // verify valid limits
64  int m = maxEventsPerCycle_prop;
65  if ((0 > m))
66  {
67  log(Error) << "Invalid maxEventsPerCycle value of "
68  << m << ". Value must be >= 0."
69  << endlog();
70  return false;
71  }
72  maxEventsPerCycle = m;
73 
74  // \todo error checking
75  if ( hostname_prop == "localhost")
76  address = helpers::InetAddress::getLocalHost();
77  else
78  address = helpers::InetAddress::getByName( hostname_prop );
79 
80  if ( socketAppender ) {
81  socketAppender->close();
82  delete socketAppender;
83  }
84 
85  net::SocketAppender::DEFAULT_RECONNECTION_DELAY = 3000; // 3s
86 
87  socketAppender = new
88  log4cxx::net::SocketAppender( address, port_prop );
89 
90  socketAppender->activateOptions(p);
91 
92  return true;
93 }
94 
95 void Log4cxxAppender::updateHook()
96 {
97  if (!log_port.connected()) return; // no category connected to us
98 
99  /* Consume waiting events until
100  a) the buffer is empty
101  b) we consume too many events on one cycle
102  */
104  assert(socketAppender);
105  assert(0 <= maxEventsPerCycle);
106  if (0 == maxEventsPerCycle)
107  {
108  // consume infinite events
109  for (;;)
110  {
111  if (log_port.read( event ) == NewData)
112  {
113  spi::LoggingEventPtr e2 = tolog4cxx( event, p );
114  socketAppender->doAppend(e2, p);
115  }
116  else
117  {
118  break; // nothing to do
119  }
120  }
121  }
122  else
123  {
124 
125  // consume up to maxEventsPerCycle events
126  int n = maxEventsPerCycle;
127  do
128  {
129  if (log_port.read( event ) == NewData)
130  {
131  spi::LoggingEventPtr e2 = tolog4cxx( event, p );
132  socketAppender->doAppend(e2, p);
133  }
134  else
135  {
136  break; // nothing to do
137  }
138  --n;
139  }
140  while (0 < n);
141  }
142 }
143 
144 void Log4cxxAppender::cleanupHook()
145 {
146  /* normally in log4cpp the category owns the appenders and deletes them
147  itself, however we don't associate appenders and categories in the
148  same manner. Hence, you have to manually manage appenders.
149  */
150  socketAppender->close();
151  delete socketAppender;
152  socketAppender = 0;
153 }
154 
155 // namespaces
156 }
157 }
158 
159 ORO_CREATE_COMPONENT(OCL::logging::Log4cxxAppender);
A mirror of log4cpp::LoggingEvent, except using real-time capable strings.
Interoperability component which translates our log4cpp events to log4cxx events and sends them to a ...
The Orocos Component Library.
Definition: Component.hpp:43
Definition: Category.hpp:10