mock-traces 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387
  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. mobile_project = project_map["Ludic Science"]
  38. frontend_project = project_map["Fire"]
  39. backend_project = project_map["Earth"]
  40. service_projects = [
  41. project_map["Wind"],
  42. project_map["Water"],
  43. project_map["Heart"],
  44. ]
  45. timestamp = timezone.now()
  46. print(f" > Loading normal trace") # NOQA
  47. # Normal trace
  48. create_trace(
  49. slow,
  50. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  51. timestamp,
  52. generate_user(),
  53. uuid4().hex,
  54. None,
  55. {
  56. "project": frontend_project,
  57. "transaction": "/plants/:plantId/",
  58. "frontend": True,
  59. "errors": 1,
  60. "children": [
  61. {
  62. "project": backend_project,
  63. "transaction": "/api/plants/",
  64. "children": [
  65. {
  66. "project": service_projects[0],
  67. "transaction": "/products/all/",
  68. "children": [],
  69. },
  70. {
  71. "project": service_projects[1],
  72. "transaction": "/analytics/",
  73. "children": [],
  74. },
  75. {
  76. "project": service_projects[2],
  77. "transaction": "tasks.create_invoice",
  78. "children": [],
  79. },
  80. ],
  81. },
  82. ],
  83. },
  84. )
  85. print(f" > Loading normal trace, but with performance issue") # NOQA
  86. # Normal trace
  87. create_trace(
  88. slow,
  89. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  90. timestamp,
  91. generate_user(),
  92. uuid4().hex,
  93. None,
  94. {
  95. "project": frontend_project,
  96. "transaction": "/plants/:plantId/",
  97. "frontend": True,
  98. "errors": 1,
  99. "children": [
  100. {
  101. "project": backend_project,
  102. "transaction": "/api/plants/",
  103. "performance_issues": ["n+1"],
  104. "children": [
  105. {
  106. "project": service_projects[0],
  107. "transaction": "/products/all/",
  108. "children": [],
  109. },
  110. {
  111. "project": service_projects[1],
  112. "transaction": "/analytics/",
  113. "children": [],
  114. },
  115. {
  116. "project": service_projects[2],
  117. "transaction": "tasks.create_invoice",
  118. "children": [],
  119. },
  120. ],
  121. },
  122. ],
  123. },
  124. )
  125. print(f" > Loading mobile trace") # NOQA
  126. # Normal trace
  127. create_trace(
  128. slow,
  129. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  130. timestamp,
  131. generate_user(),
  132. uuid4().hex,
  133. None,
  134. {
  135. "project": mobile_project,
  136. "transaction": "MainActivity",
  137. "mobile": True,
  138. "errors": 1,
  139. "children": [
  140. {
  141. "project": backend_project,
  142. "transaction": "/api/plants/",
  143. "children": [
  144. {
  145. "project": service_projects[0],
  146. "transaction": "/products/all/",
  147. "children": [],
  148. },
  149. {
  150. "project": service_projects[1],
  151. "transaction": "/analytics/",
  152. "children": [],
  153. },
  154. {
  155. "project": service_projects[2],
  156. "transaction": "tasks.create_invoice",
  157. "children": [],
  158. },
  159. ],
  160. },
  161. ],
  162. },
  163. )
  164. print(f" > Loading orphan data") # NOQA
  165. # Trace only with orphans
  166. create_trace(
  167. slow,
  168. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  169. timestamp,
  170. generate_user(),
  171. uuid4().hex,
  172. uuid4().hex[:16],
  173. {
  174. "project": frontend_project,
  175. "transaction": "/orphans/:orphanId/",
  176. "frontend": True,
  177. "children": [
  178. {
  179. "project": backend_project,
  180. "transaction": "/api/orphans/",
  181. "errors": 1,
  182. "children": [
  183. {
  184. "project": service_projects[0],
  185. "transaction": "/orphans/all/",
  186. "errors": 1,
  187. "children": [],
  188. },
  189. {
  190. "project": service_projects[1],
  191. "transaction": "/orphan/analytics/",
  192. "children": [],
  193. },
  194. {
  195. "project": service_projects[2],
  196. "transaction": "tasks.invoice_orphans",
  197. "errors": 1,
  198. "children": [],
  199. },
  200. ],
  201. },
  202. ],
  203. },
  204. )
  205. print(f" > Loading trace with many siblings") # NOQA
  206. create_trace(
  207. slow,
  208. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  209. timestamp,
  210. generate_user(),
  211. uuid4().hex,
  212. None,
  213. {
  214. "project": frontend_project,
  215. "transaction": "/siblings/:count/",
  216. "frontend": True,
  217. "children": [
  218. {
  219. "project": backend_project,
  220. "transaction": f"/api/sibling_{i}/",
  221. "children": [],
  222. }
  223. for i in range(15)
  224. ],
  225. },
  226. )
  227. print(f" > Loading trace with many roots") # NOQA
  228. trace_id = uuid4().hex
  229. for _ in range(15):
  230. create_trace(
  231. slow,
  232. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  233. timestamp,
  234. generate_user(),
  235. trace_id,
  236. None,
  237. {
  238. "project": frontend_project,
  239. "transaction": "/multiple-root/:root/",
  240. "frontend": True,
  241. "children": [
  242. {
  243. "project": backend_project,
  244. "transaction": "/multiple-root/child/",
  245. "children": [],
  246. }
  247. ],
  248. },
  249. )
  250. print(f" > Loading chained trace with orphans") # NOQA
  251. trace_id = uuid4().hex
  252. create_trace(
  253. slow,
  254. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  255. timestamp,
  256. generate_user(),
  257. trace_id,
  258. None,
  259. {
  260. "project": frontend_project,
  261. "transaction": "/chained/:login/",
  262. "frontend": True,
  263. "children": [
  264. {
  265. "project": backend_project,
  266. "transaction": "/api/auth/",
  267. "children": [
  268. {
  269. "project": service_projects[0],
  270. "transaction": "/auth/check-login/",
  271. "errors": 1,
  272. "children": [
  273. {
  274. "project": service_projects[1],
  275. "transaction": "/analytics/",
  276. "errors": 1,
  277. "children": [
  278. {
  279. "project": service_projects[2],
  280. "transaction": "tasks.check_login",
  281. "errors": 1,
  282. "children": [],
  283. }
  284. ],
  285. }
  286. ],
  287. },
  288. ],
  289. },
  290. ],
  291. },
  292. )
  293. create_trace(
  294. slow,
  295. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  296. timestamp,
  297. generate_user(),
  298. trace_id,
  299. uuid4().hex[:16],
  300. {
  301. "project": frontend_project,
  302. "transaction": "/orphans/:orphanId/",
  303. "frontend": True,
  304. "children": [
  305. {
  306. "project": backend_project,
  307. "transaction": "/api/orphans/",
  308. "errors": 1,
  309. "children": [],
  310. }
  311. ],
  312. },
  313. )
  314. print(f" > Loading traces missing instrumentation") # NOQA
  315. create_trace(
  316. slow,
  317. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  318. timestamp,
  319. generate_user(),
  320. uuid4().hex,
  321. None,
  322. {
  323. "project": frontend_project,
  324. "transaction": "/missing/:frontend/",
  325. "frontend": True,
  326. "children": [],
  327. },
  328. )
  329. create_trace(
  330. slow,
  331. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  332. timestamp,
  333. generate_user(),
  334. uuid4().hex,
  335. None,
  336. {
  337. "project": backend_project,
  338. "transaction": "/missing/backend",
  339. "children": [],
  340. },
  341. )
  342. if __name__ == "__main__":
  343. settings.CELERY_ALWAYS_EAGER = True
  344. from optparse import OptionParser
  345. parser = OptionParser()
  346. parser.add_option(
  347. "--slow",
  348. default=False,
  349. action="store_true",
  350. help="sleep between each transaction to let clickhouse rest",
  351. )
  352. (options, args) = parser.parse_args()
  353. try:
  354. main(
  355. slow=options.slow,
  356. )
  357. except Exception:
  358. # Avoid reporting any issues recursively back into Sentry
  359. import sys
  360. import traceback
  361. traceback.print_exc()
  362. sys.exit(1)