CoreSDK  v1.0.0.b1304
r5logger.h
1 /*
2  * Copyright (c) 2022 Infrared5, Inc.
3  * License information: https://account.red5.net/assets/LICENSE.txt
4  *
5  */
6 
7 #pragma once
8 
9 #include <chrono>
10 #include <iostream>
11 #include <list>
12 #include <map>
13 #include <memory>
14 #include <mutex>
15 #include <fstream>
16 #include <iomanip>
17 #include <climits>
18 #include <sstream>
19 
20 #include "r5common.h"
21 
22 namespace r5::common {
27 enum class LogLevel {
28  All = 0,
29  Trace = 5000,
30  Debug = 10000,
31  Info = 20000,
32  Warn = 30000,
33  Error = 40000,
34  Off = INT_MAX
35 };
39 class ILogger
40 {
41 public:
42  virtual ~ILogger(){};
48  virtual void SetLogLevel(LogLevel level) = 0;
56  virtual void LogMessage(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string msg) const = 0;
57 };
61 static std::map<LogLevel, std::string> LogLevelNames = { { LogLevel::Trace, "TRACE" }, { LogLevel::Debug, "DEBUG" }, { LogLevel::Info, "INFO" },
62  { LogLevel::Warn, "WARN" }, { LogLevel::Error, "ERROR" }, { LogLevel::Off, "OFF" } };
69 std::string R5_SDK_CORE_EXPORT MapToStr(LogLevel logLevel);
78 LogLevel R5_SDK_CORE_EXPORT MapFromStr(const std::string &logLevelStr, bool *ok = nullptr);
82 typedef std::shared_ptr<ILogger> ILoggerPtr;
87 {
88 public:
94  LoggerWrapper(ILoggerPtr t) : mT(t) {}
100  template<class... Args>
101  void trace(const std::string format, const Args &... args)
102  {
103  log(LogLevel::Trace, format, args...);
104  }
110  template<class... Args>
111  void info(const std::string format, const Args &... args)
112  {
113  log(LogLevel::Info, format, args...);
114  }
120  template<class... Args>
121  void warn(const std::string format, const Args &... args)
122  {
123  log(LogLevel::Warn, format, args...);
124  }
130  template<class... Args>
131  void error(const std::string format, const Args &... args)
132  {
133  log(LogLevel::Error, format, args...);
134  }
140  template<class... Args>
141  void debug(const std::string format, const Args &... args)
142  {
143  log(LogLevel::Debug, format, args...);
144  }
145 
146 protected:
153  template<class... Args>
154  void log(LogLevel level, const std::string format, const Args &... args)
155  {
156  log(std::chrono::system_clock::now(), level, format, args...);
157  }
165  template<class... Args>
166  void log(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string format, const Args &... args)
167  {
168  if (mT == nullptr) {
169  return;
170  }
171 
172  auto formattedSize = std::snprintf(nullptr, 0, format.c_str(), args...) + 1;
173  if (formattedSize <= 0) {
174  return;
175  }
176  auto size = static_cast<size_t>(formattedSize);
177  auto buf = std::make_unique<char[]>(size);
178  std::snprintf(buf.get(), size, format.c_str(), args...);
179 
180  std::istringstream input(std::string(buf.get(), buf.get() + size - 1));
181  for (std::string line; std::getline(input, line);) {
182  mT->LogMessage(time, level, line);
183  }
184  }
185 
186  ILoggerPtr mT;
187 };
194 static std::string ToStr(const std::chrono::system_clock::time_point &time)
195 {
196  static const auto fmt = "%Y-%m-%d %T";
197 
198  // 'YYYY-MM-DD HH:MM:SS.MMM' + some extra space just in case
199  char dateTime[30] = { 0 };
200  const auto t = std::chrono::system_clock::to_time_t(time);
201  if (std::strftime(dateTime, sizeof(dateTime), fmt, localtime(&t))) {
202  }
203 
204  std::stringstream ss;
205  ss << dateTime << "." << std::setw(3) << std::setfill('0')
206  << std::chrono::duration_cast<std::chrono::milliseconds>(time.time_since_epoch()).count() % 1000;
207 
208  return ss.str();
209 }
213 class StdoutLogger : public ILogger
214 {
215 public:
223  virtual void LogMessage(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string msg) const override
224  {
225  if (level < mLevel) {
226  return;
227  }
228 
229  std::stringstream ss;
230  ss << ToStr(time) << " ";
231 
232  std::map<LogLevel, std::string>::iterator iter = LogLevelNames.find(level);
233  if (iter != LogLevelNames.end()) {
234  std::stringstream ssLevel;
235  ssLevel << "[" << iter->second << "]";
236  ss << std::setw(9) << std::left << ssLevel.str(); // max length of log level is 5 + 2 for brackets '[', ']' + 2 for spaces
237  }
238 
239  ss << msg << std::endl;
240 
241  auto &os = (level == LogLevel::Error ? std::cerr : std::cout);
242  os << ss.str();
243  }
248  virtual void SetLogLevel(LogLevel level) override { mLevel = level; }
249 
250 private:
251  LogLevel mLevel = LogLevel::Warn;
252 };
257 class FileLogger : public ILogger
258 {
259 public:
265  FileLogger(std::string fileName) { mFileName = fileName; }
273  virtual void LogMessage(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string msg) const override
274  {
275  if (level < mLevel) {
276  return;
277  }
278 
279  std::lock_guard<std::mutex> lock(mMutex);
280 
281  std::ofstream logFile(mFileName, std::ios_base::app);
282  if (logFile.is_open()) {
283  logFile << ToStr(time) << " ";
284 
285  std::map<LogLevel, std::string>::iterator iter = LogLevelNames.find(level);
286  if (iter != LogLevelNames.end()) {
287  std::stringstream ssLevel;
288  ssLevel << "[" << iter->second << "]";
289  logFile << std::setw(9) << std::left << ssLevel.str(); // max length of log level is 5 + 2 for brackets '[', ']' + 2 for spaces
290  }
291 
292  logFile << msg << std::endl;
293 
294  logFile.close();
295  }
296  }
297 
302  virtual void SetLogLevel(LogLevel level) override { mLevel = level; }
303 
304 private:
305  LogLevel mLevel = LogLevel::Warn;
306  std::string mFileName;
307  mutable std::mutex mMutex;
308 };
309 }
virtual void SetLogLevel(LogLevel level) override
Implementatio of method to set the log level of object.
Definition: r5logger.h:302
virtual void SetLogLevel(LogLevel level) override
Implementatio of method to set the log level of object.
Definition: r5logger.h:248
void log(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string format, const Args &... args)
Log message with specified log level and timestamp.
Definition: r5logger.h:166
LoggerWrapper(ILoggerPtr t)
Default constructor.
Definition: r5logger.h:94
void error(const std::string format, const Args &... args)
Log message with Error log level.
Definition: r5logger.h:131
Helper object that simplfies use of ILogger.
Definition: r5logger.h:86
ILoggerPtr mT
internal pointer to logger instance
Definition: r5logger.h:186
virtual void LogMessage(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string msg) const override
Implementation of method to log message to stdout.
Definition: r5logger.h:223
void warn(const std::string format, const Args &... args)
Log message with Warn log level.
Definition: r5logger.h:121
virtual void LogMessage(const std::chrono::system_clock::time_point &time, LogLevel level, const std::string msg) const override
Implementation of method to log message to specified file.
Definition: r5logger.h:273
void debug(const std::string format, const Args &... args)
Log message with Debug log level.
Definition: r5logger.h:141
void log(LogLevel level, const std::string format, const Args &... args)
Log message with specified log level.
Definition: r5logger.h:154
Simple implementation of logger that prints messages to file.
Definition: r5logger.h:257
Interface for Red5Pro Core SDK internal logger access.
Definition: r5logger.h:39
Simple implementation of logger that prints messages to stdout.
Definition: r5logger.h:213
void trace(const std::string format, const Args &... args)
Log message with Trace log level.
Definition: r5logger.h:101
Definition: r5codec.h:12
void info(const std::string format, const Args &... args)
Log message with Info log level.
Definition: r5logger.h:111
FileLogger(std::string fileName)
Constructor that specify output file name.
Definition: r5logger.h:265