mock-traces 12 KB

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