diff --git a/src/logging.cpp b/src/logging.cpp index 3ae0fc7465..367f898151 100644 --- a/src/logging.cpp +++ b/src/logging.cpp @@ -154,6 +154,7 @@ const CLogCategoryDesc LogCategories[] = {BCLog::SPV, "spv"}, {BCLog::ORACLE, "oracle"}, {BCLog::LOAN, "loan"}, + {BCLog::ACCOUNTCHANGE, "accountchange"}, {BCLog::ALL, "1"}, {BCLog::ALL, "all"}, }; diff --git a/src/logging.h b/src/logging.h index 362e859bc0..c1034a1f20 100644 --- a/src/logging.h +++ b/src/logging.h @@ -8,6 +8,7 @@ #include #include +#include #include #include @@ -15,6 +16,7 @@ #include #include #include +#include static const bool DEFAULT_LOGTIMEMICROS = false; static const bool DEFAULT_LOGIPS = false; @@ -32,33 +34,34 @@ struct CLogCategoryActive namespace BCLog { enum LogFlags : uint32_t { - NONE = 0, - NET = (1 << 0), - TOR = (1 << 1), - MEMPOOL = (1 << 2), - HTTP = (1 << 3), - BENCH = (1 << 4), - ZMQ = (1 << 5), - DB = (1 << 6), - RPC = (1 << 7), - ESTIMATEFEE = (1 << 8), - ADDRMAN = (1 << 9), - SELECTCOINS = (1 << 10), - REINDEX = (1 << 11), - CMPCTBLOCK = (1 << 12), - RAND = (1 << 13), - PRUNE = (1 << 14), - PROXY = (1 << 15), - MEMPOOLREJ = (1 << 16), - LIBEVENT = (1 << 17), - COINDB = (1 << 18), - LEVELDB = (1 << 20), - STAKING = (1 << 21), - ANCHORING = (1 << 22), - SPV = (1 << 23), - ORACLE = (1 << 24), - LOAN = (1 << 25), - ALL = ~(uint32_t)0, + NONE = 0, + NET = (1 << 0), + TOR = (1 << 1), + MEMPOOL = (1 << 2), + HTTP = (1 << 3), + BENCH = (1 << 4), + ZMQ = (1 << 5), + DB = (1 << 6), + RPC = (1 << 7), + ESTIMATEFEE = (1 << 8), + ADDRMAN = (1 << 9), + SELECTCOINS = (1 << 10), + REINDEX = (1 << 11), + CMPCTBLOCK = (1 << 12), + RAND = (1 << 13), + PRUNE = (1 << 14), + PROXY = (1 << 15), + MEMPOOLREJ = (1 << 16), + LIBEVENT = (1 << 17), + COINDB = (1 << 18), + LEVELDB = (1 << 20), + STAKING = (1 << 21), + ANCHORING = (1 << 22), + SPV = (1 << 23), + ORACLE = (1 << 24), + LOAN = (1 << 25), + ACCOUNTCHANGE = (1 << 26), + ALL = ~(uint32_t)0, }; class Logger @@ -167,4 +170,35 @@ static inline void LogPrint(const BCLog::LogFlags& category, const Args&... args } } +/** Implementation that logs at most every x milliseconds. If the category is enabled, it does not time throttle */ +template +static inline void LogPrintCategoryOrThreadThrottled(const BCLog::LogFlags& category, std::string message_key, uint64_t milliseconds, const Args&... args) +{ + // Map containing pairs of message key and timestamp of last log + // In case different threads use the same message key, use thread_local + thread_local std::unordered_map last_log_timestamps; + + // Log directly if category is enabled.. + if (LogAcceptCategory((category))) { + LogPrintf(args...); + } else { // .. and otherwise time throttle logging + + int64_t current_time = GetTimeMillis(); + auto it = last_log_timestamps.find(message_key); + + if (it != last_log_timestamps.end()) { + if ((current_time - it->second) > milliseconds) + { + LogPrintf(args...); + it->second = current_time; + } + } + else { + // No entry yet -> log directly and save timestamp + last_log_timestamps.insert(std::make_pair(message_key, current_time)); + LogPrintf(args...); + } + } +} + #endif // DEFI_LOGGING_H diff --git a/src/masternodes/accountshistory.cpp b/src/masternodes/accountshistory.cpp index f084e35327..f28c6f1929 100644 --- a/src/masternodes/accountshistory.cpp +++ b/src/masternodes/accountshistory.cpp @@ -151,6 +151,8 @@ void CHistoryErasers::Flush(const uint32_t height, const uint32_t txn, const uin CHistoryWriters::CHistoryWriters(CAccountHistoryStorage* historyView, CBurnHistoryStorage* burnView, CVaultHistoryStorage* vaultView) : historyView(historyView), burnView(burnView), vaultView(vaultView) {} +extern std::string ScriptToString(CScript const& script); + void CHistoryWriters::AddBalance(const CScript& owner, const CTokenAmount amount, const uint256& vaultID) { if (historyView) { @@ -188,6 +190,7 @@ void CHistoryWriters::Flush(const uint32_t height, const uint256& txid, const ui { if (historyView) { for (const auto& diff : diffs) { + LogPrint(BCLog::ACCOUNTCHANGE, "AccountChange: txid=%s addr=%s change=%s\n", txid.GetHex(), ScriptToString(diff.first), (CBalances{diff.second}.ToString())); historyView->WriteAccountHistory({diff.first, height, txn}, {txid, type, diff.second}); } } diff --git a/src/miner.cpp b/src/miner.cpp index 53da2f51be..61c857021b 100644 --- a/src/miner.cpp +++ b/src/miner.cpp @@ -9,14 +9,15 @@ #include #include #include -#include #include #include +#include #include #include #include #include #include +#include #include #include #include @@ -960,10 +961,10 @@ void ThreadStaker::operator()(std::vector args, CChainParams nMinted[arg.operatorID]++; } else if (status == Staker::Status::initWaiting) { - LogPrintf("ThreadStaker: (%s) waiting init...\n", operatorName); + LogPrintCategoryOrThreadThrottled(BCLog::STAKING, "init_waiting", 1000 * 60 * 10, "ThreadStaker: (%s) waiting init...\n", operatorName); } else if (status == Staker::Status::stakeWaiting) { - LogPrint(BCLog::STAKING, "ThreadStaker: (%s) Staked, but no kernel found yet.\n", operatorName); + LogPrintCategoryOrThreadThrottled(BCLog::STAKING, "no_kernel_found", 1000 * 60 * 10,"ThreadStaker: (%s) Staked, but no kernel found yet.\n", operatorName); } } catch (const std::runtime_error &e) { diff --git a/src/pos.cpp b/src/pos.cpp index 445985c498..1ad8d066d8 100644 --- a/src/pos.cpp +++ b/src/pos.cpp @@ -204,7 +204,7 @@ boost::optional CheckSignedBlock(const std::shared_ptr& pbl if (!CheckProofOfStake(*(CBlockHeader*)pblock.get(), pindexPrev, chainparams.GetConsensus(), pcustomcsview.get())) return {std::string{} + "proof-of-stake checking failed"}; - LogPrint(BCLog::STAKING, "new proof-of-stake block found hash: %s\n", hashBlock.GetHex()); + LogPrintf("new proof-of-stake block found hash: %s\n", hashBlock.GetHex()); // Found a solution if (pblock->hashPrevBlock != pindexPrev->GetBlockHash())