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 
131  break;
132 
134  if(c == '\n')
135  {
136  std::string msg{m_buffer.data(), m_buffer.size()-1};
137 
138  if(m_cb)
139  m_cb(Event{std::move(msg), LogEvent::Type::Raw});
140 
142  m_buffer.clear();
143  }
144 
145  break;
146  }
147  }
148 
149  void checkPending(const std::chrono::steady_clock::time_point& time = std::chrono::steady_clock::now())
150  {
152  return;
153 
154  if(time - m_msgStartTime > std::chrono::milliseconds(250))
155  flush();
156  }
157 
158  void flush()
159  {
160  if(m_buffer.empty())
161  return;
162 
163  // Emit completed lines
164  while(true)
165  {
166  auto it = std::find(m_buffer.begin(), m_buffer.end(), '\n');
167  if(it == m_buffer.end())
168  break;
169 
170  std::size_t size = it - m_buffer.begin();
171  std::string msg{m_buffer.data(), size};
172 
173  if(m_cb)
174  m_cb(Event{std::move(msg), LogEvent::Type::Raw});
175 
176  std::memmove(m_buffer.data(), m_buffer.data() + size + 1, m_buffer.size() - size - 1);
177  m_buffer.resize(m_buffer.size() - size - 1);
178  }
179 
181  }
182 
184 
185  int m_colorCode = 0;
186 
187  std::vector<char> m_buffer;
188 
189  std::size_t m_msgBegin = 0;
190  std::size_t m_msgEnd = 0;
191  std::chrono::steady_clock::time_point m_msgStartTime;
192 
193  std::function<void(LogParser::Event&&)> m_cb;
194 };
195 
197  : m_d{new Private}
198 {
199 }
200 
202 {
203 }
204 
205 void LogParser::process(const char* input, std::size_t size, const std::chrono::steady_clock::time_point& time)
206 {
207  for(std::size_t i = 0; i < size; ++i)
208  m_d->process(input[i], time);
209 }
210 
211 void LogParser::setCallback(const std::function<void(Event&&)>& cb)
212 {
213  m_d->m_cb = cb;
214 }
215 
216 void LogParser::checkPending(const std::chrono::steady_clock::time_point& time)
217 {
218  m_d->checkPending(time);
219 }
220 
222 {
223  m_d->flush();
224 }
225 
226 }
227 }
static LogEvent::Type typeFromColorCode(int code)
Definition: log_parser.cpp:34
void setCallback(const std::function< void(Event &&)> &cb)
Definition: log_parser.cpp:211
void checkPending(const std::chrono::steady_clock::time_point &time=std::chrono::steady_clock::now())
Definition: log_parser.cpp:216
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:205
void process(char c, const std::chrono::steady_clock::time_point &time)
Definition: log_parser.cpp:47
std::function< void(LogParser::Event &&)> m_cb
Definition: log_parser.cpp:193
void checkPending(const std::chrono::steady_clock::time_point &time=std::chrono::steady_clock::now())
Definition: log_parser.cpp:149
std::unique_ptr< Private > m_d
Definition: log_parser.h:42
std::chrono::steady_clock::time_point m_msgStartTime
Definition: log_parser.cpp:191


rosmon_core
Author(s): Max Schwarz
autogenerated on Fri Jun 16 2023 02:15:06