mirror of
https://github.com/CHOMPStation2/CHOMPStation2.git
synced 2025-12-10 10:12:45 +00:00
Co-authored-by: Selis <12716288+ItsSelis@users.noreply.github.com> Co-authored-by: Kashargul <144968721+Kashargul@users.noreply.github.com>
128 lines
4.0 KiB
Plaintext
128 lines
4.0 KiB
Plaintext
|
|
// Schema version must always be the very last element in the array.
|
|
|
|
// Current Schema: 1.0.0
|
|
// [timestamp, category, message, data, world_state, semver_store, id, schema_version]
|
|
|
|
/// A datum which contains log information.
|
|
/datum/log_entry
|
|
/// Next id to assign to a log entry.
|
|
var/static/next_id = 0
|
|
|
|
/// Unique id of the log entry.
|
|
var/id
|
|
|
|
/// Schema version of the log entry.
|
|
var/schema_version = "1.0.0"
|
|
|
|
/// Unix timestamp of the log entry.
|
|
var/timestamp
|
|
|
|
/// Category of the log entry.
|
|
var/category
|
|
|
|
/// Message of the log entry.
|
|
var/message
|
|
|
|
/// Bitfield that describes how exactly to log stuff exactly
|
|
/// See code/__DEFINES/logging/dm
|
|
var/flags = NONE
|
|
|
|
/// Data of the log entry; optional.
|
|
var/list/data
|
|
|
|
/// Semver store of the log entry, used to store the schema of data entries
|
|
var/list/semver_store
|
|
|
|
GENERAL_PROTECT_DATUM(/datum/log_entry)
|
|
|
|
/datum/log_entry/New(timestamp, category, message, flags, list/data, list/semver_store)
|
|
..()
|
|
|
|
src.id = next_id++
|
|
src.timestamp = timestamp
|
|
src.category = category
|
|
src.flags = flags
|
|
src.message = message
|
|
with_data(data)
|
|
with_semver_store(semver_store)
|
|
|
|
/datum/log_entry/proc/with_data(list/data)
|
|
if(!isnull(data))
|
|
if(!islist(data))
|
|
src.data = list("data" = data)
|
|
stack_trace("Log entry data was not a list, it was [data.type].")
|
|
else
|
|
src.data = data
|
|
return src
|
|
|
|
/datum/log_entry/proc/with_semver_store(list/semver_store)
|
|
if(isnull(semver_store))
|
|
return
|
|
if(!islist(semver_store))
|
|
stack_trace("Log entry semver store was not a list, it was [semver_store.type]. We cannot reliably convert it to a list.")
|
|
else
|
|
src.semver_store = semver_store
|
|
return src
|
|
|
|
/// Converts the log entry to a human-readable string.
|
|
/datum/log_entry/proc/to_readable_text(format = TRUE)
|
|
var/output = ""
|
|
if(format)
|
|
output += "\[[timestamp]\] [uppertext(category)]: [message]"
|
|
else
|
|
output += "[uppertext(category)]: [message]"
|
|
|
|
if(flags & ENTRY_USE_DATA_W_READABLE)
|
|
output += json_encode(data, JSON_PRETTY_PRINT)
|
|
return output
|
|
|
|
#define MANUAL_JSON_ENTRY(list, key, value) list.Add("\"[key]\":[(!isnull(value)) ? json_encode(value) : "null"]")
|
|
|
|
/// Converts the log entry to a JSON string.
|
|
/datum/log_entry/proc/to_json_text()
|
|
// I do not trust byond's json encoder, and need to ensure the order doesn't change.
|
|
var/list/json_entries = list()
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_TIMESTAMP, timestamp)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_CATEGORY, category)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_MESSAGE, message)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_DATA, data)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_WORLD_STATE, world.get_world_state_for_logging())
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_SEMVER_STORE, semver_store)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_ID, id)
|
|
MANUAL_JSON_ENTRY(json_entries, LOG_ENTRY_KEY_SCHEMA_VERSION, schema_version)
|
|
return "{[json_entries.Join(",")]}"
|
|
|
|
#undef MANUAL_JSON_ENTRY
|
|
|
|
#define CHECK_AND_TRY_FILE_ERROR_RECOVERY(file) \
|
|
var/static/in_error_recovery = FALSE; \
|
|
if(!fexists(##file)) { \
|
|
if(in_error_recovery) { \
|
|
in_error_recovery = FALSE; \
|
|
CRASH("Failed to error recover log file: [file]"); \
|
|
}; \
|
|
in_error_recovery = TRUE; \
|
|
logger.Log(LOG_CATEGORY_INTERNAL_ERROR, "attempting to perform file error recovery: [file]"); \
|
|
logger.init_category_file(logger.log_categories[category]); \
|
|
call(src, __PROC__)(arglist(args)); \
|
|
return; \
|
|
}; \
|
|
in_error_recovery = FALSE;
|
|
|
|
/// Writes the log entry to a file.
|
|
/datum/log_entry/proc/write_entry_to_file(file)
|
|
CHECK_AND_TRY_FILE_ERROR_RECOVERY(file)
|
|
WRITE_LOG_NO_FORMAT(file, "[to_json_text()]\n")
|
|
|
|
/// Writes the log entry to a file as a human-readable string.
|
|
/datum/log_entry/proc/write_readable_entry_to_file(file, format_internally = TRUE)
|
|
CHECK_AND_TRY_FILE_ERROR_RECOVERY(file)
|
|
// If it's being formatted internally we need to manually add a newline
|
|
if(format_internally)
|
|
WRITE_LOG_NO_FORMAT(file, "[to_readable_text(format = TRUE)]\n")
|
|
else
|
|
WRITE_LOG(file, "[to_readable_text(format = FALSE)]")
|
|
|
|
#undef CHECK_AND_TRY_FILE_ERROR_RECOVERY
|