/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 | 1 | thread_local std::string Logger::m_LastError = [] { |
54 | 1 | std::string str; |
55 | 1 | str.reserve(200); |
56 | 1 | return str; |
57 | 1 | }(); |
58 | | |
59 | 1 | Logger::Logger() : m_LogsEnabled(true), m_LogPrinter(&printToCerr) |
60 | 1 | { |
61 | 1 | m_LogModulesArray.fill(LogLevel::Info); |
62 | 1 | } |
63 | | |
64 | | std::string Logger::logLevelAsString(LogLevel logLevel) |
65 | 0 | { |
66 | 0 | switch (logLevel) |
67 | 0 | { |
68 | 0 | case LogLevel::Off: |
69 | 0 | return "OFF"; |
70 | 0 | case LogLevel::Error: |
71 | 0 | return "ERROR"; |
72 | 0 | case LogLevel::Warn: |
73 | 0 | return "WARN"; |
74 | 0 | case LogLevel::Info: |
75 | 0 | return "INFO"; |
76 | 0 | case LogLevel::Debug: |
77 | 0 | return "DEBUG"; |
78 | 0 | default: |
79 | 0 | return "UNKNOWN"; |
80 | 0 | } |
81 | 0 | } |
82 | | |
83 | | void Logger::resetLogPrinter() |
84 | 0 | { |
85 | 0 | m_LogPrinter = &printToCerr; // Reset to the default log printer |
86 | 0 | } |
87 | | |
88 | | std::unique_ptr<internal::LogContext> Logger::createLogContext() |
89 | 0 | { |
90 | 0 | return createLogContext(LogLevel::Info, {}); // call the other createLogContext method |
91 | 0 | } |
92 | | std::unique_ptr<internal::LogContext> Logger::createLogContext(LogLevel level, LogSource const& source) |
93 | 1.77k | { |
94 | 1.77k | if (m_UseContextPooling) |
95 | 1.77k | { |
96 | 1.77k | auto ctx = m_LogContextPool.acquireObject(); |
97 | 1.77k | ctx->init(level, source); |
98 | 1.77k | return ctx; |
99 | 1.77k | } |
100 | 0 | return std::make_unique<internal::LogContext>(level, source); |
101 | 1.77k | } |
102 | | |
103 | | void Logger::emit(std::unique_ptr<internal::LogContext> message) |
104 | 1.77k | { |
105 | 1.77k | emit(message->m_Source, message->m_Level, message->m_Stream.str()); |
106 | | // Pushes the message back to the pool if pooling is enabled. Otherwise, the message is deleted. |
107 | 1.77k | if (m_UseContextPooling) |
108 | 1.77k | { |
109 | 1.77k | m_LogContextPool.releaseObject(std::move(message)); |
110 | 1.77k | } |
111 | 1.77k | } |
112 | | |
113 | | void Logger::emit(LogSource const& source, LogLevel logLevel, std::string const& message) |
114 | 1.77k | { |
115 | | // If the log level is an error, save the error to the last error message variable. |
116 | 1.77k | if (logLevel == LogLevel::Error) |
117 | 498 | { |
118 | 498 | m_LastError = message; |
119 | 498 | } |
120 | 1.77k | if (m_LogsEnabled) |
121 | 0 | { |
122 | 0 | m_LogPrinter(logLevel, message, source.file, source.function, source.line); |
123 | 0 | } |
124 | 1.77k | } |
125 | | } // namespace pcpp |