utils.py 4.9 KB

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