LCOV - code coverage report
Current view: top level - src - logging.cpp (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 95 123 77.2 %
Date: 2025-02-23 09:33:43 Functions: 16 18 88.9 %

          Line data    Source code
       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             : 
      13             : /**
      14             :  * NOTE: the logger instances is leaked on exit. This is ugly, but will be
      15             :  * cleaned up by the OS/libc. Defining a logger as a global object doesn't work
      16             :  * since the order of destruction of static/global objects is undefined.
      17             :  * Consider if the logger gets destroyed, and then some later destructor calls
      18             :  * LogPrintf, maybe indirectly, and you get a core dump at shutdown trying to
      19             :  * access the logger. When the shutdown sequence is fully audited and tested,
      20             :  * explicit destruction of these objects can be implemented by changing this
      21             :  * from a raw pointer to a std::unique_ptr.
      22             :  *
      23             :  * This method of initialization was originally introduced in
      24             :  * bitcoin@ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
      25             :  */
      26             : BCLog::Logger* const g_logger = new BCLog::Logger();
      27             : 
      28             : bool fLogIPs = DEFAULT_LOGIPS;
      29             : 
      30             : 
      31     4393160 : static int FileWriteStr(const std::string &str, FILE *fp)
      32             : {
      33     4393160 :     return fwrite(str.data(), 1, str.size(), fp);
      34             : }
      35             : 
      36         378 : bool BCLog::Logger::OpenDebugLog()
      37             : {
      38         756 :     std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
      39             : 
      40         378 :     assert(m_fileout == nullptr);
      41         378 :     assert(!m_file_path.empty());
      42             : 
      43         378 :     m_fileout = fsbridge::fopen(m_file_path, "a");
      44         378 :     if (!m_fileout) return false;
      45             : 
      46         376 :     setbuf(m_fileout, nullptr); // unbuffered
      47             :     // dump buffered messages from before we opened the log
      48        2149 :     while (!m_msgs_before_open.empty()) {
      49        1773 :         FileWriteStr(m_msgs_before_open.front(), m_fileout);
      50        2149 :         m_msgs_before_open.pop_front();
      51             :     }
      52             : 
      53             :     return true;
      54             : }
      55             : 
      56         481 : void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)
      57             : {
      58         481 :     m_categories |= flag;
      59         481 : }
      60             : 
      61         481 : bool BCLog::Logger::EnableCategory(const std::string& str)
      62             : {
      63         481 :     BCLog::LogFlags flag;
      64         481 :     if (!GetLogCategory(flag, str)) return false;
      65         481 :     EnableCategory(flag);
      66         481 :     return true;
      67             : }
      68             : 
      69         764 : void BCLog::Logger::DisableCategory(BCLog::LogFlags flag)
      70             : {
      71         764 :     m_categories &= ~flag;
      72         764 : }
      73             : 
      74         764 : bool BCLog::Logger::DisableCategory(const std::string& str)
      75             : {
      76         764 :     BCLog::LogFlags flag;
      77         764 :     if (!GetLogCategory(flag, str)) return false;
      78         764 :     DisableCategory(flag);
      79         764 :     return true;
      80             : }
      81             : 
      82     3934310 : bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
      83             : {
      84     3934310 :     return (m_categories.load(std::memory_order_relaxed) & category) != 0;
      85             : }
      86             : 
      87         838 : bool BCLog::Logger::DefaultShrinkDebugFile() const
      88             : {
      89         838 :     return m_categories == BCLog::NONE;
      90             : }
      91             : 
      92             : struct CLogCategoryDesc
      93             : {
      94             :     BCLog::LogFlags flag;
      95             :     std::string category;
      96             : };
      97             : 
      98             : const CLogCategoryDesc LogCategories[] = {
      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        1245 : bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
     134             : {
     135        1245 :     if (str == "") {
     136         382 :         flag = BCLog::ALL;
     137         382 :         return true;
     138             :     }
     139       14520 :     for (const CLogCategoryDesc& category_desc : LogCategories) {
     140       14520 :         if (category_desc.category == str) {
     141         863 :             flag = category_desc.flag;
     142         863 :             return true;
     143             :         }
     144             :     }
     145             :     return false;
     146             : }
     147             : 
     148           1 : std::string ListLogCategories()
     149             : {
     150           1 :     std::string ret;
     151           1 :     int outcount = 0;
     152          33 :     for (const CLogCategoryDesc& category_desc : LogCategories) {
     153             :         // Omit the special cases.
     154          32 :         if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
     155          29 :             if (outcount != 0) ret += ", ";
     156          29 :             ret += category_desc.category;
     157          29 :             outcount++;
     158             :         }
     159             :     }
     160           1 :     return ret;
     161             : }
     162             : 
     163           0 : std::vector<CLogCategoryActive> ListActiveLogCategories()
     164             : {
     165           0 :     std::vector<CLogCategoryActive> ret;
     166           0 :     for (const CLogCategoryDesc& category_desc : LogCategories) {
     167             :         // Omit the special cases.
     168           0 :         if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
     169           0 :             CLogCategoryActive catActive;
     170           0 :             catActive.category = category_desc.category;
     171           0 :             catActive.active = LogAcceptCategory(category_desc.flag);
     172           0 :             ret.push_back(catActive);
     173             :         }
     174             :     }
     175           0 :     return ret;
     176             : }
     177             : 
     178     4393260 : std::string BCLog::Logger::LogTimestampStr(const std::string &str)
     179             : {
     180     8786530 :     std::string strStamped;
     181             : 
     182     4393260 :     if (!m_log_timestamps)
     183     4393260 :         return str;
     184             : 
     185     4393260 :     if (m_started_new_line) {
     186     4386590 :         int64_t nTimeMicros = GetTimeMicros();
     187     4386590 :         strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
     188     4386590 :         if (m_log_time_micros) {
     189           0 :             strStamped.pop_back();
     190           0 :             strStamped += strprintf(".%06dZ", nTimeMicros % 1000000);
     191             :         }
     192     4386590 :         int64_t mocktime = GetMockTime();
     193     4386590 :         if (mocktime) {
     194     1770770 :             strStamped += " (mocktime: " + FormatISO8601DateTime(mocktime) + ")";
     195             :         }
     196    13156800 :         strStamped += ' ' + str;
     197             :     } else
     198        6676 :         strStamped = str;
     199             : 
     200     4393260 :     if (!str.empty() && str[str.size()-1] == '\n')
     201     4386580 :         m_started_new_line = true;
     202             :     else
     203        6679 :         m_started_new_line = false;
     204             : 
     205     8786530 :     return strStamped;
     206             : }
     207             : 
     208     4393260 : void BCLog::Logger::LogPrintStr(const std::string &str)
     209             : {
     210     4393260 :     std::string strTimestamped = LogTimestampStr(str);
     211             : 
     212     4393260 :     if (m_print_to_console) {
     213             :         // print to console
     214           0 :         fwrite(strTimestamped.data(), 1, strTimestamped.size(), stdout);
     215           0 :         fflush(stdout);
     216             :     }
     217             : 
     218     4393260 :     if (m_print_to_file) {
     219     8786530 :         std::lock_guard<std::mutex> scoped_lock(m_file_mutex);
     220             : 
     221             :         // buffer if we haven't opened the log yet
     222     4393260 :         if (m_fileout == nullptr) {
     223     4393260 :             m_msgs_before_open.push_back(strTimestamped);
     224             : 
     225             :         } else {
     226             :             // reopen the log file, if requested
     227     4391390 :             if (m_reopen_file) {
     228           0 :                 m_reopen_file = false;
     229           0 :                 FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
     230           0 :                 if (new_fileout) {
     231           0 :                     setbuf(new_fileout, nullptr); // unbuffered
     232           0 :                     fclose(m_fileout);
     233           0 :                     m_fileout = new_fileout;
     234             :                 }
     235             :             }
     236     4391390 :             FileWriteStr(strTimestamped, m_fileout);
     237             :         }
     238             :     }
     239     4393260 : }
     240             : 
     241           4 : void BCLog::Logger::ShrinkDebugFile()
     242             : {
     243             :     // Amount of debug.log to save at end when shrinking (must fit in memory)
     244           4 :     constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
     245             : 
     246           4 :     assert(!m_file_path.empty());
     247             : 
     248             :     // Scroll debug.log if it's getting too big
     249           4 :     FILE* file = fsbridge::fopen(m_file_path, "r");
     250           4 :     if (file && fs::file_size(m_file_path) > RECENT_DEBUG_HISTORY_SIZE) {
     251             :         // Restart the file with some of the end
     252           0 :         std::vector<char> vch(200000, 0);
     253           0 :         fseek(file, -((long)vch.size()), SEEK_END);
     254           0 :         int nBytes = fread(vch.data(), 1, vch.size(), file);
     255           0 :         fclose(file);
     256             : 
     257           0 :         file = fsbridge::fopen(m_file_path, "w");
     258           0 :         if (file) {
     259           0 :             fwrite(vch.data(), 1, nBytes, file);
     260           0 :             fclose(file);
     261             :         }
     262           4 :     } else if (file != nullptr)
     263           0 :         fclose(file);
     264           4 : }
     265             : 
     266             : /// PIVX
     267             : 
     268        1501 : CBatchedLogger::CBatchedLogger(BCLog::Logger* _logger, BCLog::LogFlags _category, const std::string& _header) :
     269             :     logger(_logger),
     270        1501 :     accept(LogAcceptCategory(_category)),
     271        1501 :     header(_header)
     272        1501 : {}
     273             : 
     274        2327 : CBatchedLogger::~CBatchedLogger()
     275             : {
     276        1501 :     Flush();
     277        1501 : }
     278             : 
     279        1883 : void CBatchedLogger::Flush()
     280             : {
     281        1883 :     if (!accept || msg.empty()) {
     282             :         return;
     283             :     }
     284         826 :     if (logger && logger->Enabled()) {
     285         826 :         logger->LogPrintStr(strprintf("%s:\n%s", header, msg));
     286        1883 :     msg.clear();
     287             :     }
     288             : }

Generated by: LCOV version 1.14