logger.cpp
Go to the documentation of this file.
1 // Logs all output to a log file for the run
2 // Author: Max Schwarz <max.schwarz@uni-bonn.de>
3 
4 #include "logger.h"
5 #include "fmt/format.h"
6 
7 #include <cerrno>
8 #include <cstdio>
9 #include <cstring>
10 #include <ctime>
11 #include <stdexcept>
12 #include <iterator>
13 
14 #include <sys/time.h>
15 
16 #include <fmt/format.h>
17 
18 #include <syslog.h>
19 
20 #include <sys/socket.h>
21 #include <sys/un.h>
22 #include <unistd.h>
23 
24 namespace rosmon
25 {
26 
27 namespace
28 {
29  int prioFromEventType(LogEvent::Type type)
30  {
31  switch(type)
32  {
33  case LogEvent::Type::Error: return 3;
34  case LogEvent::Type::Warning: return 4;
35  case LogEvent::Type::Info: return 6;
36  case LogEvent::Type::Raw: return 6;
37  case LogEvent::Type::Debug: return 7;
38  }
39 
40  return 6;
41  }
42 }
43 
44 FileLogger::FileLogger(const std::string& path, bool flush)
45  : m_flush{flush}
46 {
47  m_flush = flush;
48  m_file = fopen(path.c_str(), "ae");
49  if(!m_file)
50  {
51  throw std::runtime_error(fmt::format(
52  "Could not open log file: {}", strerror(errno)
53  ));
54  }
55 }
56 
58 {
59  if(m_file)
60  fclose(m_file);
61 }
62 
63 void FileLogger::log(const LogEvent& event)
64 {
65  struct timeval tv;
66  memset(&tv, 0, sizeof(tv));
67  gettimeofday(&tv, nullptr);
68 
69  struct tm btime;
70  memset(&btime, 0, sizeof(tv));
71  localtime_r(&tv.tv_sec, &btime);
72 
73  char timeString[100];
74  strftime(timeString, sizeof(timeString), "%a %F %T", &btime);
75 
76  unsigned int len = event.message.length();
77  while(len != 0 && (event.message[len-1] == '\n' || event.message[len-1] == '\r'))
78  len--;
79 
80  fmt::print(m_file, "{}.{:03d}: {:>20}: ",
81  timeString, tv.tv_usec / 1000,
82  event.source.c_str()
83  );
84  fwrite(event.message.c_str(), 1, len, m_file);
85  fputc('\n', m_file);
86 
87  if(m_flush)
88  fflush(m_file);
89 }
90 
91 
92 SyslogLogger::SyslogLogger(const std::string& launchFileName)
93 {
94  m_tag = fmt::format("rosmon@{}", launchFileName);
95  openlog(m_tag.c_str(), 0, LOG_USER);
96 }
97 
98 void SyslogLogger::log(const LogEvent& event)
99 {
100  syslog(prioFromEventType(event.type), "%20s: %s", event.source.c_str(), event.message.c_str());
101 }
102 
103 
104 SystemdLogger::SystemdLogger(const std::string& launchFileName)
105  : m_launchFileName{launchFileName}
106 {
107  m_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
108  if(m_fd < 0)
109  throw std::runtime_error{fmt::format("Could not create socket: {}", strerror(errno))};
110 
111  int size = 8*1024*1024;
112  if(setsockopt(m_fd, SOL_SOCKET, SO_SNDBUF, &size, sizeof(size)) < 0)
113  perror("WARNING: Could not increase SO_SNDBUF size");
114 
115  sockaddr_un addr{};
116  addr.sun_family = AF_UNIX;
117  strncpy(addr.sun_path, "/run/systemd/journal/socket", sizeof(addr.sun_path)-1);
118 
119  if(connect(m_fd, reinterpret_cast<const sockaddr*>(&addr), sizeof(addr)) != 0)
120  throw NotAvailable{fmt::format("Systemd Journal not available: {}", strerror(errno))};
121 }
122 
124 {
125  if(m_fd >= 0)
126  close(m_fd);
127 }
128 
129 void SystemdLogger::log(const LogEvent& event)
130 {
131  fmt::memory_buffer buffer;
132 
133  fmt::format_to(std::back_inserter(buffer),
134  "PRIORITY={}\n"
135  "ROSMON_LAUNCH_FILE={}\n"
136  "ROSMON_NODE={}\n"
137  "SYSLOG_IDENTIFIER=rosmon@{}\n",
138  prioFromEventType(event.type),
140  event.source,
142  );
143 
144  std::string msg = fmt::format("{}: {}", event.source, event.message);
145 
146  if(msg.find('\n') == std::string::npos)
147  fmt::format_to(std::back_inserter(buffer), "MESSAGE={}\n", msg);
148  else
149  {
150  buffer.append(std::string{"MESSAGE\n"});
151  std::array<uint8_t, 8> size;
152  uint64_t sizeInt = msg.length();
153  for(int i = 0; i < 8; ++i)
154  {
155  size[i] = sizeInt & 0xFF;
156  sizeInt >>= 8;
157  }
158 
159  buffer.append(size);
160  buffer.append(msg);
161  buffer.append(std::string{"\n"});
162  }
163 
164  if(write(m_fd, buffer.data(), buffer.size()) < 0)
165  fprintf(stderr, "Could not write to systemd log: %s\n", strerror(errno));
166 }
167 
168 }
void log(const LogEvent &event) override
Definition: logger.cpp:98
std::string m_launchFileName
Definition: logger.h:77
void log(const LogEvent &event) override
Log message.
Definition: logger.cpp:63
FileLogger(const std::string &path, bool flush=false)
Constructor.
Definition: logger.cpp:44
SyslogLogger(const std::string &launchFileName)
Definition: logger.cpp:92
FILE * m_file
Definition: logger.h:39
~SystemdLogger() override
Definition: logger.cpp:123
SystemdLogger(const std::string &launchFileName)
Definition: logger.cpp:104
~FileLogger() override
Definition: logger.cpp:57
std::string source
Definition: log_event.h:60
void log(const LogEvent &event) override
Definition: logger.cpp:129
std::string message
Definition: log_event.h:61


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