LCOV - code coverage report
Current view: top level - src - logging.h (source / functions) Hit Total Coverage
Test: total_coverage.info Lines: 39 42 92.9 %
Date: 2020-09-26 01:30:44 Functions: 141 173 81.5 %

          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             : #ifndef BITCOIN_LOGGING_H
       7             : #define BITCOIN_LOGGING_H
       8             : 
       9             : #include <fs.h>
      10             : #include <tinyformat.h>
      11             : #include <threadsafety.h>
      12             : #include <util/string.h>
      13             : 
      14             : #include <atomic>
      15             : #include <cstdint>
      16             : #include <list>
      17             : #include <mutex>
      18             : #include <string>
      19             : #include <vector>
      20             : 
      21             : static const bool DEFAULT_LOGTIMEMICROS = false;
      22             : static const bool DEFAULT_LOGIPS        = false;
      23             : static const bool DEFAULT_LOGTIMESTAMPS = true;
      24             : static const bool DEFAULT_LOGTHREADNAMES = false;
      25             : extern const char * const DEFAULT_DEBUGLOGFILE;
      26             : 
      27             : extern bool fLogIPs;
      28             : 
      29      970800 : struct LogCategory {
      30             :     std::string category;
      31             :     bool active;
      32             : };
      33             : 
      34             : namespace BCLog {
      35             :     enum LogFlags : uint32_t {
      36             :         NONE        = 0,
      37             :         NET         = (1 <<  0),
      38             :         TOR         = (1 <<  1),
      39             :         MEMPOOL     = (1 <<  2),
      40             :         HTTP        = (1 <<  3),
      41             :         BENCH       = (1 <<  4),
      42             :         ZMQ         = (1 <<  5),
      43             :         WALLETDB    = (1 <<  6),
      44             :         RPC         = (1 <<  7),
      45             :         ESTIMATEFEE = (1 <<  8),
      46             :         ADDRMAN     = (1 <<  9),
      47             :         SELECTCOINS = (1 << 10),
      48             :         REINDEX     = (1 << 11),
      49             :         CMPCTBLOCK  = (1 << 12),
      50             :         RAND        = (1 << 13),
      51             :         PRUNE       = (1 << 14),
      52             :         PROXY       = (1 << 15),
      53             :         MEMPOOLREJ  = (1 << 16),
      54             :         LIBEVENT    = (1 << 17),
      55             :         COINDB      = (1 << 18),
      56             :         QT          = (1 << 19),
      57             :         LEVELDB     = (1 << 20),
      58             :         VALIDATION  = (1 << 21),
      59             :         ALL         = ~(uint32_t)0,
      60             :     };
      61             : 
      62        5470 :     class Logger
      63             :     {
      64             :     private:
      65             :         mutable StdMutex m_cs; // Can not use Mutex from sync.h because in debug mode it would cause a deadlock when a potential deadlock was detected
      66             : 
      67        1094 :         FILE* m_fileout GUARDED_BY(m_cs) = nullptr;
      68             :         std::list<std::string> m_msgs_before_open GUARDED_BY(m_cs);
      69        1094 :         bool m_buffering GUARDED_BY(m_cs) = true; //!< Buffer messages before logging can be started.
      70             : 
      71             :         /**
      72             :          * m_started_new_line is a state variable that will suppress printing of
      73             :          * the timestamp when multiple calls are made that don't end in a
      74             :          * newline.
      75             :          */
      76        1094 :         std::atomic_bool m_started_new_line{true};
      77             : 
      78             :         /** Log categories bitfield. */
      79        1094 :         std::atomic<uint32_t> m_categories{0};
      80             : 
      81             :         std::string LogTimestampStr(const std::string& str);
      82             : 
      83             :         /** Slots that connect to the print signal */
      84        1094 :         std::list<std::function<void(const std::string&)>> m_print_callbacks GUARDED_BY(m_cs) {};
      85             : 
      86             :     public:
      87        1094 :         bool m_print_to_console = false;
      88        1094 :         bool m_print_to_file = false;
      89             : 
      90        1094 :         bool m_log_timestamps = DEFAULT_LOGTIMESTAMPS;
      91        1094 :         bool m_log_time_micros = DEFAULT_LOGTIMEMICROS;
      92        1094 :         bool m_log_threadnames = DEFAULT_LOGTHREADNAMES;
      93             : 
      94             :         fs::path m_file_path;
      95        1094 :         std::atomic<bool> m_reopen_file{false};
      96             : 
      97             :         /** Send a string to the log output */
      98             :         void LogPrintStr(const std::string& str);
      99             : 
     100             :         /** Returns whether logs will be written to any output */
     101     2284456 :         bool Enabled() const
     102             :         {
     103     2284456 :             StdLockGuard scoped_lock(m_cs);
     104     2284456 :             return m_buffering || m_print_to_console || m_print_to_file || !m_print_callbacks.empty();
     105     2284483 :         }
     106             : 
     107             :         /** Connect a slot to the print signal and return the connection */
     108         460 :         std::list<std::function<void(const std::string&)>>::iterator PushBackCallback(std::function<void(const std::string&)> fun)
     109             :         {
     110         460 :             StdLockGuard scoped_lock(m_cs);
     111         460 :             m_print_callbacks.push_back(std::move(fun));
     112         460 :             return --m_print_callbacks.end();
     113         460 :         }
     114             : 
     115             :         /** Delete a connection */
     116           9 :         void DeleteCallback(std::list<std::function<void(const std::string&)>>::iterator it)
     117             :         {
     118           9 :             StdLockGuard scoped_lock(m_cs);
     119           9 :             m_print_callbacks.erase(it);
     120           9 :         }
     121             : 
     122             :         /** Start logging (and flush all buffered messages) */
     123             :         bool StartLogging();
     124             :         /** Only for testing */
     125             :         void DisconnectTestLogger();
     126             : 
     127             :         void ShrinkDebugFile();
     128             : 
     129          10 :         uint32_t GetCategoryMask() const { return m_categories.load(); }
     130             : 
     131             :         void EnableCategory(LogFlags flag);
     132             :         bool EnableCategory(const std::string& str);
     133             :         void DisableCategory(LogFlags flag);
     134             :         bool DisableCategory(const std::string& str);
     135             : 
     136             :         bool WillLogCategory(LogFlags category) const;
     137             :         /** Returns a vector of the log categories */
     138             :         std::vector<LogCategory> LogCategoriesList();
     139             :         /** Returns a string with the log categories */
     140        3231 :         std::string LogCategoriesString()
     141             :         {
     142       74313 :             return Join(LogCategoriesList(), ", ", [&](const LogCategory& i) { return i.category; });
     143           0 :         };
     144             : 
     145             :         bool DefaultShrinkDebugFile() const;
     146             :     };
     147             : 
     148             : } // namespace BCLog
     149             : 
     150             : BCLog::Logger& LogInstance();
     151             : 
     152             : /** Return true if log accepts specified category */
     153     2259291 : static inline bool LogAcceptCategory(BCLog::LogFlags category)
     154             : {
     155     2259291 :     return LogInstance().WillLogCategory(category);
     156             : }
     157             : 
     158             : /** Return true if str parses as a log category and set the flag */
     159             : bool GetLogCategory(BCLog::LogFlags& flag, const std::string& str);
     160             : 
     161             : // Be conservative when using LogPrintf/error or other things which
     162             : // unconditionally log to debug.log! It should not be the case that an inbound
     163             : // peer can fill up a user's disk with debug.log entries.
     164             : 
     165             : template <typename... Args>
     166     2284478 : static inline void LogPrintf(const char* fmt, const Args&... args)
     167             : {
     168     2284478 :     if (LogInstance().Enabled()) {
     169     2262804 :         std::string log_msg;
     170             :         try {
     171     2262804 :             log_msg = tfm::format(fmt, args...);
     172     2262764 :         } catch (tinyformat::format_error& fmterr) {
     173             :             /* Original format string will have newline so don't add one here */
     174           0 :             log_msg = "Error \"" + std::string(fmterr.what()) + "\" while formatting log message: " + fmt;
     175           0 :         }
     176     2262756 :         LogInstance().LogPrintStr(log_msg);
     177     2262804 :     }
     178     2284483 : }
     179             : 
     180             : // Use a macro instead of a function for conditional logging to prevent
     181             : // evaluating arguments when logging for the category is not enabled.
     182             : #define LogPrint(category, ...)              \
     183             :     do {                                     \
     184             :         if (LogAcceptCategory((category))) { \
     185             :             LogPrintf(__VA_ARGS__);          \
     186             :         }                                    \
     187             :     } while (0)
     188             : 
     189             : #endif // BITCOIN_LOGGING_H

Generated by: LCOV version 1.15