#!/usr/bin/env python from sentry.runner import configure configure() import itertools from datetime import datetime, timedelta from django.conf import settings from django.db import IntegrityError, transaction from django.utils import timezone from hashlib import md5 from pytz import utc from random import randint from sentry import roles from sentry.app import tsdb, buffer from sentry.models import ( Activity, Broadcast, File, GroupMeta, Organization, OrganizationAccessRequest, OrganizationMember, Project, Release, ReleaseFile, Team, User, UserReport ) from sentry.utils.samples import create_sample_event PLATFORMS = itertools.cycle([ 'ruby', 'php', 'python', 'java', 'javascript', ]) LEVELS = itertools.cycle([ 'error', 'error', 'error', 'fatal', 'warning', ]) def create_system_time_series(): now = datetime.utcnow().replace(tzinfo=utc) for _ in xrange(60): count = randint(1, 10) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.2xx'), (tsdb.models.internal, 'client-api.all-versions.requests'), ), now, int(count * 0.9)) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.4xx'), ), now, int(count * 0.05)) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.5xx'), ), now, int(count * 0.1)) now = now - timedelta(seconds=1) for _ in xrange(24 * 30): count = randint(100, 1000) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.2xx'), (tsdb.models.internal, 'client-api.all-versions.requests'), ), now, int(count * 4.9)) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.4xx'), ), now, int(count * 0.05)) tsdb.incr_multi(( (tsdb.models.internal, 'client-api.all-versions.responses.5xx'), ), now, int(count * 0.1)) now = now - timedelta(hours=1) def create_sample_time_series(event): group = event.group now = datetime.utcnow().replace(tzinfo=utc) for _ in xrange(60): count = randint(1, 10) tsdb.incr_multi(( (tsdb.models.project, group.project.id), (tsdb.models.group, group.id), ), now, count) tsdb.incr_multi(( (tsdb.models.organization_total_received, group.project.organization_id), (tsdb.models.project_total_received, group.project.id), ), now, int(count * 1.1)) tsdb.incr_multi(( (tsdb.models.organization_total_rejected, group.project.organization_id), (tsdb.models.project_total_rejected, group.project.id), ), now, int(count * 0.1)) now = now - timedelta(seconds=1) for _ in xrange(24 * 30): count = randint(100, 1000) tsdb.incr_multi(( (tsdb.models.project, group.project.id), (tsdb.models.group, group.id), ), now, count) tsdb.incr_multi(( (tsdb.models.organization_total_received, group.project.organization_id), (tsdb.models.project_total_received, group.project.id), ), now, int(count * 1.1)) tsdb.incr_multi(( (tsdb.models.organization_total_rejected, group.project.organization_id), (tsdb.models.project_total_rejected, group.project.id), ), now, int(count * 0.1)) now = now - timedelta(hours=1) epoch = datetime.utcfromtimestamp(0) def milliseconds_ago(now, milliseconds): ago = (now - timedelta(milliseconds=milliseconds)) return (ago - epoch).total_seconds() def get_sample_breadcrumbs(prior_event_id=None): now = datetime.now() sample_breadcrumbs = { "values": [ { "type": "navigation", "timestamp": milliseconds_ago(now, 5200), "category": "react-router", "data": { "from": "/login/", "to": "/dashboard/", } }, { "timestamp": milliseconds_ago(now, 4000), "message": "This is an info log message", "category": "django" }, { "timestamp": milliseconds_ago(now, 3300), "message": "This is a warning log message", "level": "warning", "category": 'django' }, { "timestamp": milliseconds_ago(now, 2700), "message": "This is an error log message", "level": "error", "category": 'django' }, { "timestamp": milliseconds_ago(now, 2700), "message": "This is a critical log message", "level": "critical", "category": 'django' }, { "timestamp": milliseconds_ago(now, 2700), "message": "This is a debug log message", "level": "debug", "category": 'django', "data": { "foo": "bar", "baz": "blah" } }, { "type": "http", "category": "requests", "timestamp": milliseconds_ago(now, 1300), "data": { "reason": "OK", "status_code": 200, "url": "Http://example.com/", "method": "POST" } }, { "type": "query", "category": "django", "timestamp": milliseconds_ago(now, 1200), "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', "duration": 0.002 }, { "type": "ui", "timestamp": milliseconds_ago(now, 1000), "message": "div > form[name=\"post\"] > button.btn.btn-small[name=\"submit\"]", "category": 'ui.click' } ] } if prior_event_id: sample_breadcrumbs["values"].insert(2, { "type": "error", "timestamp": milliseconds_ago(now, 3000), "message": "TypeError: something broke earlier", "category": "error", "event_id": prior_event_id }) return sample_breadcrumbs def main(num_events=1): user = User.objects.filter(is_superuser=True)[0] dummy_user, _ = User.objects.get_or_create( username='dummy@example.com', defaults={ 'email': 'dummy@example.com', } ) dummy_user.set_password('dummy') dummy_user.save() mocks = ( ('Massive Dynamic', ('Ludic Science',)), ('Captain Planet', ('Earth', 'Fire', 'Wind', 'Water', 'Heart')), ) Broadcast.objects.create( title="Learn about Source Maps", message="Source maps are JSON files that contain information on how to map your transpiled source code back to their original source.", link="https://docs.getsentry.com/hosted/clients/javascript/sourcemaps/#uploading-source-maps-to-sentry", ) if settings.SENTRY_SINGLE_ORGANIZATION: org = Organization.get_default() else: print('Mocking org {}'.format('Default')) org, _ = Organization.objects.get_or_create( slug='default', ) OrganizationMember.objects.get_or_create( user=user, organization=org, role=roles.get_top_dog().id, ) dummy_member, _ = OrganizationMember.objects.get_or_create( user=dummy_user, organization=org, defaults={ 'role': roles.get_default().id, } ) for team_name, project_names in mocks: print('> Mocking team {}'.format(team_name)) team, _ = Team.objects.get_or_create( name=team_name, defaults={ 'organization': org, }, ) for project_name in project_names: print(' > Mocking project {}'.format(project_name)) project, _ = Project.objects.get_or_create( team=team, name=project_name, defaults={ 'organization': org, 'first_event': timezone.now(), } ) release = Release.objects.get_or_create( version='4f38b65c62c4565aa94bba391ff8946922a8eed4', project=project, )[0] ReleaseFile.objects.get_or_create( project=project, release=release, name='an-example.js', file=File.objects.get_or_create( name='an-example.js', type='release.file', checksum='abcde' * 8, size=13043, )[0], ) Activity.objects.create( type=Activity.RELEASE, project=project, ident=release.version, user=user, data={'version': release.version}, ) # Add a bunch of additional dummy events to support pagination last_event = None for _ in range(45): platform = PLATFORMS.next() last_event = create_sample_event( project=project, platform=platform, release=release.version, level=LEVELS.next(), message='This is a mostly useless example %s exception' % platform, checksum=md5(platform + str(_)).hexdigest(), breadcrumbs=get_sample_breadcrumbs(prior_event_id=last_event.id if last_event else None), ) for _ in range(num_events): event1 = create_sample_event( project=project, platform='python', release=release.version, ) event2 = create_sample_event( project=project, platform='javascript', release=release.version, breadcrumbs=get_sample_breadcrumbs(prior_event_id=event1.event_id), sdk={ 'name': 'raven-js', 'version': '2.1.0', }, ) event3 = create_sample_event(project, 'java') event4 = create_sample_event( project=project, platform='ruby', release=release.version, ) event5 = create_sample_event( project=project, platform='cocoa', release=release.version, ) create_sample_event( project=project, platform='php', release=release.version, 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.', ) create_sample_event( project=project, platform='csp', ) with transaction.atomic(): try: GroupMeta.objects.create( group=event1.group, key='github:tid', value='134', ) except IntegrityError: pass UserReport.objects.create( project=project, event_id=event3.event_id, group=event3.group, name='Jane Doe', email='jane@example.com', comments='I have no idea how I got here.', ) print(' > Loading time series data'.format(project_name)) create_sample_time_series(event1) create_sample_time_series(event2) create_sample_time_series(event3) create_sample_time_series(event4) create_sample_time_series(event5) if hasattr(buffer, 'process_pending'): print(' > Processing pending buffers') buffer.process_pending() OrganizationAccessRequest.objects.create_or_update( member=dummy_member, team=team, ) Activity.objects.create( type=Activity.RELEASE, project=project, ident='4f38b65c62c4565aa94bba391ff8946922a8eed4', user=user, data={'version': '4f38b65c62c4565aa94bba391ff8946922a8eed4'}, ) create_system_time_series() if __name__ == '__main__': settings.CELERY_ALWAYS_EAGER = True from optparse import OptionParser parser = OptionParser() parser.add_option('--events', dest='num_events', default=1, type=int) (options, args) = parser.parse_args() main(num_events=options.num_events)