Coverage Report

Created: 2026-08-14 06:50

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/PcapPlusPlus/Common++/src/Logger.cpp
Line
Count
Source
1
#include "Logger.h"
2
3
#include <iostream>
4
#include <iomanip>
5
#include <sstream>
6
#include <cstring>
7
#include <mutex>
8
9
namespace pcpp
10
{
11
12
  namespace
13
  {
14
    /// Default log printer function that prints to std::cerr.
15
    void printToCerr(LogLevel logLevel, const std::string& logMessage, const std::string& file,
16
                     const std::string& method, const int line)
17
0
    {
18
      // This mutex is used to prevent multiple threads from writing to the console at the same time.
19
0
      static std::mutex logMutex;
20
21
0
      std::ostringstream sstream;
22
0
      sstream << file << ": " << method << ":" << line;
23
24
0
      std::unique_lock<std::mutex> const lock(logMutex);
25
0
      std::cerr << std::left << "[" << std::setw(5) << Logger::logLevelAsString(logLevel) << ": " << std::setw(45)
26
0
                << sstream.str() << "] " << logMessage << std::endl;
27
0
    }
28
  }  // namespace
29
30
  // Alpine Linux incorrectly declares strerror_r
31
  // https://stackoverflow.com/questions/41953104/strerror-r-is-incorrectly-declared-on-alpine-linux
32
  char* checkError(int /*unused*/, char* buffer, int /*unused*/)
33
0
  {
34
0
    return buffer;
35
0
  }
36
37
  char* checkError(char* result, const char* /*unused*/, int /*unused*/)
38
0
  {
39
0
    return result;
40
0
  }
41
42
  std::string getErrorString(int errnum)
43
0
  {
44
0
    std::array<char, BUFSIZ> buffer{};
45
#if defined(_WIN32)
46
    strerror_s(buffer.data(), buffer.size(), errnum);
47
    return buffer.data();
48
#else
49
0
    return checkError(strerror_r(errnum, buffer.data(), BUFSIZ), buffer.data(), errnum);
50
0
#endif
51
0
  }
52
53
  thread_local std::array<char, 255> Logger::m_LastError = { 0 };
54
55
1
  Logger::Logger() : m_LogsEnabled(true), m_LogPrinter(&printToCerr)
56
1
  {
57
1
    m_LogModulesArray.fill(LogLevel::Info);
58
1
  }
59
60
  std::string Logger::logLevelAsString(LogLevel logLevel)
61
0
  {
62
0
    switch (logLevel)
63
0
    {
64
0
    case LogLevel::Off:
65
0
      return "OFF";
66
0
    case LogLevel::Error:
67
0
      return "ERROR";
68
0
    case LogLevel::Warn:
69
0
      return "WARN";
70
0
    case LogLevel::Info:
71
0
      return "INFO";
72
0
    case LogLevel::Debug:
73
0
      return "DEBUG";
74
0
    default:
75
0
      return "UNKNOWN";
76
0
    }
77
0
  }
78
79
  void Logger::resetLogPrinter()
80
0
  {
81
0
    m_LogPrinter = &printToCerr;  // Reset to the default log printer
82
0
  }
83
84
  std::unique_ptr<internal::LogContext> Logger::createLogContext()
85
0
  {
86
0
    return createLogContext(LogLevel::Info, {});  // call the other createLogContext method
87
0
  }
88
  std::unique_ptr<internal::LogContext> Logger::createLogContext(LogLevel level, LogSource const& source)
89
1.29k
  {
90
1.29k
    if (m_UseContextPooling)
91
1.29k
    {
92
1.29k
      auto ctx = m_LogContextPool.acquireObject();
93
1.29k
      ctx->init(level, source);
94
1.29k
      return ctx;
95
1.29k
    }
96
0
    return std::make_unique<internal::LogContext>(level, source);
97
1.29k
  }
98
99
  void Logger::emit(std::unique_ptr<internal::LogContext> message)
100
1.29k
  {
101
1.29k
    emit(message->m_Source, message->m_Level, message->m_Stream.str());
102
    // Pushes the message back to the pool if pooling is enabled. Otherwise, the message is deleted.
103
1.29k
    if (m_UseContextPooling)
104
1.29k
    {
105
1.29k
      m_LogContextPool.releaseObject(std::move(message));
106
1.29k
    }
107
1.29k
  }
108
109
  void Logger::emit(LogSource const& source, LogLevel logLevel, std::string const& message)
110
1.29k
  {
111
    // If the log level is an error, save the error to the last error message variable.
112
1.29k
    if (logLevel == LogLevel::Error)
113
264
    {
114
264
      static_assert(m_LastError.size() >= 1,
115
264
                    "Last error buffer size must be at least 1 to hold a null terminator");
116
117
      // Copy the message to the last error buffer, leaving space for null terminator
118
264
      auto const copied = message.copy(m_LastError.data(), m_LastError.size() - 1);
119
264
      m_LastError[copied] = '\0';
120
264
    }
121
1.29k
    if (m_LogsEnabled)
122
0
    {
123
0
      m_LogPrinter(logLevel, message, source.file, source.function, source.line);
124
0
    }
125
1.29k
  }
126
}  // namespace pcpp