Coverage Report

Created: 2025-07-11 06:47

/src/PcapPlusPlus/Common++/header/Logger.h
Line
Count
Source (jump to first uncovered line)
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 "DeprecationUtils.h"
11
#include "ObjectPool.h"
12
13
#ifndef LOG_MODULE
14
0
# define LOG_MODULE UndefinedLogModule
15
#endif
16
17
// Use __FILE_NAME__ to avoid leaking complete full path
18
#ifdef __FILE_NAME__
19
705
# define PCAPPP_FILENAME __FILE_NAME__
20
#else
21
# define PCAPPP_FILENAME __FILE__
22
#endif
23
24
/// @file
25
26
// Compile time log levels.
27
// Allows for conditional removal of unwanted log calls at compile time.
28
#define PCPP_LOG_LEVEL_OFF 0
29
#define PCPP_LOG_LEVEL_ERROR 1
30
#define PCPP_LOG_LEVEL_INFO 2
31
#define PCPP_LOG_LEVEL_DEBUG 3
32
33
// All log messages built via a PCPP_LOG_* macro below the PCPP_ACTIVE_LOG_LEVEL will be removed at compile time.
34
// Uses the PCPP_ACTIVE_LOG_LEVEL if it is defined, otherwise defaults to PCAP_LOG_LEVEL_DEBUG
35
#ifndef PCPP_ACTIVE_LOG_LEVEL
36
# define PCPP_ACTIVE_LOG_LEVEL PCPP_LOG_LEVEL_DEBUG
37
#endif  // !PCPP_ACTIVE_LOG_LEVEL
38
39
/// @namespace pcpp
40
/// @brief The main namespace for the PcapPlusPlus lib
41
namespace pcpp
42
{
43
  /// Cross-platform and thread-safe version of strerror
44
  /// @param errnum Value of errno
45
  /// @return String representation of the error number
46
  std::string getErrorString(int errnum);
47
48
  /// An enum representing all PcapPlusPlus modules
49
  enum LogModule : uint8_t
50
  {
51
    UndefinedLogModule,
52
    CommonLogModuleIpUtils,          ///< IP Utils module (Common++)
53
    CommonLogModuleTablePrinter,     ///< Table printer module (Common++)
54
    CommonLogModuleGenericUtils,     ///< Generic Utils (Common++)
55
    PacketLogModuleRawPacket,        ///< RawPacket module (Packet++)
56
    PacketLogModulePacket,           ///< Packet module (Packet++)
57
    PacketLogModuleLayer,            ///< Layer module (Packet++)
58
    PacketLogModuleAsn1Codec,        ///< Asn1Codec module (Packet++)
59
    PacketLogModuleArpLayer,         ///< ArpLayer module (Packet++)
60
    PacketLogModuleEthLayer,         ///< EthLayer module (Packet++)
61
    PacketLogModuleIPv4Layer,        ///< IPv4Layer module (Packet++)
62
    PacketLogModuleIPv6Layer,        ///< IPv6Layer module (Packet++)
63
    PacketLogModulePayloadLayer,     ///< PayloadLayer module (Packet++)
64
    PacketLogModuleTcpLayer,         ///< TcpLayer module (Packet++)
65
    PacketLogModuleUdpLayer,         ///< UdpLayer module (Packet++)
66
    PacketLogModuleVlanLayer,        ///< VlanLayer module (Packet++)
67
    PacketLogModuleHttpLayer,        ///< HttpLayer module (Packet++)
68
    PacketLogModulePPPoELayer,       ///< PPPoELayer module (Packet++)
69
    PacketLogModuleDnsLayer,         ///< DnsLayer module (Packet++)
70
    PacketLogModuleMplsLayer,        ///< MplsLayer module (Packet++)
71
    PacketLogModuleIcmpLayer,        ///< IcmpLayer module (Packet++)
72
    PacketLogModuleIcmpV6Layer,      ///< IcmpV6Layer module (Packet++)
73
    PacketLogModuleGreLayer,         ///< GreLayer module (Packet++)
74
    PacketLogModuleSSLLayer,         ///< SSLLayer module (Packet++)
75
    PacketLogModuleSllLayer,         ///< SllLayer module (Packet++)
76
    PacketLogModuleSll2Layer,        ///< Sll2Layer module (Packet++)
77
    PacketLogModuleNflogLayer,       ///< NflogLayer module (Packet++)
78
    PacketLogModuleDhcpLayer,        ///< DhcpLayer module (Packet++)
79
    PacketLogModuleDhcpV6Layer,      ///< DhcpV6Layer module (Packet++)
80
    PacketLogModuleIgmpLayer,        ///< IgmpLayer module (Packet++)
81
    PacketLogModuleSipLayer,         ///< SipLayer module (Packet++)
82
    PacketLogModuleSdpLayer,         ///< SdpLayer module (Packet++)
83
    PacketLogModuleRadiusLayer,      ///< RadiusLayer module (Packet++)
84
    PacketLogModuleGtpLayer,         ///< GtpLayer module (Packet++)
85
    PacketLogModuleBgpLayer,         ///< GtpLayer module (Packet++)
86
    PacketLogModuleSSHLayer,         ///< SSHLayer module (Packet++)
87
    PacketLogModuleVrrpLayer,        ///< Vrrp Record module (Packet++)
88
    PacketLogModuleTcpReassembly,    ///< TcpReassembly module (Packet++)
89
    PacketLogModuleIPReassembly,     ///< IPReassembly module (Packet++)
90
    PacketLogModuleIPSecLayer,       ///< IPSecLayers module (Packet++)
91
    PacketLogModuleNtpLayer,         ///< NtpLayer module (Packet++)
92
    PacketLogModuleTelnetLayer,      ///< TelnetLayer module (Packet++)
93
    PacketLogModuleStpLayer,         ///< StpLayer module (Packet++)
94
    PacketLogModuleLLCLayer,         ///< LLCLayer module (Packet++)
95
    PacketLogModuleNdpLayer,         ///< NdpLayer module (Packet++)
96
    PacketLogModuleFtpLayer,         ///< FtpLayer module (Packet++)
97
    PacketLogModuleSomeIpLayer,      ///< SomeIpLayer module (Packet++)
98
    PacketLogModuleSomeIpSdLayer,    ///< SomeIpSdLayer module (Packet++)
99
    PacketLogModuleWakeOnLanLayer,   ///< WakeOnLanLayer module (Packet++)
100
    PacketLogModuleSmtpLayer,        ///< SmtpLayer module (Packet++)
101
    PacketLogModuleWireGuardLayer,   ///< WireGuardLayer module (Packet++)
102
    PcapLogModuleWinPcapLiveDevice,  ///< WinPcapLiveDevice module (Pcap++)
103
    PcapLogModuleRemoteDevice,       ///< WinPcapRemoteDevice module (Pcap++)
104
    PcapLogModuleLiveDevice,         ///< PcapLiveDevice module (Pcap++)
105
    PcapLogModuleFileDevice,         ///< FileDevice module (Pcap++)
106
    PcapLogModulePfRingDevice,       ///< PfRingDevice module (Pcap++)
107
    PcapLogModuleMBufRawPacket,      ///< MBufRawPacket module (Pcap++)
108
    PcapLogModuleDpdkDevice,         ///< DpdkDevice module (Pcap++)
109
    PcapLogModuleKniDevice,          ///< KniDevice module (Pcap++)
110
    PcapLogModuleXdpDevice,          ///< XdpDevice module (Pcap++)
111
    PcapLogModuleNetworkUtils,       ///< Network Utils module (Pcap++)
112
    NumOfLogModules
113
  };
114
115
  /// @struct LogSource
116
  /// Represents the source of a log message.
117
  /// Contains information about the source file, function, line number, and the log module.
118
  struct LogSource
119
  {
120
    /// Default constructor for LogSource.
121
2
    constexpr LogSource() = default;
122
123
    /// Constructor for LogSource with only the log module.
124
    /// @param logModule The log module.
125
    explicit constexpr LogSource(LogModule logModule) : logModule(logModule)
126
0
    {}
127
128
    /// Constructor for LogSource with all parameters.
129
    /// @param logModule The log module.
130
    /// @param file The source file.
131
    /// @param function The source function.
132
    /// @param line The line number.
133
    constexpr LogSource(LogModule logModule, const char* file, const char* function, int line)
134
705
        : file(file), function(function), line(line), logModule(logModule)
135
705
    {}
136
137
    const char* file = nullptr;               /**< The source file. */
138
    const char* function = nullptr;           /**< The source function. */
139
    int line = 0;                             /**< The line number. */
140
    LogModule logModule = UndefinedLogModule; /**< The log module. */
141
  };
142
143
  /// An enum representing the log level. Currently 4 log levels are supported: Off, Error, Info and Debug. Info is
144
  /// the default log level
145
  enum class LogLevel
146
  {
147
    Off = PCPP_LOG_LEVEL_OFF,      ///< No log messages are emitted.
148
    Error = PCPP_LOG_LEVEL_ERROR,  ///< Error level logs are emitted.
149
    Info = PCPP_LOG_LEVEL_INFO,    ///< Info level logs and above are emitted.
150
    Debug = PCPP_LOG_LEVEL_DEBUG   ///< Debug level logs and above are emitted.
151
  };
152
153
  inline std::ostream& operator<<(std::ostream& s, LogLevel v)
154
0
  {
155
0
    return s << static_cast<std::underlying_type<LogLevel>::type>(v);
156
0
  }
157
158
  // Forward declaration
159
  class Logger;
160
161
  namespace internal
162
  {
163
    /// @class LogContext
164
    /// @brief A context encapsulating the details of a single log message to be passed to the Logger.
165
    class LogContext
166
    {
167
    public:
168
      friend class pcpp::Logger;
169
170
      /// @brief Creates a context with an empty message with Info level and no source.
171
2
      LogContext() = default;
172
173
      /// @brief Creates a context with an empty message with the given level and source.
174
      /// @param level The log level for this message.
175
      /// @param source The log source.
176
0
      explicit LogContext(LogLevel level, LogSource const& source = {}) : m_Source(source), m_Level(level)
177
0
      {}
178
179
      /// @brief Initializes the context with an empty message and the given level and source.
180
      /// @param level The log level for this message.
181
      /// @param source The log source.
182
      void init(LogLevel level, LogSource const& source)
183
705
      {
184
705
        m_Source = source;
185
705
        m_Level = level;
186
705
        m_Stream.clear();
187
705
        m_Stream.str({});
188
705
      }
189
190
      /// @brief Appends to the message.
191
      /// @param value The value to append.
192
      /// @return A reference to this context.
193
      template <class T> inline LogContext& operator<<(T const& value)
194
2.87k
      {
195
2.87k
        m_Stream << value;
196
2.87k
        return *this;
197
2.87k
      }
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [54]>(char const (&) [54])
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > >(std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&)
Line
Count
Source
194
705
      {
195
705
        m_Stream << value;
196
705
        return *this;
197
705
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [2]>(char const (&) [2])
Line
Count
Source
194
56
      {
195
56
        m_Stream << value;
196
56
        return *this;
197
56
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [46]>(char const (&) [46])
Line
Count
Source
194
649
      {
195
649
        m_Stream << value;
196
649
        return *this;
197
649
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [4]>(char const (&) [4])
Line
Count
Source
194
649
      {
195
649
        m_Stream << value;
196
649
        return *this;
197
649
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [256]>(char const (&) [256])
Line
Count
Source
194
649
      {
195
649
        m_Stream << value;
196
649
        return *this;
197
649
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [21]>(char const (&) [21])
Line
Count
Source
194
56
      {
195
56
        m_Stream << value;
196
56
        return *this;
197
56
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <int>(int const&)
Line
Count
Source
194
56
      {
195
56
        m_Stream << value;
196
56
        return *this;
197
56
      }
pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [31]>(char const (&) [31])
Line
Count
Source
194
56
      {
195
56
        m_Stream << value;
196
56
        return *this;
197
56
      }
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [18]>(char const (&) [18])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [53]>(char const (&) [53])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [14]>(char const (&) [14])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [13]>(char const (&) [13])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [47]>(char const (&) [47])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [32]>(char const (&) [32])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [36]>(char const (&) [36])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [33]>(char const (&) [33])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [30]>(char const (&) [30])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [48]>(char const (&) [48])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [56]>(char const (&) [56])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [60]>(char const (&) [60])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [55]>(char const (&) [55])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [107]>(char const (&) [107])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [44]>(char const (&) [44])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [35]>(char const (&) [35])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [49]>(char const (&) [49])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char const*>(char const* const&)
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [22]>(char const (&) [22])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [26]>(char const (&) [26])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [15]>(char const (&) [15])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [17]>(char const (&) [17])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [94]>(char const (&) [94])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <pcpp::LinkLayerType>(pcpp::LinkLayerType const&)
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [3]>(char const (&) [3])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [24]>(char const (&) [24])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [27]>(char const (&) [27])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [37]>(char const (&) [37])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [41]>(char const (&) [41])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [59]>(char const (&) [59])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [45]>(char const (&) [45])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [61]>(char const (&) [61])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [23]>(char const (&) [23])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [43]>(char const (&) [43])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [28]>(char const (&) [28])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [52]>(char const (&) [52])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [40]>(char const (&) [40])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [20]>(char const (&) [20])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [38]>(char const (&) [38])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [70]>(char const (&) [70])
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <unsigned long>(unsigned long const&)
Unexecuted instantiation: pcpp::internal::LogContext& pcpp::internal::LogContext::operator<< <char [42]>(char const (&) [42])
198
199
    private:
200
      std::ostringstream m_Stream;
201
      LogSource m_Source;
202
      LogLevel m_Level = LogLevel::Info;
203
    };
204
  }  // namespace internal
205
206
  /// @class Logger
207
  /// PcapPlusPlus logger manager.
208
  /// PcapPlusPlus uses this logger to output both error and debug logs.
209
  /// There are currently 3 log levels: Logger#Error, Logger#Info and Logger#Debug.
210
  ///
211
  /// PcapPlusPlus is divided into modules (described in #LogModule enum). The user can set the log level got each
212
  /// module or to all modules at once. The default is Logger#Info which outputs only error messages. Changing log
213
  /// level for modules can be done dynamically while the application is running.
214
  ///
215
  /// The logger also exposes a method to retrieve the last error log message.
216
  ///
217
  /// Logs are printed to console by default in a certain format. The user can set a different print function to
218
  /// change the format or to print to other media (such as files, etc.).
219
  ///
220
  /// PcapPlusPlus logger is a singleton which can be reached from anywhere in the code.
221
  ///
222
  /// Note: Logger#Info level logs are currently only used in DPDK devices to set DPDK log level to RTE_LOG_NOTICE.
223
  class Logger
224
  {
225
  public:
226
    Logger(const Logger&) = delete;
227
    Logger& operator=(const Logger&) = delete;
228
229
    // Deprecated, Use the LogLevel in the pcpp namespace instead.
230
    using LogLevel = pcpp::LogLevel;
231
    PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
232
    static const LogLevel Error = LogLevel::Error;
233
    PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
234
    static const LogLevel Info = LogLevel::Info;
235
    PCPP_DEPRECATED("Use the LogLevel in the pcpp namespace instead.")
236
    static const LogLevel Debug = LogLevel::Debug;
237
238
    /// @typedef LogPrinter
239
    /// Log printer callback. Used for printing the logs in a custom way.
240
    /// @param[in] logLevel The log level for this log message
241
    /// @param[in] logMessage The log message
242
    /// @param[in] file The source file in PcapPlusPlus code the log message is coming from
243
    /// @param[in] method The method in PcapPlusPlus code the log message is coming from
244
    /// @param[in] line The line in PcapPlusPlus code the log message is coming from
245
    /// @remarks The printer callback should support being called from multiple threads simultaneously.
246
    using LogPrinter =
247
        std::add_pointer<void(LogLevel logLevel, const std::string& logMessage, const std::string& file,
248
                              const std::string& method, const int line)>::type;
249
250
    /// A static method for converting the log level enum to a string.
251
    /// @param[in] logLevel A log level enum
252
    /// @return The log level as a string
253
    static std::string logLevelAsString(LogLevel logLevel);
254
255
    /// Get the log level for a certain module
256
    /// @param[in] module PcapPlusPlus module
257
    /// @return The log level set for this module
258
    LogLevel getLogLevel(LogModule module)
259
0
    {
260
0
      return m_LogModulesArray[module];
261
0
    }
262
263
    /// Set the log level for a certain PcapPlusPlus module
264
    /// @param[in] module PcapPlusPlus module
265
    /// @param[in] level The log level to set the module to
266
    void setLogLevel(LogModule module, LogLevel level)
267
0
    {
268
0
      m_LogModulesArray[module] = level;
269
0
    }
270
271
    /// Check whether a certain module is set to debug log level
272
    /// @param[in] module PcapPlusPlus module
273
    /// @return True if this module log level is "debug". False otherwise
274
    bool isDebugEnabled(LogModule module) const
275
0
    {
276
0
      return m_LogModulesArray[module] == LogLevel::Debug;
277
0
    }
278
279
    /// @brief Check whether a log level should be emitted by the logger.
280
    /// @param level The level of the log message.
281
    /// @param module PcapPlusPlus module
282
    /// @return True if the message should be emitted. False otherwise.
283
    bool shouldLog(LogLevel level, LogModule module) const
284
23.0k
    {
285
23.0k
      return level != LogLevel::Off && m_LogModulesArray[module] >= level;
286
23.0k
    }
287
288
    /// Set all PcapPlusPlus modules to a certain log level
289
    /// @param[in] level The log level to set all modules to
290
    void setAllModulesToLogLevel(LogLevel level)
291
0
    {
292
0
      for (int i = 1; i < NumOfLogModules; i++)
293
0
      {
294
0
        m_LogModulesArray[i] = level;
295
0
      }
296
0
    }
297
298
    /// Set a custom log printer.
299
    /// @param[in] printer A log printer function that will be called for every log message
300
    void setLogPrinter(LogPrinter printer)
301
0
    {
302
0
      m_LogPrinter = printer;
303
0
    }
304
305
    /// Set the log printer back to the default printer
306
    void resetLogPrinter()
307
0
    {
308
0
      m_LogPrinter = &defaultLogPrinter;
309
0
    }
310
311
    /// @return Get the last error message
312
    std::string getLastError() const
313
0
    {
314
0
      std::lock_guard<std::mutex> lock(m_LastErrorMtx);
315
0
      return m_LastError;
316
0
    }
317
318
    /// Suppress logs in all PcapPlusPlus modules
319
    void suppressLogs()
320
4.65k
    {
321
4.65k
      m_LogsEnabled = false;
322
4.65k
    }
323
324
    /// Enable logs in all PcapPlusPlus modules
325
    void enableLogs()
326
0
    {
327
0
      m_LogsEnabled = true;
328
0
    }
329
330
    /// Get an indication if logs are currently enabled.
331
    /// @return True if logs are currently enabled, false otherwise
332
    bool logsEnabled() const
333
0
    {
334
0
      return m_LogsEnabled;
335
0
    }
336
337
    /// @brief Controls if the logger should use a pool of LogContext objects.
338
    ///
339
    /// If enabled is set to false, preallocate and maxPoolSize are ignored.
340
    /// @param enabled True to enable context pooling, false to disable.
341
    /// @param preallocate The number of LogContext objects to preallocate in the pool.
342
    /// @param maxPoolSize The maximum number of LogContext objects to keep in the pool.
343
    /// @remarks Disabling the pooling clears the pool.
344
    void useContextPooling(bool enabled, std::size_t preallocate = 2, std::size_t maxPoolSize = 10)
345
0
    {
346
0
      m_UseContextPooling = enabled;
347
0
348
0
      if (m_UseContextPooling)
349
0
      {
350
0
        m_LogContextPool.setMaxSize(maxPoolSize);
351
0
352
0
        if (preallocate > 0)
353
0
        {
354
0
          m_LogContextPool.preallocate(preallocate);
355
0
        }
356
0
      }
357
0
      else
358
0
      {
359
0
        // Clear the pool if we're disabling pooling.
360
0
        m_LogContextPool.clear();
361
0
      }
362
0
    }
363
364
    /// Get access to Logger singleton
365
    /// @todo: make this singleton thread-safe/
366
    /// @return a pointer to the Logger singleton
367
    static Logger& getInstance()
368
27.6k
    {
369
27.6k
      static Logger instance;
370
27.6k
      return instance;
371
27.6k
    }
372
373
    /// @brief Creates a new LogContext with Info level and no source.
374
    /// @return A new LogContext.
375
    std::unique_ptr<internal::LogContext> createLogContext();
376
377
    /// @brief Creates a new LogContext with the given level and source.
378
    /// @param level The log level for this message.
379
    /// @param source The log source.
380
    /// @return A new LogContext.
381
    std::unique_ptr<internal::LogContext> createLogContext(LogLevel level, LogSource const& source = {});
382
383
    /// @brief Directly emits a log message bypassing all level checks.
384
    /// @param source The log source.
385
    /// @param level The log level for this message. This is only used for the log printer.
386
    /// @param message The log message.
387
    void emit(LogSource const& source, LogLevel level, std::string const& message);
388
389
    /// @brief Directly emits a log message bypassing all level checks.
390
    /// @param message The log message.
391
    void emit(std::unique_ptr<internal::LogContext> message);
392
393
  private:
394
    bool m_LogsEnabled;
395
    std::array<LogLevel, NumOfLogModules> m_LogModulesArray;
396
    LogPrinter m_LogPrinter;
397
398
    mutable std::mutex m_LastErrorMtx;
399
    std::string m_LastError;
400
401
    bool m_UseContextPooling = true;
402
    // Keep a maximum of 10 LogContext objects in the pool.
403
    internal::DynamicObjectPool<internal::LogContext> m_LogContextPool{ 10, 2 };
404
405
    // private c'tor - this class is a singleton
406
    Logger();
407
408
    static void defaultLogPrinter(LogLevel logLevel, const std::string& logMessage, const std::string& file,
409
                                  const std::string& method, int line);
410
  };
411
412
}  // namespace pcpp
413
414
#define PCPP_LOG(level, message)                                                                                       \
415
23.0k
  do                                                                                                                 \
416
23.0k
  {                                                                                                                  \
417
23.0k
    auto& logger = pcpp::Logger::getInstance();                                                                    \
418
23.0k
    if (logger.shouldLog(level, LOG_MODULE))                                                                       \
419
23.0k
    {                                                                                                              \
420
705
      auto ctx =                                                                                                 \
421
705
          logger.createLogContext(level, pcpp::LogSource(LOG_MODULE, PCAPPP_FILENAME, __FUNCTION__, __LINE__));  \
422
705
      (*ctx) << message;                                                                                         \
423
705
      logger.emit(std::move(ctx));                                                                               \
424
705
    }                                                                                                              \
425
23.0k
  } while (0)
426
427
#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_DEBUG
428
22.3k
# define PCPP_LOG_DEBUG(message) PCPP_LOG(pcpp::LogLevel::Debug, message)
429
#else
430
# define PCPP_LOG_DEBUG(message) (void)0
431
#endif
432
433
#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_INFO
434
# define PCPP_LOG_INFO(message) PCPP_LOG(pcpp::LogLevel::Info, message)
435
#else
436
# define PCPP_LOG_INFO(message) (void)0
437
#endif
438
439
#if PCPP_ACTIVE_LOG_LEVEL >= PCPP_LOG_LEVEL_ERROR
440
705
# define PCPP_LOG_ERROR(message) PCPP_LOG(pcpp::LogLevel::Error, message)
441
#else
442
# define PCPP_LOG_ERROR(message) (void)0
443
#endif