load-mocks 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410
  1. #!/usr/bin/env python
  2. from sentry.runner import configure
  3. configure()
  4. import itertools
  5. from datetime import datetime, timedelta
  6. from django.conf import settings
  7. from django.db import IntegrityError, transaction
  8. from django.utils import timezone
  9. from hashlib import md5
  10. from pytz import utc
  11. from random import randint
  12. from sentry import roles
  13. from sentry.app import tsdb, buffer
  14. from sentry.models import (
  15. Activity, Broadcast, File, GroupMeta, Organization, OrganizationAccessRequest,
  16. OrganizationMember, Project, Release, ReleaseFile, Team, User, UserReport
  17. )
  18. from sentry.utils.samples import create_sample_event
  19. PLATFORMS = itertools.cycle([
  20. 'ruby',
  21. 'php',
  22. 'python',
  23. 'java',
  24. 'javascript',
  25. ])
  26. LEVELS = itertools.cycle([
  27. 'error',
  28. 'error',
  29. 'error',
  30. 'fatal',
  31. 'warning',
  32. ])
  33. def create_system_time_series():
  34. now = datetime.utcnow().replace(tzinfo=utc)
  35. for _ in xrange(60):
  36. count = randint(1, 10)
  37. tsdb.incr_multi((
  38. (tsdb.models.internal, 'client-api.all-versions.responses.2xx'),
  39. (tsdb.models.internal, 'client-api.all-versions.requests'),
  40. ), now, int(count * 0.9))
  41. tsdb.incr_multi((
  42. (tsdb.models.internal, 'client-api.all-versions.responses.4xx'),
  43. ), now, int(count * 0.05))
  44. tsdb.incr_multi((
  45. (tsdb.models.internal, 'client-api.all-versions.responses.5xx'),
  46. ), now, int(count * 0.1))
  47. now = now - timedelta(seconds=1)
  48. for _ in xrange(24 * 30):
  49. count = randint(100, 1000)
  50. tsdb.incr_multi((
  51. (tsdb.models.internal, 'client-api.all-versions.responses.2xx'),
  52. (tsdb.models.internal, 'client-api.all-versions.requests'),
  53. ), now, int(count * 4.9))
  54. tsdb.incr_multi((
  55. (tsdb.models.internal, 'client-api.all-versions.responses.4xx'),
  56. ), now, int(count * 0.05))
  57. tsdb.incr_multi((
  58. (tsdb.models.internal, 'client-api.all-versions.responses.5xx'),
  59. ), now, int(count * 0.1))
  60. now = now - timedelta(hours=1)
  61. def create_sample_time_series(event):
  62. group = event.group
  63. now = datetime.utcnow().replace(tzinfo=utc)
  64. for _ in xrange(60):
  65. count = randint(1, 10)
  66. tsdb.incr_multi((
  67. (tsdb.models.project, group.project.id),
  68. (tsdb.models.group, group.id),
  69. ), now, count)
  70. tsdb.incr_multi((
  71. (tsdb.models.organization_total_received, group.project.organization_id),
  72. (tsdb.models.project_total_received, group.project.id),
  73. ), now, int(count * 1.1))
  74. tsdb.incr_multi((
  75. (tsdb.models.organization_total_rejected, group.project.organization_id),
  76. (tsdb.models.project_total_rejected, group.project.id),
  77. ), now, int(count * 0.1))
  78. now = now - timedelta(seconds=1)
  79. for _ in xrange(24 * 30):
  80. count = randint(100, 1000)
  81. tsdb.incr_multi((
  82. (tsdb.models.project, group.project.id),
  83. (tsdb.models.group, group.id),
  84. ), now, count)
  85. tsdb.incr_multi((
  86. (tsdb.models.organization_total_received, group.project.organization_id),
  87. (tsdb.models.project_total_received, group.project.id),
  88. ), now, int(count * 1.1))
  89. tsdb.incr_multi((
  90. (tsdb.models.organization_total_rejected, group.project.organization_id),
  91. (tsdb.models.project_total_rejected, group.project.id),
  92. ), now, int(count * 0.1))
  93. now = now - timedelta(hours=1)
  94. epoch = datetime.utcfromtimestamp(0)
  95. def milliseconds_ago(now, milliseconds):
  96. ago = (now - timedelta(milliseconds=milliseconds))
  97. return (ago - epoch).total_seconds()
  98. def get_sample_breadcrumbs(prior_event_id=None):
  99. now = datetime.now()
  100. sample_breadcrumbs = {
  101. "values": [
  102. {
  103. "type": "navigation",
  104. "timestamp": milliseconds_ago(now, 5200),
  105. "category": "react-router",
  106. "data": {
  107. "from": "/login/",
  108. "to": "/dashboard/",
  109. }
  110. },
  111. {
  112. "timestamp": milliseconds_ago(now, 4000),
  113. "message": "This is an info log message",
  114. "category": "django"
  115. },
  116. {
  117. "timestamp": milliseconds_ago(now, 3300),
  118. "message": "This is a warning log message",
  119. "level": "warning",
  120. "category": 'django'
  121. },
  122. {
  123. "timestamp": milliseconds_ago(now, 2700),
  124. "message": "This is an error log message",
  125. "level": "error",
  126. "category": 'django'
  127. },
  128. {
  129. "timestamp": milliseconds_ago(now, 2700),
  130. "message": "This is a critical log message",
  131. "level": "critical",
  132. "category": 'django'
  133. },
  134. {
  135. "timestamp": milliseconds_ago(now, 2700),
  136. "message": "This is a debug log message",
  137. "level": "debug",
  138. "category": 'django',
  139. "data": {
  140. "foo": "bar",
  141. "baz": "blah"
  142. }
  143. },
  144. {
  145. "type": "http",
  146. "category": "requests",
  147. "timestamp": milliseconds_ago(now, 1300),
  148. "data": {
  149. "reason": "OK",
  150. "status_code": 200,
  151. "url": "Http://example.com/",
  152. "method": "POST"
  153. }
  154. },
  155. {
  156. "type": "query",
  157. "category": "django",
  158. "timestamp": milliseconds_ago(now, 1200),
  159. "message": u'SELECT "auth_user"."password", "auth_user"."last_login", "auth_user"."id", "auth_user"."username", "auth_user"."first_name", "auth_user"."email", "auth_user"."is_staff", "auth_user"."is_active", "auth_user"."is_superuser", "auth_user"."is_managed", "auth_user"."date_joined" FROM "auth_user" WHERE "auth_user"."id" = 1',
  160. "duration": 0.002
  161. },
  162. {
  163. "type": "ui",
  164. "timestamp": milliseconds_ago(now, 1000),
  165. "message": "div > form[name=\"post\"] > button.btn.btn-small[name=\"submit\"]",
  166. "category": 'ui.click'
  167. }
  168. ]
  169. }
  170. if prior_event_id:
  171. sample_breadcrumbs["values"].insert(2, {
  172. "type": "error",
  173. "timestamp": milliseconds_ago(now, 3000),
  174. "message": "TypeError: something broke earlier",
  175. "category": "error",
  176. "event_id": prior_event_id
  177. })
  178. return sample_breadcrumbs
  179. def main(num_events=1):
  180. user = User.objects.filter(is_superuser=True)[0]
  181. dummy_user, _ = User.objects.get_or_create(
  182. username='dummy@example.com',
  183. defaults={
  184. 'email': 'dummy@example.com',
  185. }
  186. )
  187. dummy_user.set_password('dummy')
  188. dummy_user.save()
  189. mocks = (
  190. ('Massive Dynamic', ('Ludic Science',)),
  191. ('Captain Planet', ('Earth', 'Fire', 'Wind', 'Water', 'Heart')),
  192. )
  193. Broadcast.objects.create(
  194. title="Learn about Source Maps",
  195. message="Source maps are JSON files that contain information on how to map your transpiled source code back to their original source.",
  196. link="https://docs.getsentry.com/hosted/clients/javascript/sourcemaps/#uploading-source-maps-to-sentry",
  197. )
  198. if settings.SENTRY_SINGLE_ORGANIZATION:
  199. org = Organization.get_default()
  200. else:
  201. print('Mocking org {}'.format('Default'))
  202. org, _ = Organization.objects.get_or_create(
  203. slug='default',
  204. )
  205. OrganizationMember.objects.get_or_create(
  206. user=user,
  207. organization=org,
  208. role=roles.get_top_dog().id,
  209. )
  210. dummy_member, _ = OrganizationMember.objects.get_or_create(
  211. user=dummy_user,
  212. organization=org,
  213. defaults={
  214. 'role': roles.get_default().id,
  215. }
  216. )
  217. for team_name, project_names in mocks:
  218. print('> Mocking team {}'.format(team_name))
  219. team, _ = Team.objects.get_or_create(
  220. name=team_name,
  221. defaults={
  222. 'organization': org,
  223. },
  224. )
  225. for project_name in project_names:
  226. print(' > Mocking project {}'.format(project_name))
  227. project, _ = Project.objects.get_or_create(
  228. team=team,
  229. name=project_name,
  230. defaults={
  231. 'organization': org,
  232. 'first_event': timezone.now(),
  233. }
  234. )
  235. release = Release.objects.get_or_create(
  236. version='4f38b65c62c4565aa94bba391ff8946922a8eed4',
  237. project=project,
  238. )[0]
  239. ReleaseFile.objects.get_or_create(
  240. project=project,
  241. release=release,
  242. name='an-example.js',
  243. file=File.objects.get_or_create(
  244. name='an-example.js',
  245. type='release.file',
  246. checksum='abcde' * 8,
  247. size=13043,
  248. )[0],
  249. )
  250. Activity.objects.create(
  251. type=Activity.RELEASE,
  252. project=project,
  253. ident=release.version,
  254. user=user,
  255. data={'version': release.version},
  256. )
  257. # Add a bunch of additional dummy events to support pagination
  258. last_event = None
  259. for _ in range(45):
  260. platform = PLATFORMS.next()
  261. last_event = create_sample_event(
  262. project=project,
  263. platform=platform,
  264. release=release.version,
  265. level=LEVELS.next(),
  266. message='This is a mostly useless example %s exception' % platform,
  267. checksum=md5(platform + str(_)).hexdigest(),
  268. breadcrumbs=get_sample_breadcrumbs(prior_event_id=last_event.id if last_event else None),
  269. )
  270. for _ in range(num_events):
  271. event1 = create_sample_event(
  272. project=project,
  273. platform='python',
  274. release=release.version,
  275. )
  276. event2 = create_sample_event(
  277. project=project,
  278. platform='javascript',
  279. release=release.version,
  280. breadcrumbs=get_sample_breadcrumbs(prior_event_id=event1.event_id),
  281. sdk={
  282. 'name': 'raven-js',
  283. 'version': '2.1.0',
  284. },
  285. )
  286. event3 = create_sample_event(project, 'java')
  287. event4 = create_sample_event(
  288. project=project,
  289. platform='ruby',
  290. release=release.version,
  291. )
  292. event5 = create_sample_event(
  293. project=project,
  294. platform='cocoa',
  295. release=release.version,
  296. )
  297. create_sample_event(
  298. project=project,
  299. platform='php',
  300. release=release.version,
  301. message='This is a an example PHP event with an extremely long and annoying title\nIt also happens to contain some newlines in it,\nthus making it even more annoying.',
  302. )
  303. create_sample_event(
  304. project=project,
  305. platform='csp',
  306. )
  307. with transaction.atomic():
  308. try:
  309. GroupMeta.objects.create(
  310. group=event1.group,
  311. key='github:tid',
  312. value='134',
  313. )
  314. except IntegrityError:
  315. pass
  316. UserReport.objects.create(
  317. project=project,
  318. event_id=event3.event_id,
  319. group=event3.group,
  320. name='Jane Doe',
  321. email='jane@example.com',
  322. comments='I have no idea how I got here.',
  323. )
  324. print(' > Loading time series data'.format(project_name))
  325. create_sample_time_series(event1)
  326. create_sample_time_series(event2)
  327. create_sample_time_series(event3)
  328. create_sample_time_series(event4)
  329. create_sample_time_series(event5)
  330. if hasattr(buffer, 'process_pending'):
  331. print(' > Processing pending buffers')
  332. buffer.process_pending()
  333. OrganizationAccessRequest.objects.create_or_update(
  334. member=dummy_member,
  335. team=team,
  336. )
  337. Activity.objects.create(
  338. type=Activity.RELEASE,
  339. project=project,
  340. ident='4f38b65c62c4565aa94bba391ff8946922a8eed4',
  341. user=user,
  342. data={'version': '4f38b65c62c4565aa94bba391ff8946922a8eed4'},
  343. )
  344. create_system_time_series()
  345. if __name__ == '__main__':
  346. settings.CELERY_ALWAYS_EAGER = True
  347. from optparse import OptionParser
  348. parser = OptionParser()
  349. parser.add_option('--events', dest='num_events', default=1, type=int)
  350. (options, args) = parser.parse_args()
  351. main(num_events=options.num_events)