LCOV - code coverage report
Current view: top level - src - logging.cpp (source / functions) Hit Total Coverage
Test: coverage.lcov Lines: 143 185 77.3 %
Date: 2021-06-29 14:35:33 Functions: 15 16 93.8 %
Legend: Modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed

Not modified by patch:
Lines: hit not hit | Branches: + taken - not taken # not executed
Branches: 58 82 70.7 %

           Branch data     Line data    Source code
#       1                 :            : // Copyright (c) 2009-2010 Satoshi Nakamoto
#       2                 :            : // Copyright (c) 2009-2020 The Bitcoin Core developers
#       3                 :            : // Distributed under the MIT software license, see the accompanying
#       4                 :            : // file COPYING or http://www.opensource.org/licenses/mit-license.php.
#       5                 :            : 
#       6                 :            : #include <logging.h>
#       7                 :            : #include <util/threadnames.h>
#       8                 :            : #include <util/string.h>
#       9                 :            : #include <util/time.h>
#      10                 :            : 
#      11                 :            : #include <mutex>
#      12                 :            : 
#      13                 :            : const char * const DEFAULT_DEBUGLOGFILE = "debug.log";
#      14                 :            : 
#      15                 :            : BCLog::Logger& LogInstance()
#      16                 :   12095813 : {
#      17                 :            : /**
#      18                 :            :  * NOTE: the logger instances is leaked on exit. This is ugly, but will be
#      19                 :            :  * cleaned up by the OS/libc. Defining a logger as a global object doesn't work
#      20                 :            :  * since the order of destruction of static/global objects is undefined.
#      21                 :            :  * Consider if the logger gets destroyed, and then some later destructor calls
#      22                 :            :  * LogPrintf, maybe indirectly, and you get a core dump at shutdown trying to
#      23                 :            :  * access the logger. When the shutdown sequence is fully audited and tested,
#      24                 :            :  * explicit destruction of these objects can be implemented by changing this
#      25                 :            :  * from a raw pointer to a std::unique_ptr.
#      26                 :            :  * Since the ~Logger() destructor is never called, the Logger class and all
#      27                 :            :  * its subclasses must have implicitly-defined destructors.
#      28                 :            :  *
#      29                 :            :  * This method of initialization was originally introduced in
#      30                 :            :  * ee3374234c60aba2cc4c5cd5cac1c0aefc2d817c.
#      31                 :            :  */
#      32                 :   12095813 :     static BCLog::Logger* g_logger{new BCLog::Logger()};
#      33                 :   12095813 :     return *g_logger;
#      34                 :   12095813 : }
#      35                 :            : 
#      36                 :            : bool fLogIPs = DEFAULT_LOGIPS;
#      37                 :            : 
#      38                 :            : static int FileWriteStr(const std::string &str, FILE *fp)
#      39                 :    4159549 : {
#      40                 :    4159549 :     return fwrite(str.data(), 1, str.size(), fp);
#      41                 :    4159549 : }
#      42                 :            : 
#      43                 :            : bool BCLog::Logger::StartLogging()
#      44                 :       1511 : {
#      45                 :       1511 :     StdLockGuard scoped_lock(m_cs);
#      46                 :            : 
#      47                 :       1511 :     assert(m_buffering);
#      48                 :       1511 :     assert(m_fileout == nullptr);
#      49                 :            : 
#      50         [ +  + ]:       1511 :     if (m_print_to_file) {
#      51                 :       1510 :         assert(!m_file_path.empty());
#      52                 :       1510 :         m_fileout = fsbridge::fopen(m_file_path, "a");
#      53         [ +  + ]:       1510 :         if (!m_fileout) {
#      54                 :          2 :             return false;
#      55                 :          2 :         }
#      56                 :            : 
#      57                 :       1508 :         setbuf(m_fileout, nullptr); // unbuffered
#      58                 :            : 
#      59                 :            :         // Add newlines to the logfile to distinguish this execution from the
#      60                 :            :         // last one.
#      61                 :       1508 :         FileWriteStr("\n\n\n\n\n", m_fileout);
#      62                 :       1508 :     }
#      63                 :            : 
#      64                 :            :     // dump buffered messages from before we opened the log
#      65                 :       1511 :     m_buffering = false;
#      66         [ +  + ]:       9587 :     while (!m_msgs_before_open.empty()) {
#      67                 :       8078 :         const std::string& s = m_msgs_before_open.front();
#      68                 :            : 
#      69         [ +  + ]:       8078 :         if (m_print_to_file) FileWriteStr(s, m_fileout);
#      70         [ -  + ]:       8078 :         if (m_print_to_console) fwrite(s.data(), 1, s.size(), stdout);
#      71         [ +  + ]:       8078 :         for (const auto& cb : m_print_callbacks) {
#      72                 :       3392 :             cb(s);
#      73                 :       3392 :         }
#      74                 :            : 
#      75                 :       8078 :         m_msgs_before_open.pop_front();
#      76                 :       8078 :     }
#      77         [ -  + ]:       1509 :     if (m_print_to_console) fflush(stdout);
#      78                 :            : 
#      79                 :       1509 :     return true;
#      80                 :       1511 : }
#      81                 :            : 
#      82                 :            : void BCLog::Logger::DisconnectTestLogger()
#      83                 :        847 : {
#      84                 :        847 :     StdLockGuard scoped_lock(m_cs);
#      85                 :        847 :     m_buffering = true;
#      86         [ +  - ]:        847 :     if (m_fileout != nullptr) fclose(m_fileout);
#      87                 :        847 :     m_fileout = nullptr;
#      88                 :        847 :     m_print_callbacks.clear();
#      89                 :        847 : }
#      90                 :            : 
#      91                 :            : void BCLog::Logger::EnableCategory(BCLog::LogFlags flag)
#      92                 :       1515 : {
#      93                 :       1515 :     m_categories |= flag;
#      94                 :       1515 : }
#      95                 :            : 
#      96                 :            : bool BCLog::Logger::EnableCategory(const std::string& str)
#      97                 :       1515 : {
#      98                 :       1515 :     BCLog::LogFlags flag;
#      99         [ -  + ]:       1515 :     if (!GetLogCategory(flag, str)) return false;
#     100                 :       1515 :     EnableCategory(flag);
#     101                 :       1515 :     return true;
#     102                 :       1515 : }
#     103                 :            : 
#     104                 :            : void BCLog::Logger::DisableCategory(BCLog::LogFlags flag)
#     105                 :       3029 : {
#     106                 :       3029 :     m_categories &= ~flag;
#     107                 :       3029 : }
#     108                 :            : 
#     109                 :            : bool BCLog::Logger::DisableCategory(const std::string& str)
#     110                 :       3029 : {
#     111                 :       3029 :     BCLog::LogFlags flag;
#     112         [ -  + ]:       3029 :     if (!GetLogCategory(flag, str)) return false;
#     113                 :       3029 :     DisableCategory(flag);
#     114                 :       3029 :     return true;
#     115                 :       3029 : }
#     116                 :            : 
#     117                 :            : bool BCLog::Logger::WillLogCategory(BCLog::LogFlags category) const
#     118                 :    3807351 : {
#     119                 :    3807351 :     return (m_categories.load(std::memory_order_relaxed) & category) != 0;
#     120                 :    3807351 : }
#     121                 :            : 
#     122                 :            : bool BCLog::Logger::DefaultShrinkDebugFile() const
#     123                 :        662 : {
#     124                 :        662 :     return m_categories == BCLog::NONE;
#     125                 :        662 : }
#     126                 :            : 
#     127                 :            : struct CLogCategoryDesc
#     128                 :            : {
#     129                 :            :     BCLog::LogFlags flag;
#     130                 :            :     std::string category;
#     131                 :            : };
#     132                 :            : 
#     133                 :            : const CLogCategoryDesc LogCategories[] =
#     134                 :            : {
#     135                 :            :     {BCLog::NONE, "0"},
#     136                 :            :     {BCLog::NONE, "none"},
#     137                 :            :     {BCLog::NET, "net"},
#     138                 :            :     {BCLog::TOR, "tor"},
#     139                 :            :     {BCLog::MEMPOOL, "mempool"},
#     140                 :            :     {BCLog::HTTP, "http"},
#     141                 :            :     {BCLog::BENCH, "bench"},
#     142                 :            :     {BCLog::ZMQ, "zmq"},
#     143                 :            :     {BCLog::WALLETDB, "walletdb"},
#     144                 :            :     {BCLog::RPC, "rpc"},
#     145                 :            :     {BCLog::ESTIMATEFEE, "estimatefee"},
#     146                 :            :     {BCLog::ADDRMAN, "addrman"},
#     147                 :            :     {BCLog::SELECTCOINS, "selectcoins"},
#     148                 :            :     {BCLog::REINDEX, "reindex"},
#     149                 :            :     {BCLog::CMPCTBLOCK, "cmpctblock"},
#     150                 :            :     {BCLog::RAND, "rand"},
#     151                 :            :     {BCLog::PRUNE, "prune"},
#     152                 :            :     {BCLog::PROXY, "proxy"},
#     153                 :            :     {BCLog::MEMPOOLREJ, "mempoolrej"},
#     154                 :            :     {BCLog::LIBEVENT, "libevent"},
#     155                 :            :     {BCLog::COINDB, "coindb"},
#     156                 :            :     {BCLog::QT, "qt"},
#     157                 :            :     {BCLog::LEVELDB, "leveldb"},
#     158                 :            :     {BCLog::VALIDATION, "validation"},
#     159                 :            :     {BCLog::I2P, "i2p"},
#     160                 :            :     {BCLog::IPC, "ipc"},
#     161                 :            :     {BCLog::ALL, "1"},
#     162                 :            :     {BCLog::ALL, "all"},
#     163                 :            : };
#     164                 :            : 
#     165                 :            : bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str)
#     166                 :       4544 : {
#     167         [ +  + ]:       4544 :     if (str == "") {
#     168                 :       1514 :         flag = BCLog::ALL;
#     169                 :       1514 :         return true;
#     170                 :       1514 :     }
#     171         [ +  - ]:      65146 :     for (const CLogCategoryDesc& category_desc : LogCategories) {
#     172         [ +  + ]:      65146 :         if (category_desc.category == str) {
#     173                 :       3030 :             flag = category_desc.flag;
#     174                 :       3030 :             return true;
#     175                 :       3030 :         }
#     176                 :      65146 :     }
#     177                 :       3030 :     return false;
#     178                 :       3030 : }
#     179                 :            : 
#     180                 :            : std::vector<LogCategory> BCLog::Logger::LogCategoriesList() const
#     181                 :       2878 : {
#     182                 :       2878 :     std::vector<LogCategory> ret;
#     183         [ +  + ]:      80584 :     for (const CLogCategoryDesc& category_desc : LogCategories) {
#     184                 :            :         // Omit the special cases.
#     185 [ +  + ][ +  + ]:      80584 :         if (category_desc.flag != BCLog::NONE && category_desc.flag != BCLog::ALL) {
#     186                 :      69072 :             LogCategory catActive;
#     187                 :      69072 :             catActive.category = category_desc.category;
#     188                 :      69072 :             catActive.active = WillLogCategory(category_desc.flag);
#     189                 :      69072 :             ret.push_back(catActive);
#     190                 :      69072 :         }
#     191                 :      80584 :     }
#     192                 :       2878 :     return ret;
#     193                 :       2878 : }
#     194                 :            : 
#     195                 :            : std::string BCLog::Logger::LogTimestampStr(const std::string& str)
#     196                 :    4167906 : {
#     197                 :    4167906 :     std::string strStamped;
#     198                 :            : 
#     199         [ -  + ]:    4167906 :     if (!m_log_timestamps)
#     200                 :          0 :         return str;
#     201                 :            : 
#     202         [ +  + ]:    4167906 :     if (m_started_new_line) {
#     203                 :    4054897 :         int64_t nTimeMicros = GetTimeMicros();
#     204                 :    4054897 :         strStamped = FormatISO8601DateTime(nTimeMicros/1000000);
#     205         [ +  + ]:    4054897 :         if (m_log_time_micros) {
#     206                 :    4045068 :             strStamped.pop_back();
#     207                 :    4045068 :             strStamped += strprintf(".%06dZ", nTimeMicros%1000000);
#     208                 :    4045068 :         }
#     209                 :    4054897 :         std::chrono::seconds mocktime = GetMockTime();
#     210         [ +  + ]:    4054897 :         if (mocktime > 0s) {
#     211                 :     213840 :             strStamped += " (mocktime: " + FormatISO8601DateTime(count_seconds(mocktime)) + ")";
#     212                 :     213840 :         }
#     213                 :    4054897 :         strStamped += ' ' + str;
#     214                 :    4054897 :     } else
#     215                 :     113009 :         strStamped = str;
#     216                 :            : 
#     217                 :    4167906 :     return strStamped;
#     218                 :    4167906 : }
#     219                 :            : 
#     220                 :            : namespace BCLog {
#     221                 :            :     /** Belts and suspenders: make sure outgoing log messages don't contain
#     222                 :            :      * potentially suspicious characters, such as terminal control codes.
#     223                 :            :      *
#     224                 :            :      * This escapes control characters except newline ('\n') in C syntax.
#     225                 :            :      * It escapes instead of removes them to still allow for troubleshooting
#     226                 :            :      * issues where they accidentally end up in strings.
#     227                 :            :      */
#     228                 :    4167910 :     std::string LogEscapeMessage(const std::string& str) {
#     229                 :    4167910 :         std::string ret;
#     230         [ +  + ]:  300703378 :         for (char ch_in : str) {
#     231                 :  300703378 :             uint8_t ch = (uint8_t)ch_in;
#     232 [ +  + ][ +  + ]:  300703378 :             if ((ch >= 32 || ch == '\n') && ch != '\x7f') {
#                 [ +  + ]
#     233                 :  300701297 :                 ret += ch_in;
#     234                 :  300701297 :             } else {
#     235                 :       2081 :                 ret += strprintf("\\x%02x", ch);
#     236                 :       2081 :             }
#     237                 :  300703378 :         }
#     238                 :    4167910 :         return ret;
#     239                 :    4167910 :     }
#     240                 :            : }
#     241                 :            : 
#     242                 :            : void BCLog::Logger::LogPrintStr(const std::string& str, const std::string& logging_function, const std::string& source_file, const int source_line)
#     243                 :    4167752 : {
#     244                 :    4167752 :     StdLockGuard scoped_lock(m_cs);
#     245                 :    4167752 :     std::string str_prefixed = LogEscapeMessage(str);
#     246                 :            : 
#     247 [ +  + ][ +  + ]:    4167752 :     if (m_log_sourcelocations && m_started_new_line) {
#     248                 :    4045068 :         str_prefixed.insert(0, "[" + RemovePrefix(source_file, "./") + ":" + ToString(source_line) + "] [" + logging_function + "] ");
#     249                 :    4045068 :     }
#     250                 :            : 
#     251 [ -  + ][ #  # ]:    4167752 :     if (m_log_threadnames && m_started_new_line) {
#     252                 :          0 :         str_prefixed.insert(0, "[" + util::ThreadGetInternalName() + "] ");
#     253                 :          0 :     }
#     254                 :            : 
#     255                 :    4167752 :     str_prefixed = LogTimestampStr(str_prefixed);
#     256                 :            : 
#     257 [ +  + ][ +  + ]:    4167906 :     m_started_new_line = !str.empty() && str[str.size()-1] == '\n';
#     258                 :            : 
#     259         [ +  + ]:    4167752 :     if (m_buffering) {
#     260                 :            :         // buffer if we haven't started logging yet
#     261                 :      17936 :         m_msgs_before_open.push_back(str_prefixed);
#     262                 :      17936 :         return;
#     263                 :      17936 :     }
#     264                 :            : 
#     265         [ -  + ]:    4149816 :     if (m_print_to_console) {
#     266                 :            :         // print to console
#     267                 :          0 :         fwrite(str_prefixed.data(), 1, str_prefixed.size(), stdout);
#     268                 :          0 :         fflush(stdout);
#     269                 :          0 :     }
#     270         [ +  + ]:    4149816 :     for (const auto& cb : m_print_callbacks) {
#     271                 :    1578108 :         cb(str_prefixed);
#     272                 :    1578108 :     }
#     273         [ +  + ]:    4149970 :     if (m_print_to_file) {
#     274                 :    4149970 :         assert(m_fileout != nullptr);
#     275                 :            : 
#     276                 :            :         // reopen the log file, if requested
#     277         [ -  + ]:    4149970 :         if (m_reopen_file) {
#     278                 :          0 :             m_reopen_file = false;
#     279                 :          0 :             FILE* new_fileout = fsbridge::fopen(m_file_path, "a");
#     280         [ #  # ]:          0 :             if (new_fileout) {
#     281                 :          0 :                 setbuf(new_fileout, nullptr); // unbuffered
#     282                 :          0 :                 fclose(m_fileout);
#     283                 :          0 :                 m_fileout = new_fileout;
#     284                 :          0 :             }
#     285                 :          0 :         }
#     286                 :    4149970 :         FileWriteStr(str_prefixed, m_fileout);
#     287                 :    4149970 :     }
#     288                 :    4149816 : }
#     289                 :            : 
#     290                 :            : void BCLog::Logger::ShrinkDebugFile()
#     291                 :          0 : {
#     292                 :            :     // Amount of debug.log to save at end when shrinking (must fit in memory)
#     293                 :          0 :     constexpr size_t RECENT_DEBUG_HISTORY_SIZE = 10 * 1000000;
#     294                 :            : 
#     295                 :          0 :     assert(!m_file_path.empty());
#     296                 :            : 
#     297                 :            :     // Scroll debug.log if it's getting too big
#     298                 :          0 :     FILE* file = fsbridge::fopen(m_file_path, "r");
#     299                 :            : 
#     300                 :            :     // Special files (e.g. device nodes) may not have a size.
#     301                 :          0 :     size_t log_size = 0;
#     302                 :          0 :     try {
#     303                 :          0 :         log_size = fs::file_size(m_file_path);
#     304                 :          0 :     } catch (const fs::filesystem_error&) {}
#     305                 :            : 
#     306                 :            :     // If debug.log file is more than 10% bigger the RECENT_DEBUG_HISTORY_SIZE
#     307                 :            :     // trim it down by saving only the last RECENT_DEBUG_HISTORY_SIZE bytes
#     308 [ #  # ][ #  # ]:          0 :     if (file && log_size > 11 * (RECENT_DEBUG_HISTORY_SIZE / 10))
#     309                 :          0 :     {
#     310                 :            :         // Restart the file with some of the end
#     311                 :          0 :         std::vector<char> vch(RECENT_DEBUG_HISTORY_SIZE, 0);
#     312         [ #  # ]:          0 :         if (fseek(file, -((long)vch.size()), SEEK_END)) {
#     313                 :          0 :             LogPrintf("Failed to shrink debug log file: fseek(...) failed\n");
#     314                 :          0 :             fclose(file);
#     315                 :          0 :             return;
#     316                 :          0 :         }
#     317                 :          0 :         int nBytes = fread(vch.data(), 1, vch.size(), file);
#     318                 :          0 :         fclose(file);
#     319                 :            : 
#     320                 :          0 :         file = fsbridge::fopen(m_file_path, "w");
#     321         [ #  # ]:          0 :         if (file)
#     322                 :          0 :         {
#     323                 :          0 :             fwrite(vch.data(), 1, nBytes, file);
#     324                 :          0 :             fclose(file);
#     325                 :          0 :         }
#     326                 :          0 :     }
#     327         [ #  # ]:          0 :     else if (file != nullptr)
#     328                 :          0 :         fclose(file);
#     329                 :          0 : }

Generated by: LCOV version 1.14