Coverage Report

Created: 2025-07-18 06:14

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