Skip to content

Instantly share code, notes, and snippets.

@zwim
Last active May 15, 2023 17:21
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save zwim/9896498977c8eeb679b516059e752de7 to your computer and use it in GitHub Desktop.
Save zwim/9896498977c8eeb679b516059e752de7 to your computer and use it in GitHub Desktop.
KOReader user patch, to limit the crash.log's filesize during run
-- A KOReader patch for limiting the crash.log file size during run (and not only on KOReader start)
-- The menu entry can be found in Filemanager: Settings > More tools > Developer options > Limit log file size
-- Version 0.2
-- Kobo os.execute("truncate") is not available -> os.execute("busybox truncate")
-- Version 0.3
-- onSuspend and onResume work now
-- Version 0.4
-- unschedule tasks in onClose
-- Version 0.5
-- don't use onClose, but onExit (unschedule and close)
local FFIUtil = require("ffi/util")
local UIManager = require("ui/uimanager")
local _ = require("gettext")
local T = FFIUtil.template
local WidgetContainer = require("ui/widget/container/widgetcontainer")
local datetime = require("datetime")
local lfs = require("libs/libkoreader-lfs")
local logger = require("logger")
local util = require("util")
local truncate_cmd
if os.execute("which truncate") == 0 then
truncate_cmd = "truncate -s 0 crash.log"
elseif os.execute("busybox truncate --help") == 0 then
truncate_cmd = "busybox truncate -s 0 crash.log"
else
logger.dbg("Crashlog: truncate command not found!")
return
end
local function crashlog_exists()
return lfs.attributes("crash.log", "mode") == "file"
end
if not crashlog_exists() then
logger.dbg("Crashlog: crash.log does not exist on this device.")
return
end
--- crash.log handling ---
local CRASHLOG_MAXSIZE = 500000 -- 500000 is the maximum filesize in koreader.sh startup
local CRASHLOG_OVERCOMMIT_FACTOR = 2.5 -- factor the file size can be overcomitted, before trimming should happen during KOReader running
local MINIMAL_TRIM_INTERVAL_S = 5*60 -- should be at least > a few minutes
local CrashLog = WidgetContainer:extend{
name = "limit_crashlog",
}
function CrashLog:init()
self:maybeSchedule()
end
function CrashLog:exists()
return crashlog_exists()
end
function CrashLog:size()
return lfs.attributes("crash.log", "size")
end
--- Trim the crash.log file
function CrashLog:trim()
if not CrashLog.exists() then
return
end
local crashlog_size = CrashLog:size()
logger.dbg("Crashlog: original filesize", util.getFriendlySize(crashlog_size))
if crashlog_size > CRASHLOG_MAXSIZE * CRASHLOG_OVERCOMMIT_FACTOR then
if os.execute("tail -c 500000 crash.log > crash.log.tail ") ~= 0 then return end
if os.execute(truncate_cmd) ~= 0 then return end
if os.execute("echo '... trimmed ...' >> crash.log") ~= 0 then return end
if os.execute("cat crash.log.tail >> crash.log") ~= 0 then return end
if os.execute("rm crash.log.tail") ~= 0 then return end
if os.execute("sync") ~= 0 then return end
logger.dbg("Crashlog: trimmed filesize", util.getFriendlySize(CrashLog:size()))
end
end
--- Trim the logfile and schedule the next trim if necessary
-- @number time_s if >= MINIMA_TRIM_INTERVAL_S then trim and schedule, else unschedule
function CrashLog:maybeSchedule(time_s)
local schedule_time_s = time_s or G_reader_settings:readSetting("crashlog_autotrim_time_s", -1)
if schedule_time_s >= MINIMAL_TRIM_INTERVAL_S then -- don't schedule, when time is within a minute
self:trim()
UIManager:scheduleIn(schedule_time_s, self.maybeSchedule, self)
else
UIManager:unschedule(self.maybeSchedule)
end
end
function CrashLog:onSuspend()
logger.dbg("Crashlog: onSuspend")
if G_reader_settings:readSetting("crashlog_autotrim_time_s", -1) >= 0 then
self:trim()
self:maybeSchedule(0)
end
end
function CrashLog:onResume()
logger.dbg("Crashlog: onResume")
self:maybeSchedule()
end
function CrashLog:onExit()
logger.dbg("Crashlog: onExit")
UIManager:unschedule(self.maybeSchedule)
UIManager:close(self)
end
--- monkey patch the developer menu ---
local FileManagerMenu = require("apps/filemanager/filemanagermenu")
local setUpdateItemTable_orig = FileManagerMenu.setUpdateItemTable
FileManagerMenu.setUpdateItemTable = function(self)
setUpdateItemTable_orig(self)
local function find_table(table, id)
for i, v in pairs(table) do
if v.id == id then
return v, true
end
end
end
local table_to_insert, found = find_table(self.tab_item_table, "tools")
if not found then return end
table_to_insert, found = find_table(table_to_insert, "more_tools")
if not found then return end
table_to_insert, found = find_table(table_to_insert.sub_item_table, "developer_options")
if not found then return end
table.insert(table_to_insert.sub_item_table, {
text_func = function()
local crashlog_autotrim_time_s = G_reader_settings:readSetting("crashlog_autotrim_time_s", -1)
local size = util.getFriendlySize(CrashLog:size())
if crashlog_autotrim_time_s < 0 then
return T(_("Limit log file size (%1)"), size)
elseif crashlog_autotrim_time_s == 0 then
return T(_("Limit log file size (%1, %2)"), size, "only on suspend")
else
local time_string = datetime.secondsToClockDuration("letters", crashlog_autotrim_time_s, true, true, true)
return T(_("Limit log file size (%1, %2)"), size, time_string)
end
end,
enabled_func = function()
return CrashLog:exists()
end,
checked_func = function()
return G_reader_settings:readSetting("crashlog_autotrim_time_s", -1) >= 0
end,
callback = function()
local crashlog_autotrim_time_s = G_reader_settings:readSetting("crashlog_autotrim_time_s")
local time_table_s = {6*3600, 3600, 30*60, 15*60, 0, -1}
if crashlog_autotrim_time_s >= time_table_s[1] then
crashlog_autotrim_time_s = -1
else
for i = 2, #time_table_s do
if crashlog_autotrim_time_s >= time_table_s[i] then
crashlog_autotrim_time_s = time_table_s[i-1]
break
end
end
end
G_reader_settings:saveSetting("crashlog_autotrim_time_s", crashlog_autotrim_time_s)
CrashLog:maybeSchedule()
end,
keep_menu_open = true,
})
end
--- initialisations
UIManager:show(CrashLog:new())
@zwim
Copy link
Author

zwim commented Mar 21, 2023

CHANGELOG

Version 0.5
don't use onClose, but onExit (unschedule and close)

Version 0.4
onSuspend and onResume work now

Version 0.3
unschedule tasks in onClose

Version 0.2
os.execute("truncate") is not available on Kobo, so check if truncate is available, if not try to use busybox truncate
works on emulator and Kobo

Version 0.1:
initial commit; works on the emulator

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment