Line data Source code
1 : // Copyright (c) 2009-2010 Satoshi Nakamoto
2 : // Copyright (c) 2009-2018 The Bitcoin developers
3 : // Copyright (c) 2018-2021 The Dash Core developers
4 : // Copyright (c) 2015-2022 The PIVX Core developers
5 : // Distributed under the MIT software license, see the accompanying
6 : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
7 :
8 : /**
9 : * Server/client environment: argument handling, config file parsing,
10 : * logging, thread wrappers
11 : */
12 : #ifndef PIVX_LOGGING_H
13 : #define PIVX_LOGGING_H
14 :
15 : #include "fs.h"
16 : #include "tinyformat.h"
17 :
18 : #include <atomic>
19 : #include <cstdint>
20 : #include <list>
21 : #include <mutex>
22 : #include <vector>
23 :
24 :
25 : static const bool DEFAULT_LOGTIMEMICROS = false;
26 : static const bool DEFAULT_LOGIPS = false;
27 : static const bool DEFAULT_LOGTIMESTAMPS = true;
28 : extern const char * const DEFAULT_DEBUGLOGFILE;
29 :
30 : extern bool fLogIPs;
31 :
32 0 : struct CLogCategoryActive
33 : {
34 : std::string category;
35 : bool active;
36 : };
37 :
38 : namespace BCLog {
39 : enum LogFlags : uint32_t {
40 : NONE = 0,
41 : NET = (1 << 0),
42 : TOR = (1 << 1),
43 : MEMPOOL = (1 << 2),
44 : HTTP = (1 << 3),
45 : BENCHMARK = (1 << 4),
46 : ZMQ = (1 << 5),
47 : DB = (1 << 6),
48 : RPC = (1 << 7),
49 : ESTIMATEFEE = (1 << 8),
50 : ADDRMAN = (1 << 9),
51 : REINDEX = (1 << 10),
52 : PROXY = (1 << 11),
53 : MEMPOOLREJ = (1 << 12),
54 : LIBEVENT = (1 << 13),
55 : COINDB = (1 << 14),
56 : QT = (1 << 15),
57 : LEVELDB = (1 << 16),
58 : STAKING = (1 << 17),
59 : MASTERNODE = (1 << 18),
60 : MNBUDGET = (1 << 19),
61 : MNPING = (1 << 20),
62 : LEGACYZC = (1 << 21),
63 : SAPLING = (1 << 22),
64 : SPORKS = (1 << 23),
65 : VALIDATION = (1 << 24),
66 : LLMQ = (1 << 25),
67 : NET_MN = (1 << 26),
68 : DKG = (1 << 27),
69 : CHAINLOCKS = (1 << 28),
70 : ALL = ~(uint32_t)0,
71 : };
72 :
73 : class Logger
74 : {
75 : private:
76 : FILE* m_fileout = nullptr;
77 : std::mutex m_file_mutex;
78 : std::list<std::string> m_msgs_before_open;
79 :
80 : /**
81 : * m_started_new_line is a state variable that will suppress printing of
82 : * the timestamp when multiple calls are made that don't end in a
83 : * newline.
84 : */
85 : std::atomic_bool m_started_new_line{true};
86 :
87 : /** Log categories bitfield. */
88 : std::atomic<uint32_t> m_categories{0};
89 :
90 : std::string LogTimestampStr(const std::string& str);
91 :
92 : public:
93 : bool m_print_to_console = false;
94 : bool m_print_to_file = false;
95 :
96 : bool m_log_timestamps = DEFAULT_LOGTIMESTAMPS;
97 : bool m_log_time_micros = DEFAULT_LOGTIMEMICROS;
98 :
99 : fs::path m_file_path;
100 : std::atomic<bool> m_reopen_file{false};
101 :
102 : /** Send a string to the log output */
103 : void LogPrintStr(const std::string &str);
104 :
105 : /** Returns whether logs will be written to any output */
106 4421806 : bool Enabled() const { return m_print_to_console || m_print_to_file; }
107 :
108 : bool OpenDebugLog();
109 : void ShrinkDebugFile();
110 :
111 0 : uint32_t GetCategoryMask() const { return m_categories.load(); }
112 :
113 : void EnableCategory(LogFlags flag);
114 : bool EnableCategory(const std::string& str);
115 : void DisableCategory(LogFlags flag);
116 : bool DisableCategory(const std::string& str);
117 :
118 : bool WillLogCategory(LogFlags category) const;
119 :
120 : bool DefaultShrinkDebugFile() const;
121 : };
122 :
123 : } // namespace BCLog
124 :
125 : extern BCLog::Logger* const g_logger;
126 :
127 : /** Return true if log accepts specified category */
128 3933938 : static inline bool LogAcceptCategory(BCLog::LogFlags category)
129 : {
130 3933938 : return g_logger->WillLogCategory(category);
131 : }
132 :
133 : /** Returns a string with the supported log categories */
134 : std::string ListLogCategories();
135 :
136 : /** Returns a vector of the active log categories. */
137 : std::vector<CLogCategoryActive> ListActiveLogCategories();
138 :
139 : /** Return true if str parses as a log category and set the flag */
140 : bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
141 :
142 : // Be conservative when using LogPrintf/error or other things which
143 : // unconditionally log to debug.log! It should not be the case that an inbound
144 : // peer can fill up a user's disk with debug.log entries.
145 :
146 : template <typename... Args>
147 4420980 : static inline void LogPrintf(const char* fmt, const Args&... args)
148 : {
149 8813418 : if (g_logger->Enabled()) {
150 4392438 : std::string log_msg;
151 : try {
152 4392438 : log_msg = tfm::format(fmt, args...);
153 0 : } catch (tinyformat::format_error& fmterr) {
154 : /* Original format string will have newline so don't add one here */
155 0 : log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt;
156 : }
157 4392438 : g_logger->LogPrintStr(log_msg);
158 : }
159 4420980 : }
160 :
161 : // Use a macro instead of a function for conditional logging to prevent
162 : // evaluating arguments when logging for the category is not enabled.
163 : #define LogPrint(category, ...) do { \
164 : if (LogAcceptCategory((category))) { \
165 : LogPrintf(__VA_ARGS__); \
166 : } \
167 : } while(0)
168 :
169 : /// PIVX
170 :
171 : class CBatchedLogger
172 : {
173 : private:
174 : BCLog::Logger* logger;
175 : bool accept;
176 : std::string header;
177 : std::string msg;
178 : public:
179 : CBatchedLogger(BCLog::Logger* _logger, BCLog::LogFlags _category, const std::string& _header);
180 : virtual ~CBatchedLogger();
181 : void Flush();
182 :
183 : template<typename... Args>
184 1801 : void Batch(const std::string& fmt, const Args&... args)
185 : {
186 1801 : if (!accept) {
187 : return;
188 : }
189 3599 : msg += " " + strprintf(fmt, args...) + "\n";
190 : }
191 : };
192 :
193 : #endif // PIVX_LOGGING_H
|