log_parser.cpp
Go to the documentation of this file.
1 // Splits the log stream into individual messages
2 // Author: Max Schwarz <max.schwarz@ais.uni-bonn.de>
3 
4 #include "log_parser.h"
5 
6 #include <algorithm>
7 #include <cstring>
8 #include <vector>
9 
10 namespace rosmon
11 {
12 namespace monitor
13 {
14 
16 {
17 public:
18  enum class State
19  {
23 
25 
27 
28  EndEscape1,
29  EndEscape2,
30  EndEscape3,
32  };
33 
35  {
36  switch(code)
37  {
38  case 0: return LogEvent::Type::Info;
39  case 31: return LogEvent::Type::Error;
40  case 32: return LogEvent::Type::Debug;
41  case 33: return LogEvent::Type::Warning;
42  }
43 
44  return LogEvent::Type::Info;
45  }
46 
47  void process(char c, const std::chrono::steady_clock::time_point& time)
48  {
49  m_buffer.push_back(c);
50 
51  switch(m_state)
52  {
54  if(c == '\e')
56  else
58 
59  break;
60 
62  if(c == '[')
63  {
65  m_colorCode = 0;
66  }
67  else
69 
70  break;
71 
73  if(std::isdigit(c))
74  m_colorCode = m_colorCode * 10 + (c - '0');
75  else if(c == 'm')
76  {
77  m_msgBegin = m_buffer.size();
78  m_msgStartTime = time;
80  }
81  else
83 
84  break;
85 
87  if(c == '\e')
88  {
89  m_msgEnd = m_buffer.size() - 1;
91  }
92 
93  break;
94 
95  case State::EndEscape1:
96  if(c == '[')
98  else
100 
101  break;
102 
103  case State::EndEscape2:
104  if(c == '0')
106  else
108 
109  break;
110 
111  case State::EndEscape3:
112  if(c == 'm')
114  else
116 
117  break;
118 
119  case State::EndEscape4:
120  if(c == '\n')
121  {
122  std::string msg{m_buffer.data() + m_msgBegin, m_msgEnd - m_msgBegin};
123 
124  if(m_cb)
125  m_cb(Event{std::move(msg), typeFromColorCode(m_colorCode)});
126 
128  m_buffer.clear();
129  }
130  else
132 
133  break;
134 
136  if(c == '\n')
137  {
138  std::string msg{m_buffer.data(), m_buffer.size()-1};
139 
140  if(m_cb)
141  m_cb(Event{std::move(msg), LogEvent::Type::Raw});
142 
144  m_buffer.clear();
145  }
146 
147  break;
148  }
149  }
150 
151  void checkPending(const std::chrono::steady_clock::time_point& time = std::chrono::steady_clock::now())
152  {
154  return;
155 
156  if(time - m_msgStartTime > std::chrono::milliseconds(250))
157  flush();
158  }
159 
160  void flush()
161  {
162  if(m_buffer.empty())
163  return;
164 
165  // Emit completed lines
166  while(true)
167  {
168  auto it = std::find(m_buffer.begin(), m_buffer.end(), '\n');
169  if(it == m_buffer.end())
170  break;
171 
172  std::size_t size = it - m_buffer.begin();
173  std::string msg{m_buffer.data(), size};
174 
175  if(m_cb)
176  m_cb(Event{std::move(msg), LogEvent::Type::Raw});
177 
178  std::memmove(m_buffer.data(), m_buffer.data() + size + 1, m_buffer.size() - size - 1);
179  m_buffer.resize(m_buffer.size() - size - 1);
180  }
181 
183  }
184 
186 
187  int m_colorCode = 0;
188 
189  std::vector<char> m_buffer;
190 
191  std::size_t m_msgBegin = 0;
192  std::size_t m_msgEnd = 0;
193  std::chrono::steady_clock::time_point m_msgStartTime;
194 
195  std::function<void(LogParser::Event&&)> m_cb;
196 };
197 
199  : m_d{new Private}
200 {
201 }
202 
204 {
205 }
206 
207 void LogParser::process(const char* input, std::size_t size, const std::chrono::steady_clock::time_point& time)
208 {
209  for(std::size_t i = 0; i < size; ++i)
210  m_d->process(input[i], time);
211 }
212 
213 void LogParser::setCallback(const std::function<void(Event&&)>& cb)
214 {
215  m_d->m_cb = cb;
216 }
217 
218 void LogParser::checkPending(const std::chrono::steady_clock::time_point& time)
219 {
220  m_d->checkPending(time);
221 }
222 
224 {
225  m_d->flush();
226 }
227 
228 }
229 }
rosmon::monitor::LogParser::Private::State::TypedMsgContent
@ TypedMsgContent
rosmon
Definition: diagnostics_publisher.cpp:34
rosmon::monitor::LogParser::Private::State::EndEscape4
@ EndEscape4
rosmon::monitor::LogParser::setCallback
void setCallback(const std::function< void(Event &&)> &cb)
Definition: log_parser.cpp:213
rosmon::monitor::LogParser::Private::checkPending
void checkPending(const std::chrono::steady_clock::time_point &time=std::chrono::steady_clock::now())
Definition: log_parser.cpp:151
rosmon::monitor::LogParser::Private::State::EndEscape2
@ EndEscape2
rosmon::monitor::LogParser::LogParser
LogParser()
Definition: log_parser.cpp:198
rosmon::monitor::LogParser::Private::m_cb
std::function< void(LogParser::Event &&)> m_cb
Definition: log_parser.cpp:195
rosmon::monitor::LogParser::flush
void flush()
Definition: log_parser.cpp:223
rosmon::LogEvent::Type
Type
Definition: log_event.h:16
rosmon::monitor::LogParser::Private::State::ColorEscape1
@ ColorEscape1
rosmon::monitor::LogParser::Private::State::ColorEscape3
@ ColorEscape3
rosmon::LogEvent::Type::Info
@ Info
rosmon::monitor::LogParser::Private::m_buffer
std::vector< char > m_buffer
Definition: log_parser.cpp:189
rosmon::monitor::LogParser::~LogParser
~LogParser()
Definition: log_parser.cpp:203
rosmon::monitor::LogParser::Private::State
State
Definition: log_parser.cpp:18
rosmon::monitor::LogParser::m_d
std::unique_ptr< Private > m_d
Definition: log_parser.h:42
rosmon::monitor::LogParser::Private::State::ColorEscape2
@ ColorEscape2
rosmon::LogEvent::Type::Debug
@ Debug
rosmon::monitor::LogParser::Private::m_colorCode
int m_colorCode
Definition: log_parser.cpp:187
log_parser.h
rosmon::monitor::LogParser::checkPending
void checkPending(const std::chrono::steady_clock::time_point &time=std::chrono::steady_clock::now())
Definition: log_parser.cpp:218
rosmon::monitor::LogParser::Private
Definition: log_parser.cpp:15
rosmon::monitor::LogParser::Private::m_state
State m_state
Definition: log_parser.cpp:185
rosmon::LogEvent::Type::Warning
@ Warning
rosmon::monitor::LogParser::Private::m_msgStartTime
std::chrono::steady_clock::time_point m_msgStartTime
Definition: log_parser.cpp:193
rosmon::monitor::LogParser::Private::m_msgEnd
std::size_t m_msgEnd
Definition: log_parser.cpp:192
rosmon::monitor::LogParser::Private::flush
void flush()
Definition: log_parser.cpp:160
rosmon::LogEvent::Type::Error
@ Error
rosmon::monitor::LogParser::Private::process
void process(char c, const std::chrono::steady_clock::time_point &time)
Definition: log_parser.cpp:47
rosmon::monitor::LogParser::Private::State::EndEscape3
@ EndEscape3
rosmon::monitor::LogParser::process
void process(const char *input, std::size_t size, const std::chrono::steady_clock::time_point &time=std::chrono::steady_clock::now())
Definition: log_parser.cpp:207
rosmon::monitor::LogParser::Private::typeFromColorCode
static LogEvent::Type typeFromColorCode(int code)
Definition: log_parser.cpp:34
rosmon::LogEvent::Type::Raw
@ Raw
rosmon::monitor::LogParser::Private::State::RawMsgContent
@ RawMsgContent
rosmon::monitor::LogParser::Event
Definition: log_parser.h:24
rosmon::monitor::LogParser::Private::State::EndEscape1
@ EndEscape1
rosmon::monitor::LogParser::Private::m_msgBegin
std::size_t m_msgBegin
Definition: log_parser.cpp:191


rosmon_core
Author(s): Max Schwarz
autogenerated on Wed Feb 21 2024 04:01:14