OrocosComponentLibrary  2.8.3
Appender.cpp
1 #include "logging/Appender.hpp"
2 #include "ocl/Component.hpp"
3 
4 #include <log4cpp/Appender.hh>
5 #include <log4cpp/BasicLayout.hh>
6 #include <log4cpp/SimpleLayout.hh>
7 #include <log4cpp/PatternLayout.hh>
8 
9 namespace OCL {
10 namespace logging {
11 
12 Appender::Appender(std::string name) :
13  RTT::TaskContext(name, RTT::TaskContext::PreOperational),
14  appender(0),
15  layoutName_prop("LayoutName", "Layout name (e.g. 'simple', 'pattern')"),
16  layoutPattern_prop("LayoutPattern", "Layout conversion pattern (for those layouts that use a pattern)"),
17  countMaxPopped(0)
18 {
19  ports()->addEventPort("LogPort", log_port );
20 
21  properties()->addProperty(layoutName_prop);
22  properties()->addProperty(layoutPattern_prop);
23 }
24 
25 Appender::~Appender()
26 {
27 }
28 
29 bool Appender::configureLayout()
30 {
31  bool rc;
32  const std::string& layoutName = layoutName_prop.rvalue();
33  const std::string& layoutPattern = layoutPattern_prop.rvalue();
34 
35  rc = true; // prove otherwise
36  if (appender &&
37  (!layoutName.empty()))
38  {
39  // \todo layout factory??
40  if (0 == layoutName.compare("basic"))
41  {
42  appender->setLayout(new log4cpp::BasicLayout());
43  }
44  else if (0 == layoutName.compare("simple"))
45  {
46  appender->setLayout(new log4cpp::SimpleLayout());
47  }
48  else if (0 == layoutName.compare("pattern"))
49  {
50  log4cpp::PatternLayout *layout = new log4cpp::PatternLayout();
52  layout->setConversionPattern(layoutPattern);
53  appender->setLayout(layout);
54  // the layout is now owned by the appender, and will be deleted
55  // by it when the appender is destroyed
56  }
57  else
58  {
59  RTT::log(RTT::Error) << "Invalid layout '" << layoutName
60  << "' in configuration for category: "
61  << getName() << RTT::endlog();
62  rc = false;
63  }
64  }
65 
66  return rc;
67 }
68 
69 bool Appender::startHook()
70 {
72 // return log_port.ready();
73 
74  return true;
75 }
76 
77 void Appender::stopHook()
78 {
79  drainBuffer();
80 
81  // introduce event to log diagnostics
82  if (0 != appender)
83  {
84  /* place a "#" at the front of the message, for appenders that are
85  reporting data for post-processing. These particular appenders
86  don't prepend the time data (it's one at time of sampling).
87  This way gnuplot, etc., ignore this diagnostic data.
88  */
89  std::stringstream ss;
90  ss << "# countMaxPopped=" << countMaxPopped;
91  log4cpp::LoggingEvent event("OCL.logging.Appender",
92  ss.str(),
93  "",
94  log4cpp::Priority::DEBUG);
95  appender->doAppend(event);
96  }
97 }
98 
99 void Appender::drainBuffer()
100 {
101  processEvents(0);
102 }
103 
104 void Appender::processEvents(int n)
105 {
106  if (!log_port.connected()) return; // no category connected to us
107  if (!appender) return; // no appender!?
108 
109  // check pre-conditions
110  if (0 > n) n = 1;
111 
112  /* Consume waiting events until
113  a) the buffer is empty
114  b) we consume enough events
115  */
117  bool again = false;
118  int count = 0;
119 
120  do
121  {
122  if (log_port.read( event ) == RTT::NewData)
123  {
124  ++count;
125 
126  appender->doAppend( event.toLog4cpp() );
127 
128  // Consume infinite events OR up to n events
129  again = (0 == n) || (count < n);
130  if ((0 != n) && (count == n)) ++countMaxPopped;
131  }
132  else
133  {
134  break; // nothing to do
135  }
136  }
137  while (again);
138 }
139 
140 // namespaces
141 }
142 }
143 
144 ORO_LIST_COMPONENT_TYPE(OCL::logging::Appender);
A mirror of log4cpp::LoggingEvent, except using real-time capable strings.
This file contains the macros and definitions to create dynamically loadable components.
The Orocos Component Library.
Definition: Component.hpp:43
Definition: Category.hpp:10
log4cpp::LoggingEvent toLog4cpp()
Convert to log4cpp class.