PcapPlusPlus  Next
Logger.h
Go to the documentation of this file.
1 #pragma once
2 
3 #include <cstdio>
4 #include <cstdint>
5 #include <memory>
6 #include <array>
7 #include <mutex>
8 #include <ostream>
9 #include <sstream>
10 #include <functional>
11 #include "DeprecationUtils.h"
12 #include "ObjectPool.h"
13 
14 #ifndef LOG_MODULE
15 # define LOG_MODULE UndefinedLogModule
16 #endif
17 
18 // Use __FILE_NAME__ to avoid leaking complete full path
19 #ifdef __FILE_NAME__
20 # define PCAPPP_FILENAME __FILE_NAME__
21 #else
22 # define PCAPPP_FILENAME __FILE__
23 #endif
24 
26 
27 // Compile time log levels.
28 // Allows for conditional removal of unwanted log calls at compile time.
29 #define PCPP_LOG_LEVEL_OFF 0
30 #define PCPP_LOG_LEVEL_ERROR 1
31 #define PCPP_LOG_LEVEL_WARN 2
32 #define PCPP_LOG_LEVEL_INFO 3
33 #define PCPP_LOG_LEVEL_DEBUG 4
34 
35 // All log messages built via a PCPP_LOG_* macro below the PCPP_ACTIVE_LOG_LEVEL will be removed at compile time.
36 // Uses the PCPP_ACTIVE_LOG_LEVEL if it is defined, otherwise defaults to PCAP_LOG_LEVEL_DEBUG
37 #ifndef PCPP_ACTIVE_LOG_LEVEL
38 # define PCPP_ACTIVE_LOG_LEVEL PCPP_LOG_LEVEL_DEBUG
39 #endif // !PCPP_ACTIVE_LOG_LEVEL
40 
43 namespace pcpp
44 {
48  std::string getErrorString(int errnum);
49 
51  enum LogModule : uint8_t
52  {
53  UndefinedLogModule,
114  NumOfLogModules
115  };
116 
120  struct LogSource
121  {
123  constexpr LogSource() = default;
124 
128  {}
129 
135  constexpr LogSource(LogModule logModule, const char* file, const char* function, int line)
137  {}
138 
139  const char* file = nullptr;
140  const char* function = nullptr;
141  int line = 0;
142  LogModule logModule = UndefinedLogModule;
143  };
144 
147  enum class LogLevel : uint8_t
148  {
149  Off = PCPP_LOG_LEVEL_OFF,
150  Error = PCPP_LOG_LEVEL_ERROR,
151  Warn = PCPP_LOG_LEVEL_WARN,
152  Info = PCPP_LOG_LEVEL_INFO,
153  Debug = PCPP_LOG_LEVEL_DEBUG
154  };
155 
156  inline std::ostream& operator<<(std::ostream& ostr, LogLevel lvl)
157  {
158  return ostr << static_cast<std::underlying_type_t<LogLevel>>(lvl);
159  }
160 
161  // Forward declaration
162  class Logger;
163 
164  namespace internal
165  {
169  {
170  public:
171  friend class pcpp::Logger;
172 
174  LogContext() = default;
175 
179  explicit LogContext(LogLevel level, LogSource const& source = {}) : m_Source(source), m_Level(level)
180  {}
181 
185  void init(LogLevel level, LogSource const& source)
186  {
187  m_Source = source;
188  m_Level = level;
189  m_Stream.clear();
190  m_Stream.str({});
191  }
192 
196  template <class T> LogContext& operator<<(T const& value)
197  {
198  m_Stream << value;
199  return *this;
200  }
201 
202  private:
203  std::ostringstream m_Stream;
204  LogSource m_Source;
205  LogLevel m_Level = LogLevel::Info;
206  };
207  } // namespace internal
208 
226  class Logger
227  {
228  public:
229  Logger(const Logger&) = delete;
230  Logger& operator=(const Logger&) = delete;
231 
232  // Deprecated, Use the LogLevel in the pcpp namespace instead.
233  using LogLevel = pcpp::LogLevel;
234  PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
235  static const LogLevel Error = LogLevel::Error;
236  PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
237  static const LogLevel Info = LogLevel::Info;
238  PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
239  static const LogLevel Debug = LogLevel::Debug;
240 
249  using LogPrinter = std::function<void(LogLevel logLevel, const std::string& logMessage, const std::string& file,
250  const std::string& method, const int line)>;
251 
255  static std::string logLevelAsString(LogLevel logLevel);
256 
261  {
262  return m_LogModulesArray[module];
263  }
264 
268  void setLogLevel(LogModule module, LogLevel level)
269  {
270  m_LogModulesArray[module] = level;
271  }
272 
276  bool isDebugEnabled(LogModule module) const
277  {
278  return m_LogModulesArray[module] == LogLevel::Debug;
279  }
280 
285  bool shouldLog(LogLevel level, LogModule module) const
286  {
287  return level != LogLevel::Off && m_LogModulesArray[module] >= level;
288  }
289 
293  {
294  for (int i = 1; i < NumOfLogModules; i++)
295  {
296  m_LogModulesArray[i] = level;
297  }
298  }
299 
302  void setLogPrinter(LogPrinter printer)
303  {
304  m_LogPrinter = printer;
305  }
306 
309  {
310  m_LogPrinter = &defaultLogPrinter;
311  }
312 
314  std::string getLastError() const
315  {
316  std::lock_guard<std::mutex> const lock(m_LastErrorMtx);
317  return m_LastError;
318  }
319 
322  {
323  m_LogsEnabled = false;
324  }
325 
327  void enableLogs()
328  {
329  m_LogsEnabled = true;
330  }
331 
334  bool logsEnabled() const
335  {
336  return m_LogsEnabled;
337  }
338 
346  void useContextPooling(bool enabled, std::size_t preallocate = 2, std::size_t maxPoolSize = 10)
347  {
348  m_UseContextPooling = enabled;
349 
350  if (m_UseContextPooling)
351  {
352  m_LogContextPool.setMaxSize(maxPoolSize);
353 
354  if (preallocate > 0)
355  {
356  m_LogContextPool.preallocate(preallocate);
357  }
358  }
359  else
360  {
361  // Clear the pool if we're disabling pooling.
362  m_LogContextPool.clear();
363  }
364  }
365 
369  static Logger& getInstance()
370  {
371  static Logger instance;
372  return instance;
373  }
374 
377  std::unique_ptr<internal::LogContext> createLogContext();
378 
383  std::unique_ptr<internal::LogContext> createLogContext(LogLevel level, LogSource const& source = {});
384 
389  void emit(LogSource const& source, LogLevel level, std::string const& message);
390 
393  void emit(std::unique_ptr<internal::LogContext> message);
394 
395  private:
396  bool m_LogsEnabled;
397  std::array<LogLevel, NumOfLogModules> m_LogModulesArray{};
398  LogPrinter m_LogPrinter;
399 
400  mutable std::mutex m_LastErrorMtx;
401  std::string m_LastError;
402 
403  bool m_UseContextPooling = true;
404  // Keep a maximum of 10 LogContext objects in the pool.
405  internal::DynamicObjectPool<internal::LogContext> m_LogContextPool{ 10, 2 };
406 
407  // private c'tor - this class is a singleton
408  Logger();
409 
410  static void defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file,
411  const std::string& method, int line);
412  };
413 
414 } // namespace pcpp
415 
416 #define PCPP_LOG(level, message) \
417  do \
418  { \
419  auto& logger = pcpp::Logger::getInstance(); \
420  if (logger.shouldLog(level, LOG_MODULE)) \
421  { \
422  auto ctx = \
423  logger.createLogContext(level, pcpp::LogSource(LOG_MODULE, PCAPPP_FILENAME, __FUNCTION__, __LINE__)); \
424  (*ctx) << message; \
425  logger.emit(std::move(ctx)); \
426  } \
427  } while (0)
428 
429 #if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_DEBUG
430 # define PCPP_LOG_DEBUG(message) PCPP_LOG(pcpp::LogLevel::Debug, message)
431 #else
432 # define PCPP_LOG_DEBUG(message) (void)0
433 #endif
434 
435 #if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_WARN
436 # define PCPP_LOG_WARN(message) PCPP_LOG(pcpp::LogLevel::Warn, message)
437 #else
438 # define PCPP_LOG_WARN(message) (void)0
439 #endif
440 
441 #if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_INFO
442 # define PCPP_LOG_INFO(message) PCPP_LOG(pcpp::LogLevel::Info, message)
443 #else
444 # define PCPP_LOG_INFO(message) (void)0
445 #endif
446 
447 #if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_ERROR
448 # define PCPP_LOG_ERROR(message) PCPP_LOG(pcpp::LogLevel::Error, message)
449 #else
450 # define PCPP_LOG_ERROR(message) (void)0
451 #endif
Definition: Logger.h:227
void setLogPrinter(LogPrinter printer)
Definition: Logger.h:302
void enableLogs()
Enable logs in all PcapPlusPlus modules.
Definition: Logger.h:327
void emit(LogSource const &source, LogLevel level, std::string const &message)
Directly emits a log message bypassing all level checks.
void setLogLevel(LogModule module, LogLevel level)
Definition: Logger.h:268
std::string getLastError() const
Definition: Logger.h:314
LogLevel getLogLevel(LogModule module)
Definition: Logger.h:260
void useContextPooling(bool enabled, std::size_t preallocate=2, std::size_t maxPoolSize=10)
Controls if the logger should use a pool of LogContext objects.
Definition: Logger.h:346
bool shouldLog(LogLevel level, LogModule module) const
Check whether a log level should be emitted by the logger.
Definition: Logger.h:285
bool logsEnabled() const
Definition: Logger.h:334
void resetLogPrinter()
Set the log printer back to the default printer.
Definition: Logger.h:308
static Logger & getInstance()
Definition: Logger.h:369
std::unique_ptr< internal::LogContext > createLogContext()
Creates a new LogContext with Info level and no source.
void emit(std::unique_ptr< internal::LogContext > message)
Directly emits a log message bypassing all level checks.
void suppressLogs()
Suppress logs in all PcapPlusPlus modules.
Definition: Logger.h:321
static std::string logLevelAsString(LogLevel logLevel)
std::unique_ptr< internal::LogContext > createLogContext(LogLevel level, LogSource const &source={})
Creates a new LogContext with the given level and source.
std::function< void(LogLevel logLevel, const std::string &logMessage, const std::string &file, const std::string &method, const int line)> LogPrinter
Definition: Logger.h:250
bool isDebugEnabled(LogModule module) const
Definition: Logger.h:276
void setAllModulesToLogLevel(LogLevel level)
Definition: Logger.h:292
A generic object pool implementation.
Definition: ObjectPool.h:24
A context encapsulating the details of a single log message to be passed to the Logger.
Definition: Logger.h:169
LogContext()=default
Creates a context with an empty message with Info level and no source.
LogContext(LogLevel level, LogSource const &source={})
Creates a context with an empty message with the given level and source.
Definition: Logger.h:179
void init(LogLevel level, LogSource const &source)
Initializes the context with an empty message and the given level and source.
Definition: Logger.h:185
LogContext & operator<<(T const &value)
Appends to the message.
Definition: Logger.h:196
The main namespace for the PcapPlusPlus lib.
std::string getErrorString(int errnum)
LogModule
An enum representing all PcapPlusPlus modules.
Definition: Logger.h:52
@ PacketLogModuleRawPacket
RawPacket module (Packet++)
Definition: Logger.h:57
@ PacketLogModulePayloadLayer
PayloadLayer module (Packet++)
Definition: Logger.h:65
@ PcapLogModuleXdpDevice
XdpDevice module (Pcap++)
Definition: Logger.h:112
@ PacketLogModuleUdpLayer
UdpLayer module (Packet++)
Definition: Logger.h:67
@ PacketLogModuleTelnetLayer
TelnetLayer module (Packet++)
Definition: Logger.h:94
@ CommonLogModuleTablePrinter
Table printer module (Common++)
Definition: Logger.h:55
@ PacketLogModuleFtpLayer
FtpLayer module (Packet++)
Definition: Logger.h:98
@ PacketLogModuleGreLayer
GreLayer module (Packet++)
Definition: Logger.h:75
@ PacketLogModuleLLCLayer
LLCLayer module (Packet++)
Definition: Logger.h:96
@ PacketLogModuleVlanLayer
VlanLayer module (Packet++)
Definition: Logger.h:68
@ PcapLogModuleKniDevice
KniDevice module (Pcap++)
Definition: Logger.h:111
@ PacketLogModuleSomeIpLayer
SomeIpLayer module (Packet++)
Definition: Logger.h:99
@ PacketLogModuleEthLayer
EthLayer module (Packet++)
Definition: Logger.h:62
@ PacketLogModuleSll2Layer
Sll2Layer module (Packet++)
Definition: Logger.h:78
@ PacketLogModuleSdpLayer
SdpLayer module (Packet++)
Definition: Logger.h:84
@ PacketLogModuleIPv4Layer
IPv4Layer module (Packet++)
Definition: Logger.h:63
@ PacketLogModuleArpLayer
ArpLayer module (Packet++)
Definition: Logger.h:61
@ PacketLogModuleRadiusLayer
RadiusLayer module (Packet++)
Definition: Logger.h:85
@ PacketLogModuleDhcpV6Layer
DhcpV6Layer module (Packet++)
Definition: Logger.h:81
@ PacketLogModuleSipLayer
SipLayer module (Packet++)
Definition: Logger.h:83
@ PacketLogModuleNflogLayer
NflogLayer module (Packet++)
Definition: Logger.h:79
@ PcapLogModuleRemoteDevice
WinPcapRemoteDevice module (Pcap++)
Definition: Logger.h:105
@ PacketLogModuleNdpLayer
NdpLayer module (Packet++)
Definition: Logger.h:97
@ CommonLogModuleIpUtils
IP Utils module (Common++)
Definition: Logger.h:54
@ PacketLogModuleIcmpLayer
IcmpLayer module (Packet++)
Definition: Logger.h:73
@ PacketLogModuleNtpLayer
NtpLayer module (Packet++)
Definition: Logger.h:93
@ PacketLogModuleVrrpLayer
Vrrp Record module (Packet++)
Definition: Logger.h:89
@ PcapLogModuleFileDevice
FileDevice module (Pcap++)
Definition: Logger.h:107
@ PacketLogModuleGtpLayer
GtpLayer module (Packet++)
Definition: Logger.h:86
@ PacketLogModuleSSHLayer
SSHLayer module (Packet++)
Definition: Logger.h:88
@ PacketLogModuleDhcpLayer
DhcpLayer module (Packet++)
Definition: Logger.h:80
@ PcapLogModuleDpdkDevice
DpdkDevice module (Pcap++)
Definition: Logger.h:110
@ PacketLogModuleWakeOnLanLayer
WakeOnLanLayer module (Packet++)
Definition: Logger.h:101
@ PacketLogModulePPPoELayer
PPPoELayer module (Packet++)
Definition: Logger.h:70
@ PacketLogModuleIPReassembly
IPReassembly module (Packet++)
Definition: Logger.h:91
@ PacketLogModuleTcpReassembly
TcpReassembly module (Packet++)
Definition: Logger.h:90
@ PacketLogModuleHttpLayer
HttpLayer module (Packet++)
Definition: Logger.h:69
@ PacketLogModuleWireGuardLayer
WireGuardLayer module (Packet++)
Definition: Logger.h:103
@ PacketLogModuleBgpLayer
GtpLayer module (Packet++)
Definition: Logger.h:87
@ PacketLogModuleSllLayer
SllLayer module (Packet++)
Definition: Logger.h:77
@ CommonLogModuleGenericUtils
Generic Utils (Common++)
Definition: Logger.h:56
@ PacketLogModuleIgmpLayer
IgmpLayer module (Packet++)
Definition: Logger.h:82
@ PacketLogModuleStpLayer
StpLayer module (Packet++)
Definition: Logger.h:95
@ PcapLogModuleWinPcapLiveDevice
WinPcapLiveDevice module (Pcap++)
Definition: Logger.h:104
@ PacketLogModuleIPv6Layer
IPv6Layer module (Packet++)
Definition: Logger.h:64
@ PacketLogModuleMplsLayer
MplsLayer module (Packet++)
Definition: Logger.h:72
@ PacketLogModuleAsn1Codec
Asn1Codec module (Packet++)
Definition: Logger.h:60
@ PcapLogModuleNetworkUtils
Network Utils module (Pcap++)
Definition: Logger.h:113
@ PacketLogModuleDnsLayer
DnsLayer module (Packet++)
Definition: Logger.h:71
@ PcapLogModulePfRingDevice
PfRingDevice module (Pcap++)
Definition: Logger.h:108
@ PacketLogModuleSSLLayer
SSLLayer module (Packet++)
Definition: Logger.h:76
@ PacketLogModulePacket
Packet module (Packet++)
Definition: Logger.h:58
@ PacketLogModuleSomeIpSdLayer
SomeIpSdLayer module (Packet++)
Definition: Logger.h:100
@ PcapLogModuleMBufRawPacket
MBufRawPacket module (Pcap++)
Definition: Logger.h:109
@ PacketLogModuleLayer
Layer module (Packet++)
Definition: Logger.h:59
@ PacketLogModuleTcpLayer
TcpLayer module (Packet++)
Definition: Logger.h:66
@ PacketLogModuleIcmpV6Layer
IcmpV6Layer module (Packet++)
Definition: Logger.h:74
@ PcapLogModuleLiveDevice
PcapLiveDevice module (Pcap++)
Definition: Logger.h:106
@ PacketLogModuleSmtpLayer
SmtpLayer module (Packet++)
Definition: Logger.h:102
@ PacketLogModuleIPSecLayer
IPSecLayers module (Packet++)
Definition: Logger.h:92
LogLevel
Definition: Logger.h:148
@ Info
Info level logs and above are emitted.
@ Warn
Warning level logs and above are emitted.
@ Error
Error level logs are emitted.
@ Debug
Debug level logs and above are emitted.
@ Off
No log messages are emitted.
Definition: Logger.h:121
const char * function
Definition: Logger.h:140
LogModule logModule
Definition: Logger.h:142
constexpr LogSource()=default
Default constructor for LogSource.
constexpr LogSource(LogModule logModule)
Definition: Logger.h:127
constexpr LogSource(LogModule logModule, const char *file, const char *function, int line)
Definition: Logger.h:135
const char * file
Definition: Logger.h:139
int line
Definition: Logger.h:141