From 2cb129ae4b608afdd329be9d006044415270dd16 Mon Sep 17 00:00:00 2001 From: Xurkon Date: Sat, 6 Jun 2026 13:44:49 -0500 Subject: [PATCH] feat: add debug message throttle --- CHANGELOG.md | 1 + .../AdvancedTab/QuestieOptionsAdvanced.lua | 15 ++++ Modules/Options/QuestieOptionsDefaults.lua | 1 + Questie.lua | 13 +++ Tests/QuestieDebugThrottle_spec.lua | 86 +++++++++++++++++++ docs/changelog.html | 1 + 6 files changed, 117 insertions(+) create mode 100644 Tests/QuestieDebugThrottle_spec.lua diff --git a/CHANGELOG.md b/CHANGELOG.md index 02a7f74..0ae2644 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,7 @@ ### Performance +- **[Questie Debug - Message Throttle]** Added a live debug-message throttle so non-fatal debug output cannot spam chat faster than it can be read. The throttle is configurable in the Advanced tab and keeps fatal output separate. - **[QuestieLearner - Kill/Pin Refresh Throttling]** Debounced learner-triggered map-pin refreshes so heavy kill streaks do not redraw pins on every event. Added a maximum wait cap so batched updates still flush predictably instead of being pushed out forever by constant activity. - **[QuestieLearner - Bystander Kill Suppression]** Changed visible nearby `UNIT_DIED` handling so kills from other players can update short-lived correlation evidence without immediately running full learner injection or pin refresh work. - **[QuestieLearner - PARTY_KILL Event-Order Fix]** Fixed an edge case where a `UNIT_DIED` debounce entry could suppress a later authoritative `PARTY_KILL` for the same GUID. The debounce now tracks event type and allows the player's/group's kill event through while still suppressing true duplicates. diff --git a/Modules/Options/AdvancedTab/QuestieOptionsAdvanced.lua b/Modules/Options/AdvancedTab/QuestieOptionsAdvanced.lua index 2a77a33..1eab88a 100644 --- a/Modules/Options/AdvancedTab/QuestieOptionsAdvanced.lua +++ b/Modules/Options/AdvancedTab/QuestieOptionsAdvanced.lua @@ -794,6 +794,21 @@ function QuestieOptions.tabs.advanced:Initialize() end end, }, + debugMessageThrottle = { + type = "range", + order = 5.10, + name = function() return l10n('Debug message throttle'); end, + desc = function() return l10n('Minimum seconds between debug lines. Higher values reduce spam while keeping fatal output separate.') end, + width = "full", + min = 0, + max = 1, + step = 0.05, + disabled = function() return not (Questie.db.profile.debugEnabledPrint and Questie.db.profile.debugEnabled); end, + get = function() return Questie.db.profile.debugMessageThrottle or 0 end, + set = function(_, value) + Questie.db.profile.debugMessageThrottle = value + end, + }, compat_header = { type = "header", order = 6, diff --git a/Modules/Options/QuestieOptionsDefaults.lua b/Modules/Options/QuestieOptionsDefaults.lua index 8aa9dd1..1e3a044 100644 --- a/Modules/Options/QuestieOptionsDefaults.lua +++ b/Modules/Options/QuestieOptionsDefaults.lua @@ -98,6 +98,7 @@ function QuestieOptionsDefaults:Load() questieShutUp = false, bugWorkarounds = true, hideIconsOnContinents = false, + debugMessageThrottle = 0.15, -- Tracker Settings Tab autoTrackQuests = true, diff --git a/Questie.lua b/Questie.lua index 93e5c77..e76a5ec 100644 --- a/Questie.lua +++ b/Questie.lua @@ -1,4 +1,7 @@ local band = bit.band +local debugThrottleState = { + lastPrint = nil, +} ------------------------- --Import modules. @@ -169,6 +172,16 @@ function Questie:Debug(msgDebugLevel, ...) return end + local throttleSeconds = tonumber(Questie.db and Questie.db.profile and Questie.db.profile.debugMessageThrottle) or 0 + local now = GetTime and GetTime() or time() + if throttleSeconds > 0 and debugThrottleState.lastPrint and (now - debugThrottleState.lastPrint) < throttleSeconds then + return + end + + if throttleSeconds > 0 then + debugThrottleState.lastPrint = now + end + local prefix = "" if (band(msgDebugLevel, Questie.DEBUG_CRITICAL) ~= 0) then prefix = prefix .. "|cff00f2e6[CRITICAL]|r " end if (band(msgDebugLevel, Questie.DEBUG_ELEVATED) ~= 0) then prefix = prefix .. "|cffebf441[ELEVATED]|r " end diff --git a/Tests/QuestieDebugThrottle_spec.lua b/Tests/QuestieDebugThrottle_spec.lua new file mode 100644 index 0000000..033945e --- /dev/null +++ b/Tests/QuestieDebugThrottle_spec.lua @@ -0,0 +1,86 @@ +describe("Questie debug throttle", function() + local originalPrint + local originalGetTime + local originalImport + + before_each(function() + dofile("Tests/wow_api_mock.lua") + Questie.Print = nil + _G.IsLoggedIn = function() + return false + end + _G.C_Timer = _G.C_Timer or {} + _G.C_Timer.After = function() + end + originalImport = QuestieLoader.ImportModule + QuestieLoader.ImportModule = function(self, name) + if name == "QuestieLib" then + return { AddonPath = "" } + elseif name == "QuestieValidateGameCache" then + return { StartCheck = function() end } + end + return originalImport(self, name) + end + dofile("Questie.lua") + + originalPrint = _G.print + originalGetTime = _G.GetTime + + _G._questie_debug_lines = {} + _G.print = function(...) + local parts = {} + for i = 1, select("#", ...) do + parts[#parts + 1] = tostring(select(i, ...)) + end + table.insert(_G._questie_debug_lines, table.concat(parts, " ")) + end + end) + + after_each(function() + _G.print = originalPrint + _G.GetTime = originalGetTime + QuestieLoader.ImportModule = originalImport + _G._questie_debug_lines = nil + end) + + it("suppresses rapid debug lines until the throttle window reopens", function() + local now = 0 + _G.GetTime = function() + return now + end + + Questie.db.profile.debugEnabled = true + Questie.db.profile.debugEnabledPrint = true + Questie.db.profile.debugLevel = Questie.DEBUG_INFO + Questie.db.profile.debugMessageThrottle = 0.5 + + Questie:Debug(Questie.DEBUG_INFO, "alpha") + now = 0.1 + Questie:Debug(Questie.DEBUG_INFO, "beta") + now = 0.6 + Questie:Debug(Questie.DEBUG_INFO, "gamma") + + assert.equals(2, table.getn(_G._questie_debug_lines)) + assert.is_true(string.find(_G._questie_debug_lines[1], "alpha", 1, true) ~= nil) + assert.is_true(string.find(_G._questie_debug_lines[2], "gamma", 1, true) ~= nil) + end) + + it("throttles critical messages too because fatal output is separate", function() + local now = 0 + _G.GetTime = function() + return now + end + + Questie.db.profile.debugEnabled = true + Questie.db.profile.debugEnabledPrint = true + Questie.db.profile.debugLevel = Questie.DEBUG_INFO + Questie.DEBUG_CRITICAL + Questie.db.profile.debugMessageThrottle = 0.5 + + Questie:Debug(Questie.DEBUG_INFO, "alpha") + now = 0.1 + Questie:Debug(Questie.DEBUG_CRITICAL, "boom") + + assert.equals(1, table.getn(_G._questie_debug_lines)) + assert.is_true(string.find(_G._questie_debug_lines[1], "alpha", 1, true) ~= nil) + end) +end) diff --git a/docs/changelog.html b/docs/changelog.html index 0e4b743..069bf55 100644 --- a/docs/changelog.html +++ b/docs/changelog.html @@ -179,6 +179,7 @@

[Unreleased] — Performance Refactor Branches