Module:ErrorHandling: Difference between revisions
Appearance
// via Wikitext Extension for VSCode Tag: Manual revert |
// via Wikitext Extension for VSCode Tag: Reverted |
||
| Line 25: | Line 25: | ||
end | end | ||
-- Add an error to the context | -- Add an error or info message to the context | ||
-- @param context The error context | -- @param context The error context | ||
-- @param source The source of the error (function name) | -- @param source The source of the error (function name) | ||
| Line 31: | Line 31: | ||
-- @param details Optional additional details about the error | -- @param details Optional additional details about the error | ||
-- @param isCritical Whether this is a critical error (default: false) | -- @param isCritical Whether this is a critical error (default: false) | ||
-- @param messageType Type of message: 'error' or 'info' (default: 'error') | |||
-- @return The error context (for chaining) | -- @return The error context (for chaining) | ||
function ErrorHandling.addError(context, source, message, details, isCritical) | function ErrorHandling.addError(context, source, message, details, isCritical, messageType) | ||
-- Increment the | messageType = messageType or 'error' | ||
-- Initialize message type counts if not present | |||
if not context.MESSAGE_TYPE_COUNTS then | |||
context.MESSAGE_TYPE_COUNTS = { error = 0, info = 0 } | |||
end | |||
-- Increment the appropriate count | |||
context.ERROR_COUNT = context.ERROR_COUNT + 1 | context.ERROR_COUNT = context.ERROR_COUNT + 1 | ||
context.MESSAGE_TYPE_COUNTS[messageType] = context.MESSAGE_TYPE_COUNTS[messageType] + 1 | |||
-- Add the error to the list | -- Add the error to the list | ||
| Line 42: | Line 51: | ||
message = message or "Unknown error", | message = message or "Unknown error", | ||
details = details or "", | details = details or "", | ||
isCritical = isCritical or false | isCritical = isCritical or false, | ||
messageType = messageType | |||
}) | }) | ||
| Line 61: | Line 71: | ||
if context.ERROR_COUNT == 0 then | if context.ERROR_COUNT == 0 then | ||
return "" | return "" | ||
end | |||
-- Determine message type for styling | |||
local errorCount = context.MESSAGE_TYPE_COUNTS and context.MESSAGE_TYPE_COUNTS.error or context.ERROR_COUNT | |||
local infoCount = context.MESSAGE_TYPE_COUNTS and context.MESSAGE_TYPE_COUNTS.info or 0 | |||
local messageType = "error" -- default | |||
if errorCount == 0 and infoCount > 0 then | |||
messageType = "info" | |||
elseif errorCount > 0 and infoCount > 0 then | |||
messageType = "mixed" | |||
end | end | ||
| Line 66: | Line 87: | ||
local divAttributes = { | local divAttributes = { | ||
['data-template-error'] = "1", | ['data-template-error'] = "1", | ||
['data-error-count'] = tostring(context.ERROR_COUNT) | ['data-error-count'] = tostring(context.ERROR_COUNT), | ||
['data-message-type'] = messageType | |||
} | } | ||
-- Add message type counts if available | |||
if context.MESSAGE_TYPE_COUNTS then | |||
divAttributes['data-error-type-count'] = tostring(errorCount) | |||
divAttributes['data-info-type-count'] = tostring(infoCount) | |||
end | |||
-- Add individual error attributes with minimal naming | -- Add individual error attributes with minimal naming | ||
| Line 73: | Line 101: | ||
divAttributes['data-error-' .. err.id .. '-source'] = err.source | divAttributes['data-error-' .. err.id .. '-source'] = err.source | ||
divAttributes['data-error-' .. err.id .. '-msg'] = err.message | divAttributes['data-error-' .. err.id .. '-msg'] = err.message | ||
divAttributes['data-error-' .. err.id .. '-type'] = err.messageType or 'error' | |||
if err.details and err.details ~= "" then | if err.details and err.details ~= "" then | ||
divAttributes['data-error-' .. err.id .. '-details'] = err.details | divAttributes['data-error-' .. err.id .. '-details'] = err.details | ||
Revision as of 11:40, 30 June 2025
Documentation for this module may be created at Module:ErrorHandling/doc
-- Module:ErrorHandling
-- A centralized error handling system for templates that provides error tracking, reporting, and graceful failure recovery. It formats errors as data attributes for the debug monitor to display in the browser console.
local ErrorHandling = {}
-- Standard error messages for common scenarios
ErrorHandling.STANDARD_MESSAGES = {
TEMPLATE_RENDER_ERROR = "<!-- Error rendering template -->",
MODULE_LOAD_ERROR = "<!-- Error loading module -->",
PROPERTY_ERROR = "<!-- Error processing semantic properties -->"
-- Add more standard messages as needed
}
-- Creates a new error context for a template
-- @param templateName The name of the template (for error reporting)
-- @return A new error context table
function ErrorHandling.createContext(templateName)
return {
TEMPLATE_NAME = templateName or "UnknownTemplate",
START_TIME = os.clock() * 1000, -- Store in milliseconds
ERROR_COUNT = 0,
ERRORS = {},
HAS_CRITICAL_ERROR = false
}
end
-- Add an error or info message to the context
-- @param context The error context
-- @param source The source of the error (function name)
-- @param message The error message
-- @param details Optional additional details about the error
-- @param isCritical Whether this is a critical error (default: false)
-- @param messageType Type of message: 'error' or 'info' (default: 'error')
-- @return The error context (for chaining)
function ErrorHandling.addError(context, source, message, details, isCritical, messageType)
messageType = messageType or 'error'
-- Initialize message type counts if not present
if not context.MESSAGE_TYPE_COUNTS then
context.MESSAGE_TYPE_COUNTS = { error = 0, info = 0 }
end
-- Increment the appropriate count
context.ERROR_COUNT = context.ERROR_COUNT + 1
context.MESSAGE_TYPE_COUNTS[messageType] = context.MESSAGE_TYPE_COUNTS[messageType] + 1
-- Add the error to the list
table.insert(context.ERRORS, {
id = context.ERROR_COUNT,
source = source or "unknown",
message = message or "Unknown error",
details = details or "",
isCritical = isCritical or false,
messageType = messageType
})
-- Update critical error flag if needed
if isCritical then
context.HAS_CRITICAL_ERROR = true
end
-- Return the error context for chaining
return context
end
-- Format the error context for debugging output using data attributes
-- @param context The error context
-- @return HTML string with data attributes containing error information
function ErrorHandling.formatOutput(context)
-- If no errors, return empty string
if context.ERROR_COUNT == 0 then
return ""
end
-- Determine message type for styling
local errorCount = context.MESSAGE_TYPE_COUNTS and context.MESSAGE_TYPE_COUNTS.error or context.ERROR_COUNT
local infoCount = context.MESSAGE_TYPE_COUNTS and context.MESSAGE_TYPE_COUNTS.info or 0
local messageType = "error" -- default
if errorCount == 0 and infoCount > 0 then
messageType = "info"
elseif errorCount > 0 and infoCount > 0 then
messageType = "mixed"
end
-- Build minimal data attribute div
local divAttributes = {
['data-template-error'] = "1",
['data-error-count'] = tostring(context.ERROR_COUNT),
['data-message-type'] = messageType
}
-- Add message type counts if available
if context.MESSAGE_TYPE_COUNTS then
divAttributes['data-error-type-count'] = tostring(errorCount)
divAttributes['data-info-type-count'] = tostring(infoCount)
end
-- Add individual error attributes with minimal naming
for _, err in ipairs(context.ERRORS) do
divAttributes['data-error-' .. err.id .. '-source'] = err.source
divAttributes['data-error-' .. err.id .. '-msg'] = err.message
divAttributes['data-error-' .. err.id .. '-type'] = err.messageType or 'error'
if err.details and err.details ~= "" then
divAttributes['data-error-' .. err.id .. '-details'] = err.details
end
end
-- Build attribute string efficiently
local attrStr = ""
for k, v in pairs(divAttributes) do
attrStr = attrStr .. ' ' .. k .. '="' .. v .. '"'
end
-- Create hidden div with minimal footprint
return string.format('<div style="display:none"%s></div>', attrStr)
end
-- Create emergency display for catastrophic failures with minimal markup
-- @param args The template arguments
-- @param errorSource The source of the error
-- @param errorMessage The error message
-- @param templateType The type of template (e.g. "Event", "Person")
-- @return HTML string with a minimal template display and error data
function ErrorHandling.createEmergencyDisplay(args, errorSource, errorMessage, templateType)
-- Extract critical information for minimal display
local title = args.name or ("Unnamed " .. (templateType or "Item"))
-- Create minimal fallback with error data attributes
return string.format(
'{| class="template-table" cellpadding="2"\n' ..
'|-\n| class="template-title template-title-%s" | <span>%s</span>\n' ..
'|}\n' ..
'<div style="display:none" data-template-error="1" data-critical="1" ' ..
'data-error-1-source="%s" data-error-1-msg="%s"></div>',
string.lower(templateType or "generic"),
title,
errorSource,
errorMessage
)
end
-- Protect a function with pcall and error handling
-- @param context The error context
-- @param funcName Name of the function (for error reporting)
-- @param func The function to protect
-- @param fallback Value to return if the function fails
-- @param ... Arguments to pass to the function
-- @return The result of the function, or fallback value on error
function ErrorHandling.protect(context, funcName, func, fallback, ...)
local success, result = pcall(func, ...)
if not success then
ErrorHandling.addError(
context,
funcName,
"Function execution failed",
tostring(result),
false
)
return fallback
end
return result
end
-- Get a standard error message with fallback
-- @param messageKey The key of the standard message to retrieve
-- @param defaultMessage Optional fallback message if the key is not found
-- @return The standard message or the default message
function ErrorHandling.getMessage(messageKey, defaultMessage)
if ErrorHandling.STANDARD_MESSAGES and ErrorHandling.STANDARD_MESSAGES[messageKey] then
return ErrorHandling.STANDARD_MESSAGES[messageKey]
end
return defaultMessage or "<!-- Error -->"
end
-- Protected module loading
-- @param context The error context
-- @param moduleName Name of the module to load
-- @param isCritical Whether failure to load is critical (default: false)
-- @return The loaded module, or an empty table on failure
function ErrorHandling.safeRequire(context, moduleName, isCritical)
local success, module = pcall(require, moduleName)
if not success then
-- Record the error
ErrorHandling.addError(
context,
"ModuleLoading",
"Failed to load module",
moduleName,
isCritical or false
)
-- Return an empty table as fallback
return {}
end
return module
end
return ErrorHandling