feat(error_log): add in some request/job metadata (#34937)

Signed-off-by: Akhil Narang <me@akhilnarang.dev>
This commit is contained in:
Akhil Narang 2025-11-28 15:29:30 +05:30 committed by GitHub
parent c2a6b91078
commit e5b340fad4
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 49 additions and 3 deletions

View file

@ -12,7 +12,8 @@
"section_break_5",
"method",
"error",
"trace_id"
"trace_id",
"metadata"
],
"fields": [
{
@ -66,13 +67,19 @@
"fieldtype": "Data",
"label": "Trace ID",
"read_only": 1
},
{
"fieldname": "metadata",
"fieldtype": "Code",
"label": "Metadata",
"read_only": 1
}
],
"icon": "fa fa-warning-sign",
"idx": 1,
"in_create": 1,
"links": [],
"modified": "2024-12-09 14:22:44.819718",
"modified": "2025-11-27 18:04:21.399557",
"modified_by": "Administrator",
"module": "Core",
"name": "Error Log",
@ -90,8 +97,9 @@
"write": 1
}
],
"row_format": "Dynamic",
"sort_field": "creation",
"sort_order": "DESC",
"states": [],
"title_field": "method"
}
}

View file

@ -17,6 +17,7 @@ class ErrorLog(Document):
from frappe.types import DF
error: DF.Code | None
metadata: DF.Code | None
method: DF.Data | None
reference_doctype: DF.Link | None
reference_name: DF.Data | None

View file

@ -59,6 +59,8 @@ def log_error(title=None, message=None, reference_doctype=None, reference_name=N
return
trace_id = get_trace_id()
metadata = get_error_metadata()
error_log = frappe.get_doc(
doctype="Error Log",
error=traceback,
@ -66,6 +68,7 @@ def log_error(title=None, message=None, reference_doctype=None, reference_name=N
reference_doctype=reference_doctype,
reference_name=reference_name,
trace_id=trace_id,
metadata=metadata,
)
# Capture exception data if telemetry is enabled
@ -77,6 +80,40 @@ def log_error(title=None, message=None, reference_doctype=None, reference_name=N
return error_log.insert(ignore_permissions=True)
def get_error_metadata() -> str:
"""
Returns request/job metadata to store in Error Log for easier debugging
"""
import rq
from frappe.utils.logger import sanitized_dict
metadata = {}
try:
if job := rq.get_current_job():
metadata["type"] = "background_job"
metadata["job_id"] = job.id
metadata["job_name"] = frappe.cstr(job.kwargs.get("method"))
metadata["queue"] = job.origin
metadata["kwargs"] = sanitized_dict(job.kwargs)
if "run_scheduled_job" in metadata["job_name"]:
metadata["scheduled"] = True
metadata["job_type"] = job.kwargs.get("kwargs", {}).get("job_type", "")
else:
metadata["type"] = "http_request"
for key in ("method", "path", "referrer"):
metadata[key] = getattr(frappe.local.request, key)
metadata["form_dict"] = sanitized_dict(frappe.form_dict)
metadata["user"] = getattr(frappe.session, "user", "Unidentified")
finally:
# We don't want to bother with exception handling *while* gathering some error's metadata
return frappe.as_json(metadata) # noqa: B012
def log_error_snapshot(exception: Exception):
if isinstance(exception, EXCLUDE_EXCEPTIONS) or _is_ldap_exception(exception):
return