YARP
Yet Another Robot Platform
YarpLogger.cpp
Go to the documentation of this file.
1 /*
2  * SPDX-FileCopyrightText: 2006-2021 Istituto Italiano di Tecnologia (IIT)
3  * SPDX-License-Identifier: BSD-3-Clause
4  */
5 
6 #include <iostream>
7 #include <cstring>
8 #include <string>
9 #include <sstream>
10 #include <cstdio>
11 #include <fstream>
12 #include <iterator>
13 #include <yarp/os/RpcClient.h>
14 #include <yarp/os/SystemClock.h>
15 #include <yarp/logger/YarpLogger.h>
16 
17 using namespace yarp::os;
18 using namespace yarp::yarpLogger;
19 /*
20 const std::string RED ="\033[01;31m";
21 const std::string GREEN ="\033[01;32m";
22 const std::string YELLOW ="\033[01;33m";
23 const std::string BLUE ="\033[01;34m";
24 const std::string CLEAR ="\033[00m";
25 
26 const std::string RED_ERROR = RED+"ERROR"+CLEAR;
27 const std::string YELLOW_WARNING = YELLOW+"WARNING"+CLEAR;
28 */
29 void LogEntry::clear_logEntries()
30 {
31  entry_list.clear();
32  logInfo.clear();
33  last_read_message=-1;
34 }
35 
36 void LogEntry::setLogEntryMaxSize(int size)
37 {
38  entry_list_max_size = size;
39  entry_list.reserve(entry_list_max_size);
40  clear_logEntries();
41 }
42 
43 void LogEntry::setLogEntryMaxSizeEnabled (bool enable)
44 {
45  entry_list_max_size_enabled=enable;
46 }
47 
48 bool LogEntry::append_logEntry(MessageEntry entry)
49 {
50  if (logInfo.logsize >= entry_list_max_size && entry_list_max_size_enabled)
51  {
52  //printf("WARNING: exceeded entry_list_max_size=%d\n",entry_list_max_size);
53  return false;
54  }
55  entry_list.push_back(entry);
56  logInfo.logsize++;
57  return true;
58 }
59 
60 void LogEntryInfo::clear()
61 {
62  logsize=0;
63  number_of_traces=0;
64  number_of_debugs=0;
65  number_of_infos=0;
66  number_of_warnings=0;
67  number_of_errors=0;
68  number_of_fatals=0;
69  highest_error=LOGLEVEL_UNDEFINED;
70  last_update=-1;
71 }
72 
73 LogLevel LogEntryInfo::getLastError()
74 {
75  return highest_error;
76 }
77 
78 void LogEntryInfo::clearLastError()
79 {
80  highest_error=LOGLEVEL_UNDEFINED;
81 }
82 
83 void LogEntryInfo::setNewError(LogLevel level)
84 {
85  if (level == LOGLEVEL_TRACE) {
86  number_of_traces++;
87  } else if (level == LOGLEVEL_DEBUG) {
88  number_of_debugs++;
89  } else if (level == LOGLEVEL_INFO) {
90  number_of_infos++;
91  } else if (level == LOGLEVEL_WARNING) {
92  number_of_warnings++;
93  } else if (level == LOGLEVEL_ERROR) {
94  number_of_errors++;
95  } else if (level == LOGLEVEL_FATAL) {
96  number_of_fatals++;
97  }
98  if (level > highest_error) {
99  highest_error = level;
100  }
101 }
102 
103 void LoggerEngine::discover (std::list<std::string>& ports)
104 {
105  RpcClient p;
106  std::string logger_portname = log_updater->getPortName();
107  p.open(logger_portname+"/discover");
108  std::string yarpservername = yarp::os::Network::getNameServerName();
109  yarp::os::Network::connect(logger_portname+"/discover",yarpservername);
110  Bottle cmd,response;
111  cmd.addString("bot");
112  cmd.addString("list");
113  p.write(cmd,response);
114  printf ("%s\n\n", response.toString().c_str());
115  int size = response.size();
116  for (int i=1; i<size; i++) //beware: skip i=0 is intentional!
117  {
118  Bottle* n1 = response.get(i).asList();
119  if (n1 && n1->get(0).toString()=="port")
120  {
121  Bottle* n2 = n1->get(1).asList();
122  if (n2 && n2->get(0).toString()=="name")
123  {
124  char* log_off = nullptr;
125  char* yarprun_log_off = nullptr;
126  log_off = std::strstr((char*)(n2->get(1).toString().c_str()), "/log/");
127  if (log_off)
128  {
129  std::string logport = n2->get(1).toString();
130  printf ("%s\n", logport.c_str());
131  ports.push_back(logport);
132  }
133  yarprun_log_off = std::strstr((char*)(n2->get(1).toString().c_str()), "/yarprunlog/");
134  if (yarprun_log_off)
135  {
136  std::string logport = n2->get(1).toString();
137  printf ("%s\n", logport.c_str());
138  ports.push_back(logport);
139  }
140  }
141  }
142  }
143 
144  std::list<std::string>::iterator ports_it;
145  for (ports_it=ports.begin(); ports_it!=ports.end(); ports_it++)
146  {
147  LogEntry entry;
148  entry.logInfo.port_complete = (*ports_it);
150  if (contact.isValid())
151  {
152  entry.logInfo.ip_address = contact.getHost();
153  }
154  else
155  {
156  printf("ERROR: invalid contact: %s\n", entry.logInfo.port_complete.c_str());
157  }
158  std::istringstream iss(*ports_it);
159  std::string token;
160  getline(iss, token, '/');
161  getline(iss, token, '/');
162  getline(iss, token, '/'); entry.logInfo.port_prefix = "/"+ token;
163  getline(iss, token, '/'); entry.logInfo.process_name = token;
164  getline(iss, token, '/'); entry.logInfo.process_pid = token;
165 
166  std::list<LogEntry>::iterator it;
167  this->log_updater->mutex.lock();
168  bool found = false;
169  for (it = this->log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
170  {
171  if (it->logInfo.port_complete==entry.logInfo.port_complete)
172  {
173  found=true; break;
174  }
175  }
176  if (found==false)
177  {
178  log_updater->log_list.push_back(entry);
179  }
180  this->log_updater->mutex.unlock();
181  }
182 }
183 
184 void LoggerEngine::connect (const std::list<std::string>& ports)
185 {
187  style.timeout=1.0;
188  style.quiet=true;
189 
190  std::list<std::string>::const_iterator it;
191  for (it = ports.begin(); it != ports.end(); it++)
192  {
193  if (yarp::os::Network::exists(*it,style) == true)
194  {
195  yarp::os::Network::connect(*it,this->log_updater->getPortName());
196  }
197  else
198  {
199  //fprintf(stderr,"unable to connect to port %s\n",it->c_str());
200  }
201  }
202 }
203 
204 std::string LoggerEngine::logger_thread::getPortName()
205 {
206  return logger_portName;
207 }
208 
209 LoggerEngine::logger_thread::logger_thread (std::string _portname, double _period, int _log_list_max_size) : PeriodicThread(_period, ShouldUseSystemClock::Yes)
210 {
211  logger_portName = _portname;
212  log_list_max_size = _log_list_max_size;
213  log_list_max_size_enabled = true;
214  listen_to_LOGLEVEL_UNDEFINED = true;
215  listen_to_LOGLEVEL_TRACE = true;
216  listen_to_LOGLEVEL_DEBUG = true;
217  listen_to_LOGLEVEL_INFO = true;
218  listen_to_LOGLEVEL_WARNING = true;
219  listen_to_LOGLEVEL_ERROR = true;
220  listen_to_LOGLEVEL_FATAL = true;
221  listen_to_YARP_MESSAGES = true;
222  listen_to_YARPRUN_MESSAGES = true;
223  unknown_format_received = 0;
224 }
225 
226 void LoggerEngine::logger_thread::run()
227 {
228  //if (is_discovering()==true)
229  {
230  //yarp::os::Network::
231  }
232 
233  //yarp::os::SystemClock::delaySystem(0.001);
234  //if (logger_port.getInputCount()>0)
235  {
236  int bufferport_size = logger_port.getPendingReads();
237 
238  while (bufferport_size>0)
239  {
240  std::time_t machine_current_time = std::time(nullptr);
241  char machine_current_time_c [50];
242  //strftime(machine_current_time_s, 20, "%Y-%m-%d %H:%M:%S", localtime(&machine_current_time));
243  static double d_time_i = yarp::os::SystemClock::nowSystem();
244  double d_time = yarp::os::SystemClock::nowSystem() - d_time_i;
245  sprintf(machine_current_time_c,"%f",d_time);
246  std::string machine_current_time_s = std::string(machine_current_time_c);
247 
248  Bottle *b = logger_port.read(); //this is blocking
249  bufferport_size = logger_port.getPendingReads();
250 
251  if (b==nullptr)
252  {
253  fprintf (stderr, "ERROR: something strange happened here, bufferport_size = %d!\n",bufferport_size);
254  return;
255  }
256 
257  if (b->size()!=2)
258  {
259  fprintf (stderr, "ERROR: unknown log format!\n");
260  unknown_format_received++;
261  continue;
262  }
263 
264  std::string bottlestring = b->toString();
265  std::string header;
266 
267  if (b->get(0).isString())
268  {
269  header = b->get(0).asString();
270  }
271  else
272  {
273  fprintf(stderr, "ERROR: unknown log format!\n");
274  unknown_format_received++;
275  continue;
276  }
277 
278  MessageEntry body;
279 
280  char ttstr [20];
281  static int count=0;
282  sprintf(ttstr,"%d",count++);
283  body.yarprun_timestamp = std::string(ttstr);
284  body.local_timestamp = machine_current_time_s;
285 
286  std::string s;
287 
288  if (b->get(1).isString())
289  {
290  s = b->get(1).asString();
291  }
292  else
293  {
294  fprintf(stderr, "ERROR: unknown log format!\n");
295  unknown_format_received++;
296  continue;
297  }
298 
299  yarp::os::Property p(s.c_str());
300 
301  if (p.check("level")) {
302  body.text = p.find("message").toString();
303 
304  auto level = p.find("level").toString();
305  if (level == "TRACE") {
306  body.level = LOGLEVEL_TRACE;
307  } else if (level == "DEBUG") {
308  body.level = LOGLEVEL_DEBUG;
309  } else if (level == "INFO") {
310  body.level = LOGLEVEL_INFO;
311  } else if (level == "WARNING") {
312  body.level = LOGLEVEL_WARNING;
313  } else if (level == "ERROR") {
314  body.level = LOGLEVEL_ERROR;
315  } else if (level == "FATAL") {
316  body.level = LOGLEVEL_FATAL;
317  } else {
318  body.level = LOGLEVEL_UNDEFINED;
319  }
320 
321  if (p.check("filename")) {
322  body.filename = p.find("filename").asString();
323  } else {
324  body.filename.clear();
325  }
326 
327  if (p.check("line")) {
328  body.line = static_cast<uint32_t>(p.find("line").asInt32());
329  } else {
330  body.line = 0;
331  }
332 
333  if (p.check("function")) {
334  body.function = p.find("function").asString();
335  } else {
336  body.function.clear();
337  }
338 
339  if (p.check("hostname")) {
340  body.hostname = p.find("hostname").asString();
341  } else {
342  body.hostname.clear();
343  }
344 
345  if (p.check("pid")) {
346  body.pid = p.find("pid").asInt32();
347  } else {
348  body.pid = 0;
349  }
350 
351  if (p.check("cmd")) {
352  body.cmd = p.find("cmd").asString();
353  } else {
354  body.cmd.clear();
355  }
356 
357  if (p.check("args")) {
358  body.args = p.find("args").asString();
359  } else {
360  body.args.clear();
361  }
362 
363  if (p.check("thread_id")) {
364  body.thread_id = p.find("thread_id").asInt64();
365  } else {
366  body.thread_id = 0;
367  }
368 
369  if (p.check("component")) {
370  body.component = p.find("component").asString();
371  } else {
372  body.component.clear();
373  }
374 
375  if (p.check("systemtime")) {
376  body.systemtime = p.find("systemtime").asFloat64();
377  } else {
378  body.systemtime = 0.0;
379  }
380 
381  if (p.check("networktime")) {
382  body.networktime = p.find("networktime").asFloat64();
383  } else {
384  body.networktime = body.systemtime;
385  body.yarprun_timestamp.clear();
386  }
387 
388  if (p.check("externaltime")) {
389  body.externaltime = p.find("externaltime").asFloat64();
390  } else {
391  body.externaltime = 0.0;
392  }
393 
394  if (p.check("backtrace")) {
395  body.backtrace = p.find("backtrace").asString();
396  } else {
397  body.backtrace.clear();
398  }
399  } else {
400  // This is plain output forwarded by yarprun
401  // Perhaps at some point yarprun could be formatting it properly
402  // But for now we just try to extract the level information
403  body.text = s;
404  body.level = LOGLEVEL_UNDEFINED;
405 
406  size_t str = s.find('[',0);
407  size_t end = s.find(']',0);
408  if (str==std::string::npos || end==std::string::npos )
409  {
410  body.level = LOGLEVEL_UNDEFINED;
411  }
412  else if (str==0)
413  {
414  std::string level = s.substr(str,end+1);
415  body.level = LOGLEVEL_UNDEFINED;
416  if (level.find("TRACE") != std::string::npos) {
417  body.level = LOGLEVEL_TRACE;
418  } else if (level.find("DEBUG") != std::string::npos) {
419  body.level = LOGLEVEL_DEBUG;
420  } else if (level.find("INFO") != std::string::npos) {
421  body.level = LOGLEVEL_INFO;
422  } else if (level.find("WARNING") != std::string::npos) {
423  body.level = LOGLEVEL_WARNING;
424  } else if (level.find("ERROR") != std::string::npos) {
425  body.level = LOGLEVEL_ERROR;
426  } else if (level.find("FATAL") != std::string::npos) {
427  body.level = LOGLEVEL_FATAL;
428  }
429  body.text = s.substr(end+1);
430  }
431  else
432  {
433  body.level = LOGLEVEL_UNDEFINED;
434  }
435  }
436 
437  if (body.level == LOGLEVEL_UNDEFINED && listen_to_LOGLEVEL_UNDEFINED == false) {continue;}
438  if (body.level == LOGLEVEL_TRACE && listen_to_LOGLEVEL_TRACE == false) {continue;}
439  if (body.level == LOGLEVEL_DEBUG && listen_to_LOGLEVEL_DEBUG == false) {continue;}
440  if (body.level == LOGLEVEL_INFO && listen_to_LOGLEVEL_INFO == false) {continue;}
441  if (body.level == LOGLEVEL_WARNING && listen_to_LOGLEVEL_WARNING == false) {continue;}
442  if (body.level == LOGLEVEL_ERROR && listen_to_LOGLEVEL_ERROR == false) {continue;}
443  if (body.level == LOGLEVEL_FATAL && listen_to_LOGLEVEL_FATAL == false) {continue;}
444 
445  this->mutex.lock();
446  LogEntry entry;
447  entry.logInfo.port_complete = header;
448  entry.logInfo.port_complete.erase(0,1);
449  entry.logInfo.port_complete.erase(entry.logInfo.port_complete.size()-1);
450  std::istringstream iss(header);
451  std::string token;
452  getline(iss, token, '/');
453  getline(iss, token, '/'); entry.logInfo.port_system = token;
454  getline(iss, token, '/'); entry.logInfo.port_prefix = "/"+ token;
455  getline(iss, token, '/'); entry.logInfo.process_name = token;
456  getline(iss, token, '/'); entry.logInfo.process_pid = token.erase(token.size()-1);
457  if (entry.logInfo.port_system == "log" && listen_to_YARP_MESSAGES == false) {
458  continue;
459  }
460  if (entry.logInfo.port_system == "yarprunlog" && listen_to_YARPRUN_MESSAGES == false) {
461  continue;
462  }
463 
464  std::list<LogEntry>::iterator it;
465  for (it = log_list.begin(); it != log_list.end(); it++)
466  {
467  if (it->logInfo.port_complete==entry.logInfo.port_complete)
468  {
469  if (it->logging_enabled)
470  {
471  it->logInfo.setNewError(body.level);
472  it->logInfo.last_update=machine_current_time;
473  it->append_logEntry(body);
474  }
475  else
476  {
477  //just skipping this message
478  }
479  break;
480  }
481  }
482  if (it == log_list.end())
483  {
484  if (log_list.size() < log_list_max_size || log_list_max_size_enabled==false )
485  {
487  if (contact.isValid())
488  {
489  entry.logInfo.setNewError(body.level);
490  entry.logInfo.ip_address = contact.getHost();
491  }
492  else
493  {
494  printf("ERROR: invalid contact: %s\n", entry.logInfo.port_complete.c_str());
495  };
496  entry.append_logEntry(body);
497  entry.logInfo.last_update=machine_current_time;
498  log_list.push_back(entry);
499  }
500  //else
501  //{
502  // printf("WARNING: exceeded log_list_max_size=%d\n",log_list_max_size);
503  //}
504  }
505 
506  this->mutex.unlock();
507  }
508  }
509 
510 }
511 
512 //public methods
514 {
515  if (logging == true)
516  {
517  fprintf(stderr,"logger is already running, listening on port %s\n", log_updater->getPortName().c_str());
518  return true;
519  }
520 
521  if (yarp::os::Network::exists(log_updater->getPortName()))
522  {
523  fprintf(stderr, "Unable to start logger: port %s is unavailable because another instance of the logger is already running (or address conflict)\n", log_updater->getPortName().c_str());
524  return false;
525  }
526 
527  if (log_updater->logger_port.open(log_updater->getPortName()))
528  {
529  fprintf(stdout,"Logger successfully started, listening on port %s\n", log_updater->getPortName().c_str());
530  }
531  else
532  {
533  fprintf(stderr,"Unable to start logger: port %s is unavailable\n", log_updater->getPortName().c_str());
534  return false;
535  }
536  log_updater->logger_port.resume();
537  log_updater->logger_port.setStrict();
538  logging=true;
539  log_updater->start();
540  return true;
541 }
542 
543 void LoggerEngine::logger_thread::threadRelease()
544 {
545  logger_port.interrupt();
546  logger_port.close();
547 }
548 
550 {
551  if (log_updater == nullptr) {
552  return false;
553  }
554 
555  logging=false;
556  if (log_updater->isRunning() == true) {
557  log_updater->stop();
558  }
559  return true;
560 }
561 
563 {
564  if (log_updater == nullptr) {
565  return;
566  }
567 
568  log_updater->start();
569  discovering=true;
570 }
571 
573 {
574  discovering=false;
575 }
576 
577 LoggerEngine::LoggerEngine(std::string portName)
578 {
579  log_updater=new logger_thread (portName, 0.01);
580  logging = false;
581  discovering = false;
582 }
583 
585 {
586  this->stop_logging();
587  if (log_updater!=nullptr)
588  {
589  delete log_updater;
590  log_updater = nullptr;
591  }
592 }
593 
595 {
596  if (log_updater == nullptr) {
597  return 0;
598  }
599 
600  return log_updater->logger_port.getInputCount();
601 }
602 
603 void LoggerEngine::get_infos (std::list<LogEntryInfo>& infos)
604 {
605  if (log_updater == nullptr) {
606  return;
607  }
608 
609  log_updater->mutex.lock();
610  std::list<LogEntry>::iterator it;
611  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
612  {
613  infos.push_back(it->logInfo);
614  }
615  log_updater->mutex.unlock();
616 }
617 
618 void LoggerEngine::get_messages (std::list<MessageEntry>& messages)
619 {
620  if (log_updater == nullptr) {
621  return;
622  }
623 
624  log_updater->mutex.lock();
625  std::list<LogEntry>::iterator it;
626  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
627  {
628  messages.insert(messages.end(), it->entry_list.begin(), it->entry_list.end());
629  }
630  log_updater->mutex.unlock();
631 }
632 
633 void LoggerEngine::get_messages_by_port_prefix (std::string port, std::list<MessageEntry>& messages, bool from_beginning)
634 {
635  if (log_updater == nullptr) {
636  return;
637  }
638 
639  log_updater->mutex.lock();
640  std::list<LogEntry>::iterator it;
641  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
642  {
643  if (it->logInfo.port_prefix == port)
644  {
645  //messages = (it->entry_list);
646  if (it->last_read_message==-1)
647  {
648  from_beginning=true;
649  }
650  if (from_beginning==true)
651  {
652  it->last_read_message = 0;
653  }
654  int i=it->last_read_message;
655  for (; i<(int)it->entry_list.size(); i++)
656  {
657  messages.push_back(it->entry_list[i]);
658  }
659  it->last_read_message=i;
660  break;
661  }
662  }
663  log_updater->mutex.unlock();
664 }
665 
667 {
668  if (log_updater == nullptr) {
669  return;
670  }
671 
672  log_updater->mutex.lock();
673  std::list<LogEntry>::iterator it;
674  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
675  {
676  if (it->logInfo.port_complete == port)
677  {
678  it->clear_logEntries();
679  break;
680  }
681  }
682  log_updater->mutex.unlock();
683 }
684 
685 void LoggerEngine::get_messages_by_port_complete (std::string port, std::list<MessageEntry>& messages, bool from_beginning)
686 {
687  if (log_updater == nullptr) {
688  return;
689  }
690 
691  log_updater->mutex.lock();
692  std::list<LogEntry>::iterator it;
693  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
694  {
695  if (it->logInfo.port_complete == port)
696  {
697  //messages = (it->entry_list);
698  if (it->last_read_message==-1)
699  {
700  from_beginning=true;
701  }
702  if (from_beginning==true)
703  {
704  it->last_read_message = 0;
705  }
706  int i=it->last_read_message;
707  int size = (int)it->entry_list.size();
708  for (; i<size; i++)
709  {
710  messages.push_back(it->entry_list[i]);
711  }
712  it->last_read_message=i;
713  break;
714  }
715  }
716  log_updater->mutex.unlock();
717 }
718 
719 void LoggerEngine::get_messages_by_process (std::string process, std::list<MessageEntry>& messages, bool from_beginning)
720 {
721  if (log_updater == nullptr) {
722  return;
723  }
724 
725  log_updater->mutex.lock();
726  std::list<LogEntry>::iterator it;
727  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
728  {
729  if (it->logInfo.process_name == process)
730  {
731  //messages = (it->entry_list);
732  if (it->last_read_message==-1)
733  {
734  from_beginning=true;
735  }
736  if (from_beginning==true)
737  {
738  it->last_read_message = 0;
739  }
740  int i=it->last_read_message;
741  for (; i<(int)it->entry_list.size(); i++)
742  {
743  messages.push_back(it->entry_list[i]);
744  }
745  it->last_read_message=i;
746  break;
747  }
748  }
749  log_updater->mutex.unlock();
750 }
751 
752 void LoggerEngine::get_messages_by_pid (std::string pid, std::list<MessageEntry>& messages, bool from_beginning)
753 {
754  if (log_updater == nullptr) {
755  return;
756  }
757 
758  log_updater->mutex.lock();
759  std::list<LogEntry>::iterator it;
760  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
761  {
762  if (it->logInfo.process_pid == pid)
763  {
764  //messages = (it->entry_list);
765  if (it->last_read_message==-1)
766  {
767  from_beginning=true;
768  }
769  if (from_beginning==true)
770  {
771  it->last_read_message = 0;
772  }
773  int i=it->last_read_message;
774  for (; i<(int)it->entry_list.size(); i++)
775  {
776  messages.push_back(it->entry_list[i]);
777  }
778  it->last_read_message=i;
779  break;
780  }
781  }
782  log_updater->mutex.unlock();
783 }
784 
785 const std::list<MessageEntry> filter_by_level (int level, const std::list<MessageEntry>& messages)
786 {
787  std::list<MessageEntry> ret;
788  std::list<MessageEntry>::const_iterator it;
789  for (it = messages.begin(); it != messages.end(); it++)
790  {
791  LogLevel llevel = it->level;
792  if (llevel.toInt() == level) {
793  ret.push_back(*it);
794  }
795  }
796  return ret;
797 }
798 
799 void LoggerEngine::set_listen_option (LogLevel logLevel, bool enable)
800 {
801  if (log_updater == nullptr) {
802  return;
803  }
804  log_updater->mutex.lock();
805  if (logLevel == LOGLEVEL_UNDEFINED) {log_updater->listen_to_LOGLEVEL_UNDEFINED=enable;}
806  else if (logLevel == LOGLEVEL_TRACE) {log_updater->listen_to_LOGLEVEL_TRACE=enable;}
807  else if (logLevel == LOGLEVEL_INFO) {log_updater->listen_to_LOGLEVEL_INFO=enable;}
808  else if (logLevel == LOGLEVEL_DEBUG) {log_updater->listen_to_LOGLEVEL_DEBUG=enable;}
809  else if (logLevel == LOGLEVEL_WARNING) {log_updater->listen_to_LOGLEVEL_WARNING=enable;}
810  else if (logLevel == LOGLEVEL_ERROR) {log_updater->listen_to_LOGLEVEL_ERROR=enable;}
811  else if (logLevel == LOGLEVEL_FATAL) {log_updater->listen_to_LOGLEVEL_FATAL=enable;}
812  log_updater->mutex.unlock();
813 }
814 
816 {
817  if (log_updater == nullptr) {
818  return false;
819  }
820  if (logLevel == LOGLEVEL_UNDEFINED) {return log_updater->listen_to_LOGLEVEL_UNDEFINED;}
821  if (logLevel == LOGLEVEL_TRACE) {return log_updater->listen_to_LOGLEVEL_TRACE;}
822  if (logLevel == LOGLEVEL_DEBUG) {return log_updater->listen_to_LOGLEVEL_DEBUG;}
823  if (logLevel == LOGLEVEL_INFO) {return log_updater->listen_to_LOGLEVEL_INFO;}
824  if (logLevel == LOGLEVEL_WARNING) {return log_updater->listen_to_LOGLEVEL_WARNING;}
825  if (logLevel == LOGLEVEL_ERROR) {return log_updater->listen_to_LOGLEVEL_ERROR;}
826  if (logLevel == LOGLEVEL_FATAL) {return log_updater->listen_to_LOGLEVEL_FATAL;}
827  return false;
828 }
829 
830 void LoggerEngine::set_listen_option (std::string option, bool enable)
831 {
832  if (log_updater == nullptr) {
833  return;
834  }
835  log_updater->mutex.lock();
836  log_updater->mutex.unlock();
837 }
838 
839 bool LoggerEngine::get_listen_option (std::string option)
840 {
841  return false;
842 }
843 
844 void LoggerEngine::set_listen_option (LogSystemEnum logSystem, bool enable)
845 {
846  if (log_updater == nullptr) {
847  return;
848  }
849  log_updater->mutex.lock();
850  if (logSystem == LOGSYSTEM_YARP) {log_updater->listen_to_YARP_MESSAGES=enable;}
851  else if (logSystem == LOGSYSTEM_YARPRUN) {log_updater->listen_to_YARPRUN_MESSAGES=enable;}
852  log_updater->mutex.unlock();
853 }
854 
856 {
857  if (log_updater == nullptr) {
858  return false;
859  }
860  if (logSystem == LOGSYSTEM_YARP) {return log_updater->listen_to_YARP_MESSAGES;}
861  if (logSystem == LOGSYSTEM_YARPRUN) {return log_updater->listen_to_YARPRUN_MESSAGES;}
862  return false;
863 }
864 
865 bool LoggerEngine::export_log_to_text_file (std::string filename, std::string portname)
866 {
867  if (log_updater == nullptr) {
868  return false;
869  }
870  if (filename.size() == 0) {
871  return false;
872  }
873 
874  log_updater->mutex.lock();
875  std::list<LogEntry>::iterator it;
876  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
877  {
878  if (it->logInfo.port_complete == portname)
879  {
880  std::ofstream file1;
881  file1.open(filename.c_str());
882  if (file1.is_open() == false) {log_updater->mutex.unlock(); return false;}
883  std::vector<MessageEntry>::iterator it1;
884  for (it1 = it->entry_list.begin(); it1 != it->entry_list.end(); it1++)
885  {
886  file1 << it1->yarprun_timestamp << " " << it1->local_timestamp << " " << it1->level.toString() << " " << it1->text << '\n';
887  }
888  file1.close();
889  }
890  }
891  log_updater->mutex.unlock();
892  return true;
893 }
894 
895 bool LoggerEngine::save_all_logs_to_file (std::string filename)
896 {
897  std::string start_string ="<#STRING_START#>";
898  std::string end_string ="<#STRING_END#>";
899 
900  if (log_updater == nullptr) {
901  return false;
902  }
903  if (filename.size() == 0) {
904  return false;
905  }
906 
907  const int LOGFILE_VERSION = 1;
908 
909  std::ofstream file1;
910  file1.open(filename.c_str());
911  if (file1.is_open() == false) {
912  return false;
913  }
914 
915  bool wasRunning = log_updater->isRunning();
916  if (wasRunning) {
917  log_updater->stop();
918  }
919  std::list<LogEntry>::iterator it;
920  file1 << LOGFILE_VERSION << '\n';
921  file1 << log_updater->log_list.size() << '\n';
922  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
923  {
924  file1 << it->logInfo.ip_address << '\n';
925  file1 << it->logInfo.port_complete << '\n';
926  file1 << it->logInfo.port_prefix << '\n';
927  file1 << it->logInfo.port_system << '\n';
928  file1 << it->logInfo.process_name << '\n';
929  file1 << it->logInfo.process_pid << '\n';
930  file1 << it->logInfo.get_number_of_traces() << '\n';
931  file1 << it->logInfo.get_number_of_debugs() << '\n';
932  file1 << it->logInfo.get_number_of_infos() << '\n';
933  file1 << it->logInfo.get_number_of_warnings() << '\n';
934  file1 << it->logInfo.get_number_of_errors() << '\n';
935  file1 << it->logInfo.get_number_of_fatals() << '\n';
936  file1 << it->logInfo.logsize << '\n';
937  file1 << it->entry_list.size() << '\n';
938  std::vector<MessageEntry>::iterator it1;
939  for (it1 = it->entry_list.begin(); it1 != it->entry_list.end(); it1++)
940  {
941  file1 << it1->yarprun_timestamp << '\n';
942  file1 << it1->local_timestamp << '\n';
943  file1 << it1->level.toInt() << '\n';
944  file1 << start_string;
945  for (char s : it1->text) {
946  file1.put(s);
947  }
948  file1 << end_string <<'\n';
949  }
950  }
951  file1.close();
952  if (wasRunning) {
953  log_updater->start();
954  }
955  return true;
956 }
957 
958 std::streamoff get_tag(std::ifstream& file, const char* tag)
959 {
960  std::streamoff pos=file.tellg();
961  int tag_size=strlen(tag);
962  char* buff = new char[tag_size+2];
963  for (int i = 0; i < tag_size + 2; i++) {
964  buff[i] = 0;
965  }
966  std::streamoff off=0;
967  for (; ;off++)
968  {
969  file.seekg(pos+off);
970  file.read(buff,tag_size);
971  if (file.good()==false)
972  {
973  delete [] buff;
974  return -1;
975  }
976  if (strcmp(buff, tag) == 0) {
977  break;
978  }
979  }
980  delete [] buff;
981  return pos+off;
982 }
983 
984 bool LoggerEngine::load_all_logs_from_file (std::string filename)
985 {
986  std::string start_string ="<#STRING_START#>";
987  int start_string_size=strlen(start_string.c_str());
988  std::string end_string ="<#STRING_END#>";
989  int end_string_size=strlen(end_string.c_str());
990 
991  if (log_updater == nullptr) {
992  return false;
993  }
994  if (filename.size() == 0) {
995  return false;
996  }
997 
998  const int LOGFILE_VERSION = 1;
999 
1000  std::ifstream file1;
1001  file1.open(filename.c_str(),std::ifstream::binary);
1002  if (file1.is_open() == false) {
1003  return false;
1004  }
1005 
1006  int log_file_version;
1007  bool wasRunning = log_updater->isRunning();
1008  if (wasRunning) {
1009  log_updater->stop();
1010  }
1011  file1 >> log_file_version;
1012  if (log_file_version == LOGFILE_VERSION)
1013  {
1014  int size_log_list;
1015  file1 >> size_log_list;
1016  log_updater->log_list.clear();
1017  for (int i=0; i< size_log_list; i++)
1018  {
1019  LogEntry l_tmp;
1020  int dummy;
1021  file1 >> l_tmp.logInfo.ip_address;
1022  file1 >> l_tmp.logInfo.port_complete;
1023  file1 >> l_tmp.logInfo.port_prefix;
1024  file1 >> l_tmp.logInfo.port_system;
1025  file1 >> l_tmp.logInfo.process_name;
1026  file1 >> l_tmp.logInfo.process_pid;
1027  file1 >> dummy; //l_tmp.logInfo.number_of_traces;
1028  file1 >> dummy; //l_tmp.logInfo.number_of_debugs;
1029  file1 >> dummy; //l_tmp.logInfo.number_of_infos;
1030  file1 >> dummy; //l_tmp.logInfo.number_of_warning;
1031  file1 >> dummy; //l_tmp.logInfo.number_of_errors;
1032  file1 >> dummy; //l_tmp.logInfo.number_of_fatals;
1033  file1 >> l_tmp.logInfo.logsize;
1034  int size_entry_list;
1035  file1 >> size_entry_list;
1036  for (int j=0; j< size_entry_list; j++)
1037  {
1038  MessageEntry m_tmp;
1039  file1 >> m_tmp.yarprun_timestamp;
1040  file1 >> m_tmp.local_timestamp;
1041  int tmp_level;
1042  file1 >> tmp_level;
1043  m_tmp.level.setLevel(tmp_level);
1044  std::streamoff start_p = get_tag(file1, start_string.c_str());
1045  std::streamoff end_p = get_tag(file1, end_string.c_str());
1046  //validity check
1047  if (start_p < 0 || end_p < 0 || end_p - start_p + start_string_size <= 0) {
1048  return false;
1049  }
1050  char *buff = new char[(unsigned int)(end_p-start_p+start_string_size)];
1051  //memset(buff,0,end_p-start_p+start_string_size);
1052  file1.seekg(start_p+start_string_size);
1053  if (end_p-start_p-start_string_size!=1)
1054  {
1055  file1.get(buff,end_p-start_p-start_string_size);
1056  }
1057  else
1058  {
1059  //skip empty strings
1060  }
1061  file1.seekg(end_p+end_string_size);
1062  m_tmp.text=buff;
1063  delete [] buff;
1064  l_tmp.entry_list.push_back(m_tmp);
1065  }
1066  log_updater->log_list.push_back(l_tmp);
1067  }
1068  }
1069  file1.close();
1070  if (wasRunning) {
1071  log_updater->start();
1072  }
1073  return true;
1074 }
1075 
1076 void LoggerEngine::set_log_lines_max_size (bool enabled, int new_size)
1077 {
1078  if (log_updater == nullptr) {
1079  return;
1080  }
1081  log_updater->mutex.lock();
1082 
1083  std::list<LogEntry>::iterator it;
1084  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
1085  {
1086  it->setLogEntryMaxSize(new_size);
1087  it->setLogEntryMaxSizeEnabled(enabled);
1088  }
1089 
1090  log_updater->mutex.unlock();
1091 }
1092 
1093 
1094 void LoggerEngine::set_log_list_max_size (bool enabled, int new_size)
1095 {
1096  if (log_updater == nullptr) {
1097  return;
1098  }
1099  log_updater->mutex.lock();
1100  log_updater->log_list_max_size_enabled = enabled;
1101  log_updater->log_list_max_size = new_size;
1102  log_updater->mutex.unlock();
1103 }
1104 
1105 void LoggerEngine::get_log_lines_max_size (bool& enabled, int& current_size)
1106 {
1107  if (log_updater == nullptr) {
1108  return;
1109  }
1110  if (log_updater->log_list.empty() == true) {
1111  return;
1112  }
1113  log_updater->mutex.lock();
1114  auto it = log_updater->log_list.begin();
1115  current_size = it->getLogEntryMaxSize();
1116  enabled = it->getLogEntryMaxSizeEnabled();
1117  log_updater->mutex.unlock();
1118 }
1119 
1120 void LoggerEngine::get_log_list_max_size (bool& enabled, int& current_size)
1121 {
1122  if (log_updater == nullptr) {
1123  return;
1124  }
1125  log_updater->mutex.lock();
1126  enabled=log_updater->log_list_max_size_enabled;
1127  current_size=log_updater->log_list_max_size;
1128  log_updater->mutex.unlock();
1129 }
1130 
1132 {
1133  if (log_updater == nullptr) {
1134  return false;
1135  }
1136  log_updater->mutex.lock();
1137  log_updater->log_list.clear();
1138  log_updater->mutex.unlock();
1139  return true;
1140 }
1141 
1142 void LoggerEngine::set_log_enable_by_port_complete (std::string port, bool enable)
1143 {
1144  if (log_updater == nullptr) {
1145  return;
1146  }
1147 
1148  log_updater->mutex.lock();
1149  std::list<LogEntry>::iterator it;
1150  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
1151  {
1152  if (it->logInfo.port_complete == port)
1153  {
1154  it->logging_enabled=enable;
1155  break;
1156  }
1157  }
1158  log_updater->mutex.unlock();
1159 }
1160 
1162 {
1163  if (log_updater == nullptr) {
1164  return false;
1165  }
1166 
1167  bool enabled=false;
1168  log_updater->mutex.lock();
1169  std::list<LogEntry>::iterator it;
1170  for (it = log_updater->log_list.begin(); it != log_updater->log_list.end(); it++)
1171  {
1172  if (it->logInfo.port_complete == port)
1173  {
1174  enabled=it->logging_enabled;
1175  break;
1176  }
1177  }
1178  log_updater->mutex.unlock();
1179  return enabled;
1180 }
bool ret
std::streamoff get_tag(std::ifstream &file, const char *tag)
Definition: YarpLogger.cpp:958
const std::list< MessageEntry > filter_by_level(int level, const std::list< MessageEntry > &messages)
Definition: YarpLogger.cpp:785
bool write(const PortWriter &writer, const PortWriter *callback=nullptr) const override
Write an object to the port.
bool open(const std::string &name) override
Start port operation, with a specific name, with automatically-chosen network parameters.
A simple collection of objects that can be described and transmitted in a portable way.
Definition: Bottle.h:74
size_type size() const
Gets the number of elements in the bottle.
Definition: Bottle.cpp:251
bool read(ConnectionReader &reader) override
Set the bottle's value based on input from a network connection.
Definition: Bottle.cpp:240
Value & get(size_type index) const
Reads a Value v from a certain part of the list.
Definition: Bottle.cpp:246
void addString(const char *str)
Places a string in the bottle, at the end of the list.
Definition: Bottle.cpp:170
std::string toString() const override
Gives a human-readable textual representation of the bottle.
Definition: Bottle.cpp:211
Preferences for how to communicate with a contact.
Definition: ContactStyle.h:24
double timeout
Set a timeout for communication (in units of seconds, fractional seconds allowed).
Definition: ContactStyle.h:47
bool quiet
Suppress all outputs and warnings.
Definition: ContactStyle.h:36
Represents how to reach a part of a YARP network.
Definition: Contact.h:36
bool isValid() const
Checks if a Contact is tagged as valid.
Definition: Contact.cpp:298
std::string getHost() const
Get the host name associated with this Contact for socket communication.
Definition: Contact.cpp:228
static std::string getNameServerName()
Get the name of the port associated with the nameserver (usually "/root", but this can be overwritten...
Definition: Network.cpp:1352
static bool connect(const std::string &src, const std::string &dest, const std::string &carrier="", bool quiet=true)
Request that an output port connect to an input port.
Definition: Network.cpp:682
static Contact queryName(const std::string &name)
Find out information about a registered name.
Definition: Network.cpp:995
static bool exists(const std::string &port, bool quiet=true, bool checkVer=true)
Check for a port to be ready and responsive.
Definition: Network.cpp:746
An abstraction for a periodic thread.
A class for storing options and configuration information.
Definition: Property.h:34
A port that is specialized as an RPC client.
Definition: RpcClient.h:23
static double nowSystem()
Definition: SystemClock.cpp:34
virtual bool isString() const
Checks if value is a string.
Definition: Value.cpp:156
virtual Bottle * asList() const
Get list value.
Definition: Value.cpp:240
std::string toString() const override
Return a standard text representation of the content of the object.
Definition: Value.cpp:356
virtual std::string asString() const
Get string value.
Definition: Value.cpp:234
void setNewError(LogLevel level)
Definition: YarpLogger.cpp:83
yarp::yarpLogger::LogEntryInfo logInfo
Definition: YarpLogger.h:202
bool append_logEntry(MessageEntry entry)
Definition: YarpLogger.cpp:48
std::vector< MessageEntry > entry_list
Definition: YarpLogger.h:181
void setLevel(LogLevelEnum level)
Definition: YarpLogger.h:58
void set_log_list_max_size(bool enabled, int new_size)
bool get_listen_option(LogLevel logLevel)
Definition: YarpLogger.cpp:815
void get_log_lines_max_size(bool &enabled, int &current_size)
void get_messages(std::list< MessageEntry > &messages)
Definition: YarpLogger.cpp:618
bool get_log_enable_by_port_complete(std::string port)
void get_messages_by_port_prefix(std::string port, std::list< MessageEntry > &messages, bool from_beginning=false)
Definition: YarpLogger.cpp:633
LoggerEngine(std::string portName)
Definition: YarpLogger.cpp:577
void clear_messages_by_port_complete(std::string port)
Definition: YarpLogger.cpp:666
void get_messages_by_port_complete(std::string port, std::list< MessageEntry > &messages, bool from_beginning=false)
Definition: YarpLogger.cpp:685
void set_log_lines_max_size(bool enabled, int new_size)
void get_messages_by_process(std::string process, std::list< MessageEntry > &messages, bool from_beginning=false)
Definition: YarpLogger.cpp:719
bool load_all_logs_from_file(std::string filename)
Definition: YarpLogger.cpp:984
void get_log_list_max_size(bool &enabled, int &current_size)
bool save_all_logs_to_file(std::string filename)
Definition: YarpLogger.cpp:895
bool export_log_to_text_file(std::string filename, std::string portname)
Definition: YarpLogger.cpp:865
void get_infos(std::list< LogEntryInfo > &infos)
Definition: YarpLogger.cpp:603
void set_log_enable_by_port_complete(std::string port, bool enable)
void set_listen_option(LogLevel logLevel, bool enable)
Definition: YarpLogger.cpp:799
void get_messages_by_pid(std::string pid, std::list< MessageEntry > &messages, bool from_beginning=false)
Definition: YarpLogger.cpp:752
An interface to the operating system, including Port based communication.
ShouldUseSystemClock
Definition: Time.h:20