mock-traces 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346
  1. #!/usr/bin/env python
  2. from sentry.runner import configure
  3. configure()
  4. from datetime import timedelta
  5. from uuid import uuid4
  6. from django.conf import settings
  7. from django.db.models import F
  8. from django.utils import timezone
  9. from sentry.models import Organization, Project
  10. from sentry.utils.samples import create_trace, generate_user, random_normal
  11. def main(slow=False):
  12. project_names = {"Ludic Science", "Earth", "Fire", "Wind", "Water", "Heart"}
  13. project_map = {}
  14. if settings.SENTRY_SINGLE_ORGANIZATION:
  15. org = Organization.get_default()
  16. print(f"Mocking org {org.name}") # NOQA
  17. else:
  18. print("Mocking org {}".format("Default")) # NOQA
  19. org, _ = Organization.objects.get_or_create(slug="default")
  20. for project_name in project_names:
  21. print(f" > Mocking project {project_name}") # NOQA
  22. project, _ = Project.objects.get_or_create(
  23. name=project_name,
  24. defaults={
  25. "organization": org,
  26. "first_event": timezone.now(),
  27. "flags": Project.flags.has_releases,
  28. },
  29. )
  30. project_map[project_name] = project
  31. if not project.first_event:
  32. project.update(first_event=project.date_added)
  33. if not project.flags.has_releases:
  34. project.update(flags=F("flags").bitor(Project.flags.has_releases))
  35. if not project.flags.has_transactions:
  36. project.update(flags=F("flags").bitor(Project.flags.has_transactions))
  37. frontend_project = project_map["Fire"]
  38. backend_project = project_map["Earth"]
  39. service_projects = [
  40. project_map["Wind"],
  41. project_map["Water"],
  42. project_map["Heart"],
  43. ]
  44. timestamp = timezone.now()
  45. print(f" > Loading normal trace") # NOQA
  46. # Normal trace
  47. create_trace(
  48. slow,
  49. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  50. timestamp,
  51. generate_user(),
  52. uuid4().hex,
  53. None,
  54. {
  55. "project": frontend_project,
  56. "transaction": "/plants/:plantId/",
  57. "frontend": True,
  58. "errors": 1,
  59. "children": [
  60. {
  61. "project": backend_project,
  62. "transaction": "/api/plants/",
  63. "children": [
  64. {
  65. "project": service_projects[0],
  66. "transaction": "/products/all/",
  67. "children": [],
  68. },
  69. {
  70. "project": service_projects[1],
  71. "transaction": "/analytics/",
  72. "children": [],
  73. },
  74. {
  75. "project": service_projects[2],
  76. "transaction": "tasks.create_invoice",
  77. "children": [],
  78. },
  79. ],
  80. },
  81. ],
  82. },
  83. )
  84. print(f" > Loading normal trace, but with performance issue") # NOQA
  85. # Normal trace
  86. create_trace(
  87. slow,
  88. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  89. timestamp,
  90. generate_user(),
  91. uuid4().hex,
  92. None,
  93. {
  94. "project": frontend_project,
  95. "transaction": "/plants/:plantId/",
  96. "frontend": True,
  97. "errors": 1,
  98. "children": [
  99. {
  100. "project": backend_project,
  101. "transaction": "/api/plants/",
  102. "performance_issues": ["n+1"],
  103. "children": [
  104. {
  105. "project": service_projects[0],
  106. "transaction": "/products/all/",
  107. "children": [],
  108. },
  109. {
  110. "project": service_projects[1],
  111. "transaction": "/analytics/",
  112. "children": [],
  113. },
  114. {
  115. "project": service_projects[2],
  116. "transaction": "tasks.create_invoice",
  117. "children": [],
  118. },
  119. ],
  120. },
  121. ],
  122. },
  123. )
  124. print(f" > Loading orphan data") # NOQA
  125. # Trace only with orphans
  126. create_trace(
  127. slow,
  128. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  129. timestamp,
  130. generate_user(),
  131. uuid4().hex,
  132. uuid4().hex[:16],
  133. {
  134. "project": frontend_project,
  135. "transaction": "/orphans/:orphanId/",
  136. "frontend": True,
  137. "children": [
  138. {
  139. "project": backend_project,
  140. "transaction": "/api/orphans/",
  141. "errors": 1,
  142. "children": [
  143. {
  144. "project": service_projects[0],
  145. "transaction": "/orphans/all/",
  146. "errors": 1,
  147. "children": [],
  148. },
  149. {
  150. "project": service_projects[1],
  151. "transaction": "/orphan/analytics/",
  152. "children": [],
  153. },
  154. {
  155. "project": service_projects[2],
  156. "transaction": "tasks.invoice_orphans",
  157. "errors": 1,
  158. "children": [],
  159. },
  160. ],
  161. },
  162. ],
  163. },
  164. )
  165. print(f" > Loading trace with many siblings") # NOQA
  166. create_trace(
  167. slow,
  168. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  169. timestamp,
  170. generate_user(),
  171. uuid4().hex,
  172. None,
  173. {
  174. "project": frontend_project,
  175. "transaction": "/siblings/:count/",
  176. "frontend": True,
  177. "children": [
  178. {
  179. "project": backend_project,
  180. "transaction": f"/api/sibling_{i}/",
  181. "children": [],
  182. }
  183. for i in range(15)
  184. ],
  185. },
  186. )
  187. print(f" > Loading trace with many roots") # NOQA
  188. trace_id = uuid4().hex
  189. for _ in range(15):
  190. create_trace(
  191. slow,
  192. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  193. timestamp,
  194. generate_user(),
  195. trace_id,
  196. None,
  197. {
  198. "project": frontend_project,
  199. "transaction": "/multiple-root/:root/",
  200. "frontend": True,
  201. "children": [
  202. {
  203. "project": backend_project,
  204. "transaction": "/multiple-root/child/",
  205. "children": [],
  206. }
  207. ],
  208. },
  209. )
  210. print(f" > Loading chained trace with orphans") # NOQA
  211. trace_id = uuid4().hex
  212. create_trace(
  213. slow,
  214. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  215. timestamp,
  216. generate_user(),
  217. trace_id,
  218. None,
  219. {
  220. "project": frontend_project,
  221. "transaction": "/chained/:login/",
  222. "frontend": True,
  223. "children": [
  224. {
  225. "project": backend_project,
  226. "transaction": "/api/auth/",
  227. "children": [
  228. {
  229. "project": service_projects[0],
  230. "transaction": "/auth/check-login/",
  231. "errors": 1,
  232. "children": [
  233. {
  234. "project": service_projects[1],
  235. "transaction": "/analytics/",
  236. "errors": 1,
  237. "children": [
  238. {
  239. "project": service_projects[2],
  240. "transaction": "tasks.check_login",
  241. "errors": 1,
  242. "children": [],
  243. }
  244. ],
  245. }
  246. ],
  247. },
  248. ],
  249. },
  250. ],
  251. },
  252. )
  253. create_trace(
  254. slow,
  255. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  256. timestamp,
  257. generate_user(),
  258. trace_id,
  259. uuid4().hex[:16],
  260. {
  261. "project": frontend_project,
  262. "transaction": "/orphans/:orphanId/",
  263. "frontend": True,
  264. "children": [
  265. {
  266. "project": backend_project,
  267. "transaction": "/api/orphans/",
  268. "errors": 1,
  269. "children": [],
  270. }
  271. ],
  272. },
  273. )
  274. print(f" > Loading traces missing instrumentation") # NOQA
  275. create_trace(
  276. slow,
  277. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  278. timestamp,
  279. generate_user(),
  280. uuid4().hex,
  281. None,
  282. {
  283. "project": frontend_project,
  284. "transaction": "/missing/:frontend/",
  285. "frontend": True,
  286. "children": [],
  287. },
  288. )
  289. create_trace(
  290. slow,
  291. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  292. timestamp,
  293. generate_user(),
  294. uuid4().hex,
  295. None,
  296. {
  297. "project": backend_project,
  298. "transaction": "/missing/backend",
  299. "children": [],
  300. },
  301. )
  302. if __name__ == "__main__":
  303. settings.CELERY_ALWAYS_EAGER = True
  304. from optparse import OptionParser
  305. parser = OptionParser()
  306. parser.add_option(
  307. "--slow",
  308. default=False,
  309. action="store_true",
  310. help="sleep between each transaction to let clickhouse rest",
  311. )
  312. (options, args) = parser.parse_args()
  313. try:
  314. main(
  315. slow=options.slow,
  316. )
  317. except Exception:
  318. # Avoid reporting any issues recursively back into Sentry
  319. import sys
  320. import traceback
  321. traceback.print_exc()
  322. sys.exit(1)