utils.py 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. import datetime
  2. import json
  3. import time
  4. import uuid
  5. from typing import Union
  6. from django.test import TestCase
  7. from model_bakery import baker
  8. from apps.organizations_ext.constants import OrganizationUserRole
  9. from glitchtip.test_utils.test_case import GlitchTipTestCaseMixin
  10. from ..process_event import process_issue_events
  11. from ..schema import (
  12. InterchangeIssueEvent,
  13. IssueEventSchema,
  14. )
  15. def list_to_envelope(data: list[dict]) -> str:
  16. result_lines = []
  17. for item in data:
  18. result_lines.append(json.dumps(item))
  19. return "\n".join(result_lines)
  20. def generate_event(
  21. event_type="error",
  22. level="error",
  23. platform="python",
  24. release="default-release",
  25. environment="production",
  26. num_events=1,
  27. event=None,
  28. envelope=False,
  29. ):
  30. """
  31. Generates sentry compatible events for use in unit tests.
  32. Args:
  33. event_type (str): The type of event ('error', 'warning', 'transaction', etc.). Default is 'error'.
  34. level (str): The event level ('error', 'warning', 'info', etc.). Default is 'error'.
  35. platform (str): The platform the event originated from ('python', 'javascript', 'java', etc.). Default is 'python'.
  36. release (str): The release version. Default is 'default-release'.
  37. environment (str): The environment (e.g., 'production', 'staging'). Default is 'production'.
  38. num_events (int): The number of events to generate. Default is 1.
  39. event (dict): A dictionary of additional fields to override in the base event.
  40. envelope (bool): Whether to wrap the event(s) in an envelope list. Default is False.
  41. Returns:
  42. dict or list: A single event dictionary, a list of event dictionaries, or an envelope list containing event data.
  43. """
  44. base_event = {
  45. "event_id": str(uuid.uuid4()),
  46. "timestamp": time.time(),
  47. "sdk": {"name": "sentry.python", "version": "1.11.0"},
  48. "platform": platform,
  49. "level": level,
  50. "exception": {
  51. "values": [
  52. {
  53. "type": "TypeError",
  54. "value": "unsupported operand type(s) for +: 'int' and 'str'",
  55. "stacktrace": {
  56. "frames": [
  57. {
  58. "filename": "my_module.py",
  59. "function": "my_function",
  60. "in_app": True,
  61. "lineno": 10,
  62. }
  63. ]
  64. },
  65. }
  66. ]
  67. },
  68. "release": release,
  69. "environment": environment,
  70. "request": {
  71. "url": "http://example.com",
  72. "headers": {"User-Agent": "Test Agent"},
  73. },
  74. }
  75. if event:
  76. base_event.update(event)
  77. if num_events == 1:
  78. if envelope:
  79. return [
  80. {
  81. "event_id": base_event["event_id"],
  82. "sent_at": datetime.datetime.now().isoformat() + "Z",
  83. },
  84. {"type": "event"},
  85. base_event,
  86. ]
  87. else:
  88. return base_event
  89. else:
  90. events = []
  91. for _ in range(num_events):
  92. new_event = base_event.copy()
  93. new_event["event_id"] = str(uuid.uuid4())
  94. if envelope:
  95. events.append(
  96. [
  97. {
  98. "event_id": new_event["event_id"],
  99. "sent_at": datetime.datetime.now().isoformat() + "Z",
  100. },
  101. {"type": "event"},
  102. new_event,
  103. ]
  104. )
  105. else:
  106. events.append(new_event)
  107. return events
  108. class EventIngestTestCase(GlitchTipTestCaseMixin, TestCase):
  109. """
  110. Base class for event ingest tests with helper functions
  111. """
  112. def setUp(self):
  113. self.create_project()
  114. self.params = f"?sentry_key={self.projectkey.public_key}"
  115. def get_json_data(self, filename: str):
  116. with open(filename) as json_file:
  117. return json.load(json_file)
  118. def create_logged_in_user(self):
  119. self.user = baker.make("users.user")
  120. self.client.force_login(self.user)
  121. self.org_user = self.organization.add_user(
  122. self.user, OrganizationUserRole.ADMIN
  123. )
  124. self.team = baker.make("teams.Team", organization=self.organization)
  125. self.team.members.add(self.org_user)
  126. self.project = baker.make("projects.Project", organization=self.organization)
  127. self.project.teams.add(self.team)
  128. def process_events(self, data: Union[dict, list[dict]]) -> list:
  129. if isinstance(data, dict):
  130. data = [data]
  131. events = [
  132. InterchangeIssueEvent(
  133. project_id=self.project.id,
  134. organization_id=self.organization.id if self.organization else None,
  135. payload=IssueEventSchema(**dat),
  136. )
  137. for dat in data
  138. ]
  139. process_issue_events(events)
  140. return events