error.py 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677
  1. from django.utils.encoding import force_str
  2. from sentry.constants import MAX_CULPRIT_LENGTH
  3. from sentry.culprit import generate_culprit
  4. from sentry.stacktraces.functions import get_function_name_for_frame
  5. from sentry.stacktraces.processing import get_crash_frame_from_event_data
  6. from sentry.utils.safe import get_path, trim, truncatechars
  7. from .base import BaseEvent
  8. def get_crash_location(data):
  9. frame = get_crash_frame_from_event_data(
  10. data,
  11. frame_filter=lambda x: x.get("function")
  12. not in (None, "<redacted>", "<unknown>"),
  13. )
  14. if frame is not None:
  15. func = get_function_name_for_frame(frame, data.get("platform"))
  16. return frame.get("filename") or frame.get("abs_path"), func
  17. class ErrorEvent(BaseEvent):
  18. key = "error"
  19. def get_metadata(self, data):
  20. # Check for undocumented interface where exception has no values. Go SDK does this.
  21. # https://docs.sentry.io/development/sdk-dev/event-payloads/exception/
  22. # exception can be an list instead of a dictionary
  23. if isinstance(data.get("exception"), list):
  24. if len(data["exception"]) == 0:
  25. return {}
  26. # Force documented interface
  27. data["exception"] = {"values": data["exception"]}
  28. exception = get_path(data, "exception", "values", -1)
  29. if not exception:
  30. return {}
  31. loc = get_crash_location(data)
  32. rv = {"value": trim(get_path(exception, "value", default=""), 1024)}
  33. # If the exception mechanism indicates a synthetic exception we do not
  34. # want to record the type and value into the metadata.
  35. if not get_path(exception, "mechanism", "synthetic"):
  36. rv["type"] = trim(get_path(exception, "type", default="Error"), 128)
  37. # Attach crash location if available
  38. if loc is not None:
  39. fn, func = loc
  40. if fn:
  41. rv["filename"] = fn
  42. if func:
  43. rv["function"] = func
  44. return rv
  45. def get_title(self, metadata):
  46. ty = metadata.get("type")
  47. if ty is None:
  48. return metadata.get("function") or "<unknown>"
  49. if not metadata.get("value"):
  50. return ty
  51. try:
  52. return "{}: {}".format(ty, truncatechars(metadata["value"].splitlines()[0]))
  53. except AttributeError:
  54. # GlitchTip modification
  55. # Exception value is specified as a string, sometimes it isn't. This is a fallback.
  56. return "{}: {}".format(ty, str(metadata["value"]))
  57. def get_location(self, data):
  58. loc_string = force_str(
  59. data.get("culprit")
  60. or data.get("transaction")
  61. or generate_culprit(data)
  62. or ""
  63. )
  64. return truncatechars(loc_string, MAX_CULPRIT_LENGTH)