diff --git a/src/logging.h b/src/logging.h index de9ea78294e..c1034a1f208 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; @@ -168,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/miner.cpp b/src/miner.cpp index 53da2f51bef..61c857021b8 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 445985c498e..1ad8d066d8b 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())