PIVX Core  5.6.99
P2P Digital Currency
logging.cpp
Go to the documentation of this file.
1 // Copyright (c) 2009-2010 Satoshi Nakamoto
2 // Copyright (c) 2009-2018 The Bitcoin developers
3 // Copyright (c) 2015-2022 The PIVX Core developers
4 // Distributed under the MIT software license, see the accompanying
5 // file COPYING or http://www.opensource.org/licenses/mit-license.php.
6 
7 #include "logging.h"
8 #include "utiltime.h"
9 
10 
11 const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
12 
27 
28 bool fLogIPs = DEFAULT_LOGIPS;
29 
30 
31 static int FileWriteStr(const std::string &str, FILE *fp)
32 {
33  return fwrite(str.data(), 1, str.size(), fp);
34 }
35 
37 {
38  std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
39 
40  assert(m_fileout == nullptr);
41  assert(!m_file_path.empty());
42 
44  if (!m_fileout) return false;
45 
46  setbuf(m_fileout, nullptr); // unbuffered
47  // dump buffered messages from before we opened the log
48  while (!m_msgs_before_open.empty()) {
49  FileWriteStr(m_msgs_before_open.front(), m_fileout);
50  m_msgs_before_open.pop_front();
51  }
52 
53  return true;
54 }
55 
57 {
58  m_categories |= flag;
59 }
60 
61 bool BCLog::Logger::EnableCategory(const std::string& str)
62 {
63  BCLog::LogFlags flag;
64  if (!GetLogCategory(flag, str)) return false;
65  EnableCategory(flag);
66  return true;
67 }
68 
70 {
71  m_categories &= ~flag;
72 }
73 
74 bool BCLog::Logger::DisableCategory(const std::string& str)
75 {
76  BCLog::LogFlags flag;
77  if (!GetLogCategory(flag, str)) return false;
78  DisableCategory(flag);
79  return true;
80 }
81 
83 {
84  return (m_categories.load(std::memory_order_relaxed) & category) != 0;
85 }
86 
88 {
89  return m_categories == BCLog::NONE;
90 }
91 
93 {
95  std::string category;
96 };
97 
99  {BCLog::NONE, "0"},
100  {BCLog::NET, "net"},
101  {BCLog::TOR, "tor"},
102  {BCLog::MEMPOOL, "mempool"},
103  {BCLog::HTTP, "http"},
104  {BCLog::BENCHMARK, "bench"},
105  {BCLog::ZMQ, "zmq"},
106  {BCLog::DB, "db"},
107  {BCLog::RPC, "rpc"},
108  {BCLog::ESTIMATEFEE, "estimatefee"},
109  {BCLog::ADDRMAN, "addrman"},
110  {BCLog::REINDEX, "reindex"},
111  {BCLog::PROXY, "proxy"},
112  {BCLog::MEMPOOLREJ, "mempoolrej"},
113  {BCLog::LIBEVENT, "libevent"},
114  {BCLog::COINDB, "coindb"},
115  {BCLog::QT, "qt"},
116  {BCLog::LEVELDB, "leveldb"},
117  {BCLog::STAKING, "staking"},
118  {BCLog::MASTERNODE, "masternode"},
119  {BCLog::MNBUDGET, "mnbudget"},
120  {BCLog::LEGACYZC, "zero"},
121  {BCLog::MNPING, "mnping"},
122  {BCLog::SAPLING, "sapling"},
123  {BCLog::SPORKS, "sporks"},
124  {BCLog::VALIDATION, "validation"},
125  {BCLog::LLMQ, "llmq"},
126  {BCLog::NET_MN, "net_mn"},
127  {BCLog::DKG, "dkg"},
128  {BCLog::CHAINLOCKS, "chainlocks"},
129  {BCLog::ALL, "1"},
130  {BCLog::ALL, "all"},
131 };
132 
133 bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
134 {
135  if (str == "") {
136  flag = BCLog::ALL;
137  return true;
138  }
139  for (const CLogCategoryDesc& category_desc : LogCategories) {
140  if (category_desc.category == str) {
141  flag = category_desc.flag;
142  return true;
143  }
144  }
145  return false;
146 }
147 
148 std::string ListLogCategories()
149 {
150  std::string ret;
151  int outcount = 0;
152  for (const CLogCategoryDesc& category_desc : LogCategories) {
153  // Omit the special cases.
154  if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
155  if (outcount != 0) ret += ", ";
156  ret += category_desc.category;
157  outcount++;
158  }
159  }
160  return ret;
161 }
162 
163 std::vector<CLogCategoryActive> ListActiveLogCategories()
164 {
165  std::vector<CLogCategoryActive> ret;
166  for (const CLogCategoryDesc& category_desc : LogCategories) {
167  // Omit the special cases.
168  if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
169  CLogCategoryActive catActive;
170  catActive.category = category_desc.category;
171  catActive.active = LogAcceptCategory(category_desc.flag);
172  ret.push_back(catActive);
173  }
174  }
175  return ret;
176 }
177 
178 std::string BCLog::Logger::LogTimestampStr(const std::string &str)
179 {
180  std::string strStamped;
181 
182  if (!m_log_timestamps)
183  return str;
184 
185  if (m_started_new_line) {
186  int64_t nTimeMicros = GetTimeMicros();
187  strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
188  if (m_log_time_micros) {
189  strStamped.pop_back();
190  strStamped += strprintf(".%06dZ", nTimeMicros % 1000000);
191  }
192  int64_t mocktime = GetMockTime();
193  if (mocktime) {
194  strStamped += " (mocktime: " + FormatISO8601DateTime(mocktime) + ")";
195  }
196  strStamped += ' ' + str;
197  } else
198  strStamped = str;
199 
200  if (!str.empty() && str[str.size()-1] == '\n')
201  m_started_new_line = true;
202  else
203  m_started_new_line = false;
204 
205  return strStamped;
206 }
207 
208 void BCLog::Logger::LogPrintStr(const std::string &str)
209 {
210  std::string strTimestamped = LogTimestampStr(str);
211 
212  if (m_print_to_console) {
213  // print to console
214  fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
215  fflush(stdout);
216  }
217 
218  if (m_print_to_file) {
219  std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
220 
221  // buffer if we haven't opened the log yet
222  if (m_fileout == nullptr) {
223  m_msgs_before_open.push_back(strTimestamped);
224 
225  } else {
226  // reopen the log file, if requested
227  if (m_reopen_file) {
228  m_reopen_file = false;
229  FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
230  if (new_fileout) {
231  setbuf(new_fileout, nullptr); // unbuffered
232  fclose(m_fileout);
233  m_fileout = new_fileout;
234  }
235  }
236  FileWriteStr(strTimestamped, m_fileout);
237  }
238  }
239 }
240 
242 {
243  // Amount of debug.log to save at end when shrinking (must fit in memory)
244  constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
245 
246  assert(!m_file_path.empty());
247 
248  // Scroll debug.log if it's getting too big
249  FILE* file = fsbridge::fopen(m_file_path, "r");
250  if (file && fs::file_size(m_file_path) > RECENT_DEBUG_HISTORY_SIZE) {
251  // Restart the file with some of the end
252  std::vector<char> vch(200000, 0);
253  fseek(file, -((long)vch.size()), SEEK_END);
254  int nBytes = fread(vch.data(), 1, vch.size(), file);
255  fclose(file);
256 
257  file = fsbridge::fopen(m_file_path, "w");
258  if (file) {
259  fwrite(vch.data(), 1, nBytes, file);
260  fclose(file);
261  }
262  } else if (file != nullptr)
263  fclose(file);
264 }
265 
267 
268 CBatchedLogger::CBatchedLogger(BCLog::Logger* _logger, BCLog::LogFlags _category, const std::string& _header) :
269  logger(_logger),
270  accept(LogAcceptCategory(_category)),
271  header(_header)
272 {}
273 
275 {
276  Flush();
277 }
278 
280 {
281  if (!accept || msg.empty()) {
282  return;
283  }
284  if (logger && logger->Enabled()) {
285  logger->LogPrintStr(strprintf("%s:\n%s", header, msg));
286  msg.clear();
287  }
288 }
bool OpenDebugLog()
Definition: logging.cpp:36
bool WillLogCategory(LogFlags category) const
Definition: logging.cpp:82
bool Enabled() const
Returns whether logs will be written to any output.
Definition: logging.h:106
std::string LogTimestampStr(const std::string &str)
Definition: logging.cpp:178
std::list< std::string > m_msgs_before_open
Definition: logging.h:78
bool DefaultShrinkDebugFile() const
Definition: logging.cpp:87
FILE * m_fileout
Definition: logging.h:76
void LogPrintStr(const std::string &str)
Send a string to the log output.
Definition: logging.cpp:208
fs::path m_file_path
Definition: logging.h:99
void EnableCategory(LogFlags flag)
Definition: logging.cpp:56
std::mutex m_file_mutex
Definition: logging.h:77
void ShrinkDebugFile()
Definition: logging.cpp:241
void DisableCategory(LogFlags flag)
Definition: logging.cpp:69
virtual ~CBatchedLogger()
Definition: logging.cpp:274
void Flush()
Definition: logging.cpp:279
CBatchedLogger(BCLog::Logger *_logger, BCLog::LogFlags _category, const std::string &_header)
PIVX.
Definition: logging.cpp:268
std::string header
Definition: logging.h:176
BCLog::Logger * logger
Definition: logging.h:174
std::string msg
Definition: logging.h:177
std::vector< CLogCategoryActive > ListActiveLogCategories()
Returns a vector of the active log categories.
Definition: logging.cpp:163
const CLogCategoryDesc LogCategories[]
Definition: logging.cpp:98
BCLog::Logger *const g_logger
NOTE: the logger instances is leaked on exit.
Definition: logging.cpp:26
bool GetLogCategory(BCLog::LogFlags &flag, const std::string &str)
Return true if str parses as a log category and set the flag.
Definition: logging.cpp:133
bool fLogIPs
Definition: logging.cpp:28
const char *const DEFAULT_DEBUGLOGFILE
Definition: logging.cpp:11
std::string ListLogCategories()
Returns a string with the supported log categories.
Definition: logging.cpp:148
LogFlags
Definition: logging.h:39
@ ESTIMATEFEE
Definition: logging.h:49
@ MNBUDGET
Definition: logging.h:60
@ COINDB
Definition: logging.h:55
@ MASTERNODE
Definition: logging.h:59
@ REINDEX
Definition: logging.h:51
@ NET_MN
Definition: logging.h:67
@ DB
Definition: logging.h:47
@ ADDRMAN
Definition: logging.h:50
@ MNPING
Definition: logging.h:61
@ ALL
Definition: logging.h:70
@ RPC
Definition: logging.h:48
@ BENCHMARK
Definition: logging.h:45
@ HTTP
Definition: logging.h:44
@ LEVELDB
Definition: logging.h:57
@ NONE
Definition: logging.h:40
@ VALIDATION
Definition: logging.h:65
@ MEMPOOLREJ
Definition: logging.h:53
@ SPORKS
Definition: logging.h:64
@ STAKING
Definition: logging.h:58
@ TOR
Definition: logging.h:42
@ LIBEVENT
Definition: logging.h:54
@ CHAINLOCKS
Definition: logging.h:69
@ LLMQ
Definition: logging.h:66
@ DKG
Definition: logging.h:68
@ PROXY
Definition: logging.h:52
@ ZMQ
Definition: logging.h:46
@ MEMPOOL
Definition: logging.h:43
@ SAPLING
Definition: logging.h:63
@ LEGACYZC
Definition: logging.h:62
@ NET
Definition: logging.h:41
@ QT
Definition: logging.h:56
FILE * fopen(const fs::path &p, const char *mode)
Definition: fs.cpp:23
std::string category
Definition: logging.h:34
BCLog::LogFlags flag
Definition: logging.cpp:94
std::string category
Definition: logging.cpp:95
#define strprintf
Definition: tinyformat.h:1056
int64_t GetTimeMicros()
Returns the system time (not mockable)
Definition: utiltime.cpp:74
int64_t GetMockTime()
For testing.
Definition: utiltime.cpp:56
std::string FormatISO8601DateTime(int64_t nTime)
ISO 8601 formatting is preferred.
Definition: utiltime.cpp:102