1
0
mirror of https://github.com/Refactorio/RedMew.git synced 2025-03-17 21:08:08 +02:00

Add error_logging

This commit is contained in:
plague006 2019-02-24 20:04:19 -05:00 committed by Matthew Heguy
parent 12557f8102
commit 2428a93154
6 changed files with 121 additions and 10 deletions

View File

@ -6,6 +6,7 @@ local Event = require 'utils.event'
local Game = require 'utils.game'
local Timestamp = require 'utils.timestamp'
local Print = require('utils.print_override')
local ErrorLogging = require 'utils.error_logging'
local serialize = serpent.serialize
local concat = table.concat
@ -18,11 +19,13 @@ local serialize_options = {sparse = true, compact = true}
local Public = {}
local server_time = {secs = nil, tick = 0}
ErrorLogging.server_time = server_time
Global.register(
server_time,
function(tbl)
server_time = tbl
ErrorLogging.server_time = tbl
end
)
@ -299,6 +302,7 @@ local function data_set_changed(data)
local success, err = pcall(handler, data)
if not success then
log(err)
ErrorLogging.generate_error_report(err)
error(err, 2)
end
end
@ -307,6 +311,7 @@ local function data_set_changed(data)
local success, err = pcall(handler, data)
if not success then
log(err)
ErrorLogging.generate_error_report(err)
end
end
end

View File

@ -2,6 +2,7 @@ local Event = require 'utils.event'
local Game = require 'utils.game'
local Utils = require 'utils.core'
local Timestamp = require 'utils.timestamp'
local ErrorLogging = require 'utils.error_logging'
local Rank = require 'features.rank_system'
local Donator = require 'features.donator'
local Server = require 'features.server'
@ -247,11 +248,14 @@ function Command.add(command_name, options, callback)
if _DEBUG then
print(format("%s triggered an error running a command and has been logged: '%s' with arguments %s", player_name, command_name, serialized_arguments))
print(error)
ErrorLogging.generate_error_report(error)
return
end
print(format('There was an error running %s, it has been logged.', command_name))
log(format("Error while running '%s' with arguments %s: %s", command_name, serialized_arguments, error))
local err = format("Error while running '%s' with arguments %s: %s", command_name, serialized_arguments, error)
log(err)
ErrorLogging.generate_error_report(err)
end
end)
end

86
utils/error_logging.lua Normal file
View File

@ -0,0 +1,86 @@
--[[
This module creates a file of just trapped lua errors. It is possible that this module misses errors, therefore it is advised
that users also verify their server/game logs.
]]
-- Dependencies
local Timestamp = require 'utils.timestamp'
-- Localized functions
local floor = math.floor
local format = string.format
local insert = table.insert
local concat = table.concat
-- Local constants
local minutes_to_ticks = 60 * 60
local hours_to_ticks = 60 * 60 * 60
local ticks_to_minutes = 1 / minutes_to_ticks
local ticks_to_hours = 1 / hours_to_ticks
local warning = '\n\n\n\nTHIS LOG IS NOT ALL-INCLUSIVE AND CAN MISS ERRORS. IF THERE ARE ANY SUSPICIONS OF ERRORS CHECK THE LOGS.\n\n\n\n'
-- Local vars
local Public = {
server_time = {secs = nil, tick = 0}
}
local first_error = true
--- Copied from utils.core, turns ticks into a human-readable time.
local function format_time(ticks)
local result = {}
local hours = floor(ticks * ticks_to_hours)
if hours > 0 then
ticks = ticks - hours * hours_to_ticks
insert(result, hours)
if hours == 1 then
insert(result, 'hour')
else
insert(result, 'hours')
end
end
local minutes = floor(ticks * ticks_to_minutes)
insert(result, minutes)
if minutes == 1 then
insert(result, 'minute')
else
insert(result, 'minutes')
end
return concat(result, ' ')
end
--- Takes the given string and generates an entry in the error file.
function Public.generate_error_report(str)
Debug.print()
local server_time = Public.server_time.secs
local server_time_str = '(Server time: unavailable)'
local file_name = 'redmew_errors.log'
if server_time then
server_time_str = format('(Server time: %s)', Timestamp.to_string(server_time))
file_name = Timestamp.to_date_string(server_time) .. '_' .. file_name
else
game.write_file(file_name, '', false, 0)
end
if first_error then
server_time_str = warning .. server_time_str
first_error = nil
end
local tick = 'pre-game'
if game then
tick = format_time(game.tick)
end
tick = 'Time of error: ' .. tick
local redmew_version = global.redmew_version or 'Unknown'
redmew_version = 'RedMew version: ' .. redmew_version
local output = concat({server_time_str, tick, redmew_version, str, '\n'}, '\n')
game.write_file(file_name, output, true, 0)
end
return Public

