Files
Arrow768 0f86453d4c Sentry Integration (#22202)
Sends Errors, Runtimes, ... to Sentry.io

---------

Signed-off-by: Arrow768 <1331699+Arrow768@users.noreply.github.com>
Co-authored-by: Werner <Arrow768@users.noreply.github.com>
2026-04-26 12:34:31 +02:00

138 lines
4.0 KiB
Plaintext

/**
* # Sentry Event
*
* Payload builder for a single Sentry event.
* Populated by SSsentry capture procs, then serialized via to_list() for
* json_encode() before being sent in the envelope body.
*/
/datum/sentry_event
/// 32-char hex UUID, stamped by SSsentry just before sending.
var/event_id = ""
/// ISO-8601 UTC timestamp, stamped by SSsentry just before sending.
var/timestamp = ""
/// Sentry level: "fatal", "error", "warning", "info", "debug".
var/level = "error"
/// Logical logger name shown in Sentry (e.g. "world.Error", "sql", "garbage").
var/logger = ""
/// Sentry environment tag, e.g. "production".
var/environment = ""
/// Sentry release string.
var/release = ""
/// Human-readable server identifier.
var/server_name = ""
// ---- tags & extra ----
/// Assoc list of short indexed tags visible in Sentry's issue sidebar.
var/list/tags
/// Assoc list of arbitrary extra context (not indexed).
var/list/extra
// ---- exception fields (mutually exclusive with message) ----
var/exc_type = ""
var/exc_value = ""
var/exc_file = ""
var/exc_line = 0
/// Flat list of detail lines from error_handler's desclines (optional).
var/list/exc_desc_lines
// ---- message fields ----
var/message_text = ""
// ---- user context ----
/// Sentry user id — either raw ckey or md5(ckey) depending on scrub setting.
var/usr_id = ""
/datum/sentry_event/New()
tags = list()
extra = list()
// ---------------------------------------------------------------------------
// Payload setters
// ---------------------------------------------------------------------------
/**
* Populate exception fields from a BYOND /exception datum.
* desclines is the optional list of extra context from world/Error().
*/
/datum/sentry_event/proc/set_exception(exception/e, list/desclines)
exc_type = e.name || "RuntimeError"
exc_value = e.desc || ""
exc_file = e.file || ""
exc_line = e.line || 0
if (LAZYLEN(desclines))
exc_desc_lines = desclines.Copy()
/// Set message text for SQL-error and hard-delete style events.
/datum/sentry_event/proc/set_message(text)
message_text = text
/// Set usr context without scrubbing (ckey sent in the clear).
/datum/sentry_event/proc/set_usr(atom/usr_ref)
if (istype(usr_ref, /mob))
var/mob/m = usr_ref
usr_id = m.ckey || m.name || "unknown"
else if (istype(usr_ref, /client))
var/client/c = usr_ref
usr_id = c.ckey || "unknown"
/// Set usr context with ckey hashed (md5) for PII compliance.
/datum/sentry_event/proc/set_usr_scrubbed(atom/usr_ref)
var/raw_ckey = ""
if (istype(usr_ref, /mob))
var/mob/m = usr_ref
raw_ckey = m.ckey || ""
else if (istype(usr_ref, /client))
var/client/c = usr_ref
raw_ckey = c.ckey || ""
usr_id = raw_ckey ? md5(raw_ckey) : "anonymous"
// ---------------------------------------------------------------------------
// Serialization
// ---------------------------------------------------------------------------
/**
* Return an associative list ready for json_encode().
* Omits empty/null fields to keep payloads lean.
*/
/datum/sentry_event/proc/to_list()
var/list/out = list(
"event_id" = event_id,
"timestamp" = timestamp,
"platform" = "other",
"level" = level
)
if (logger) out["logger"] = logger
if (environment) out["environment"] = environment
if (release) out["release"] = release
if (server_name) out["server_name"] = server_name
if (length(tags)) out["tags"] = tags
if (length(extra)) out["extra"] = extra
if (usr_id)
out["user"] = list("id" = usr_id)
// --- exception payload ---
if (exc_type)
var/list/exc_val = list(
"type" = exc_type,
"value" = exc_value
)
if (exc_file)
exc_val["stacktrace"] = list(
"frames" = list(list(
"filename" = exc_file,
"lineno" = exc_line
))
)
if (LAZYLEN(exc_desc_lines))
exc_val["extra"] = list("detail" = exc_desc_lines.Join("\n"))
out["exception"] = list("values" = list(exc_val))
// --- message payload ---
if (message_text)
out["message"] = list("formatted" = message_text)
return out