mock-traces 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388
  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. "performance_issues": ["db-main-thread"],
  140. "children": [
  141. {
  142. "project": backend_project,
  143. "transaction": "/api/plants/",
  144. "children": [
  145. {
  146. "project": service_projects[0],
  147. "transaction": "/products/all/",
  148. "children": [],
  149. },
  150. {
  151. "project": service_projects[1],
  152. "transaction": "/analytics/",
  153. "children": [],
  154. },
  155. {
  156. "project": service_projects[2],
  157. "transaction": "tasks.create_invoice",
  158. "children": [],
  159. },
  160. ],
  161. },
  162. ],
  163. },
  164. )
  165. print(f" > Loading orphan data") # NOQA
  166. # Trace only with orphans
  167. create_trace(
  168. slow,
  169. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  170. timestamp,
  171. generate_user(),
  172. uuid4().hex,
  173. uuid4().hex[:16],
  174. {
  175. "project": frontend_project,
  176. "transaction": "/orphans/:orphanId/",
  177. "frontend": True,
  178. "children": [
  179. {
  180. "project": backend_project,
  181. "transaction": "/api/orphans/",
  182. "errors": 1,
  183. "children": [
  184. {
  185. "project": service_projects[0],
  186. "transaction": "/orphans/all/",
  187. "errors": 1,
  188. "children": [],
  189. },
  190. {
  191. "project": service_projects[1],
  192. "transaction": "/orphan/analytics/",
  193. "children": [],
  194. },
  195. {
  196. "project": service_projects[2],
  197. "transaction": "tasks.invoice_orphans",
  198. "errors": 1,
  199. "children": [],
  200. },
  201. ],
  202. },
  203. ],
  204. },
  205. )
  206. print(f" > Loading trace with many siblings") # NOQA
  207. create_trace(
  208. slow,
  209. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  210. timestamp,
  211. generate_user(),
  212. uuid4().hex,
  213. None,
  214. {
  215. "project": frontend_project,
  216. "transaction": "/siblings/:count/",
  217. "frontend": True,
  218. "children": [
  219. {
  220. "project": backend_project,
  221. "transaction": f"/api/sibling_{i}/",
  222. "children": [],
  223. }
  224. for i in range(15)
  225. ],
  226. },
  227. )
  228. print(f" > Loading trace with many roots") # NOQA
  229. trace_id = uuid4().hex
  230. for _ in range(15):
  231. create_trace(
  232. slow,
  233. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  234. timestamp,
  235. generate_user(),
  236. trace_id,
  237. None,
  238. {
  239. "project": frontend_project,
  240. "transaction": "/multiple-root/:root/",
  241. "frontend": True,
  242. "children": [
  243. {
  244. "project": backend_project,
  245. "transaction": "/multiple-root/child/",
  246. "children": [],
  247. }
  248. ],
  249. },
  250. )
  251. print(f" > Loading chained trace with orphans") # NOQA
  252. trace_id = uuid4().hex
  253. create_trace(
  254. slow,
  255. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  256. timestamp,
  257. generate_user(),
  258. trace_id,
  259. None,
  260. {
  261. "project": frontend_project,
  262. "transaction": "/chained/:login/",
  263. "frontend": True,
  264. "children": [
  265. {
  266. "project": backend_project,
  267. "transaction": "/api/auth/",
  268. "children": [
  269. {
  270. "project": service_projects[0],
  271. "transaction": "/auth/check-login/",
  272. "errors": 1,
  273. "children": [
  274. {
  275. "project": service_projects[1],
  276. "transaction": "/analytics/",
  277. "errors": 1,
  278. "children": [
  279. {
  280. "project": service_projects[2],
  281. "transaction": "tasks.check_login",
  282. "errors": 1,
  283. "children": [],
  284. }
  285. ],
  286. }
  287. ],
  288. },
  289. ],
  290. },
  291. ],
  292. },
  293. )
  294. create_trace(
  295. slow,
  296. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  297. timestamp,
  298. generate_user(),
  299. trace_id,
  300. uuid4().hex[:16],
  301. {
  302. "project": frontend_project,
  303. "transaction": "/orphans/:orphanId/",
  304. "frontend": True,
  305. "children": [
  306. {
  307. "project": backend_project,
  308. "transaction": "/api/orphans/",
  309. "errors": 1,
  310. "children": [],
  311. }
  312. ],
  313. },
  314. )
  315. print(f" > Loading traces missing instrumentation") # NOQA
  316. create_trace(
  317. slow,
  318. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  319. timestamp,
  320. generate_user(),
  321. uuid4().hex,
  322. None,
  323. {
  324. "project": frontend_project,
  325. "transaction": "/missing/:frontend/",
  326. "frontend": True,
  327. "children": [],
  328. },
  329. )
  330. create_trace(
  331. slow,
  332. timestamp - timedelta(milliseconds=random_normal(4000, 250, 1000)),
  333. timestamp,
  334. generate_user(),
  335. uuid4().hex,
  336. None,
  337. {
  338. "project": backend_project,
  339. "transaction": "/missing/backend",
  340. "children": [],
  341. },
  342. )
  343. if __name__ == "__main__":
  344. settings.CELERY_ALWAYS_EAGER = True
  345. from optparse import OptionParser
  346. parser = OptionParser()
  347. parser.add_option(
  348. "--slow",
  349. default=False,
  350. action="store_true",
  351. help="sleep between each transaction to let clickhouse rest",
  352. )
  353. (options, args) = parser.parse_args()
  354. try:
  355. main(
  356. slow=options.slow,
  357. )
  358. except Exception:
  359. # Avoid reporting any issues recursively back into Sentry
  360. import sys
  361. import traceback
  362. traceback.print_exc()
  363. sys.exit(1)