View File

@ -1,5 +1,6 @@
-- This module exists to break the circular dependency between event.lua and global.lua.
-- It is not expected that any user code would require this module instead event.lua should be required.
local ErrorLogging = require 'utils.error_logging'
local Public = {}
@ -16,18 +17,22 @@ local log = log
local script_on_event = script.on_event
local script_on_nth_tick = script.on_nth_tick
local function call_handlers(handlers, event)
if _DEBUG then
local call_handlers
if _DEBUG then
function call_handlers(handlers, event)
for i = 1, #handlers do
local handler = handlers[i]
handler(event)
end
else
end
else
function call_handlers(handlers, event)
for i = 1, #handlers do
local handler = handlers[i]
local success, error = pcall(handler, event)
if not success then
log(error)
ErrorLogging.generate_error_report(error)
end
end
end

View File

@ -8,6 +8,7 @@ local Queue = require 'utils.queue'
local PriorityQueue = require 'utils.priority_queue'
local Event = require 'utils.event'
local Token = require 'utils.token'
local ErrorLogging = require 'utils.error_logging'
local Task = {}
@ -45,6 +46,7 @@ local function on_tick()
error(result)
else
log(result)
ErrorLogging.generate_error_report(result)
end
Queue.pop(queue)
global.total_task_weight = global.total_task_weight - task.weight
@ -64,6 +66,7 @@ local function on_tick()
error(result)
else
log(result)
ErrorLogging.generate_error_report(result)
end
end
PriorityQueue.pop(callbacks, comp)

View File

@ -119,15 +119,15 @@ local function normalise(year, month, day, hour, min, sec)
end
--- Converts unix epoch timestamp into table {year: number, month: number, day: number, hour: number, min: number, sec: number}
-- @param sec<number> unix epoch timestamp
-- @return {year: number, month: number, day: number, hour: number, min: number, sec: number}
-- @param <number> sec unix epoch timestamp
-- @return <table> {year: number, month: number, day: number, hour: number, min: number, sec: number}
function Public.to_timetable(secs)
return normalise(1970, 1, 1, 0, 0, secs)
end
--- Converts timetable into unix epoch timestamp
-- @param timetable<table> {year: number, month: number, day: number, hour: number, min: number, sec: number}
-- @return number
-- @param <table> timetable {year: number, month: number, day: number, hour: number, min: number, sec: number}
-- @return <number>
function Public.from_timetable(timetable)
local tt = normalise(timetable.year, timetable.month, timetable.day, timetable.hour, timetable.min, timetable.sec)
@ -142,11 +142,19 @@ function Public.from_timetable(timetable)
end
--- Converts unix epoch timestamp into human readable string.
-- @param secs<type> unix epoch timestamp
-- @return string
-- @param <number> secs unix epoch timestamp
-- @return <string>
function Public.to_string(secs)
local tt = normalise(1970, 1, 1, 0, 0, secs)
return strformat('%04u-%02u-%02u %02u:%02u:%02d', tt.year, tt.month, tt.day, tt.hour, tt.min, tt.sec)
end
--- Converts unix epoch timestamp into a date string.
-- @param <number> secs unix epoch timestamp
-- @return <string> With data in format YYYY-MM-DD
function Public.to_date_string(secs)
local tt = normalise(1970, 1, 1, 0, 0, secs)
return strformat('%04u-%02u-%02u', tt.year, tt.month, tt.day)
end
return Public