def test_get_two(self): some_date = dateparse.parse_datetime('2018-10-06T00:22:58.074859+00:00') models.Signature.objects.create( signature='OOM | Small', first_build='20180920131237', first_date=some_date ) models.Signature.objects.create( signature='OOM | Large', first_build='20180920131237', first_date=some_date ) api = models.SignatureFirstDate() resp = api.get(signatures=['OOM | Small', 'OOM | Large']) assert resp['total'] == 2 assert resp['hits'] == [ { 'first_build': '20180920131237', 'first_date': '2018-10-06T00:22:58.074859+00:00', 'signature': 'OOM | Small' }, { 'first_build': '20180920131237', 'first_date': '2018-10-06T00:22:58.074859+00:00', 'signature': 'OOM | Large' } ]
def test_get_two(self): some_date = dateparse.parse_datetime( "2018-10-06T00:22:58.074859+00:00") models.Signature.objects.create(signature="OOM | Small", first_build="20180920131237", first_date=some_date) models.Signature.objects.create(signature="OOM | Large", first_build="20180920131237", first_date=some_date) api = models.SignatureFirstDate() resp = api.get(signatures=["OOM | Small", "OOM | Large"]) assert resp["total"] == 2 assert resp["hits"] == [ { "first_build": "20180920131237", "first_date": "2018-10-06T00:22:58.074859+00:00", "signature": "OOM | Small", }, { "first_build": "20180920131237", "first_date": "2018-10-06T00:22:58.074859+00:00", "signature": "OOM | Large", }, ]
def test_signature_first_date(self): api = models.SignatureFirstDate() def mocked_get(**options): return {'hits': [], 'total': 0} models.SignatureFirstDate.implementation().get.side_effect = mocked_get r = api.get(signatures=['Pickle::ReadBytes', 'FakeSignature'], ) eq_(r['total'], 0)
def topcrashers(request, days=None, possible_days=None, default_context=None): context = default_context or {} product = request.GET.get('product') versions = request.GET.getlist('version') crash_type = request.GET.get('process_type') os_name = request.GET.get('platform') result_count = request.GET.get('_facets_size') tcbs_mode = request.GET.get('_tcbs_mode') range_type = request.GET.get('_range_type') range_type = 'build' if range_type == 'build' else 'report' if not tcbs_mode or tcbs_mode not in ('realtime', 'byday'): tcbs_mode = 'realtime' if product not in context['active_versions']: raise http.Http404('Unrecognized product') context['product'] = product if not versions: # :( # simulate what the nav.js does which is to take the latest version # for this product. for pv in context['active_versions'][product]: if pv['is_featured']: url = '%s&version=%s' % (request.build_absolute_uri(), urlquote(pv['version'])) return redirect(url) # See if all versions support builds. If not, refuse to show the "by build" # range option in the UI. versions_have_builds = True for version in versions: for pv in context['active_versions'][product]: if pv['version'] == version and not pv['has_builds']: versions_have_builds = False break context['versions_have_builds'] = versions_have_builds # Used to pick a version in the dropdown menu. context['version'] = versions[0] if tcbs_mode == 'realtime': end_date = timezone.now().replace(microsecond=0) elif tcbs_mode == 'byday': end_date = timezone.now().replace(hour=0, minute=0, second=0, microsecond=0) # settings.PROCESS_TYPES might contain tuple to indicate that some # are actual labels. process_types = [] for option in settings.PROCESS_TYPES: if isinstance(option, (list, tuple)): process_types.append(option[0]) else: process_types.append(option) if crash_type not in process_types: crash_type = 'browser' context['crash_type'] = crash_type os_api = models.Platforms() operating_systems = os_api.get() if os_name not in (os_['name'] for os_ in operating_systems): os_name = None context['os_name'] = os_name # set the result counts filter in the context to use in # the template. This way we avoid hardcoding it twice and # have it defined in one common location. context['result_counts'] = settings.TCBS_RESULT_COUNTS if result_count not in context['result_counts']: result_count = settings.TCBS_RESULT_COUNTS[0] context['result_count'] = result_count context['query'] = { 'product': product, 'versions': versions, 'crash_type': crash_type, 'os_name': os_name, 'result_count': unicode(result_count), 'mode': tcbs_mode, 'range_type': range_type, 'end_date': end_date, 'start_date': end_date - datetime.timedelta(days=days), } api_results = get_topcrashers_results( product=product, version=versions, platform=os_name, process_type=crash_type, date=[ '<' + end_date.isoformat(), '>=' + context['query']['start_date'].isoformat() ], _facets_size=result_count, _range_type=range_type, ) if api_results['total'] > 0: tcbs = api_results['facets']['signature'] else: tcbs = [] count_of_included_crashes = 0 signatures = [] for crash in tcbs[:int(result_count)]: signatures.append(crash['signature']) count_of_included_crashes += crash['count'] context['number_of_crashes'] = count_of_included_crashes context['total_percentage'] = api_results['total'] and ( 100.0 * count_of_included_crashes / api_results['total']) # Get augmented bugs data. bugs = defaultdict(list) if signatures: bugs_api = models.Bugs() for b in bugs_api.get(signatures=signatures)['hits']: bugs[b['signature']].append(b['id']) # Get augmented signature data. sig_date_data = {} if signatures: sig_api = models.SignatureFirstDate() # SignatureFirstDate().get_dates() is an optimized version # of SignatureFirstDate().get() that returns a dict of # signature --> dates. first_dates = sig_api.get_dates(signatures) for sig, dates in first_dates.items(): sig_date_data[sig] = dates['first_date'] for crash in tcbs: crash_counts = [] # Due to the inconsistencies of OS usage and naming of # codes and props for operating systems the hacky bit below # is required. Socorro and the world will be a better place # once https://bugzilla.mozilla.org/show_bug.cgi?id=790642 lands. for operating_system in operating_systems: if operating_system['name'] == 'Unknown': # not applicable in this context continue os_code = operating_system['code'][0:3].lower() key = '%s_count' % os_code crash_counts.append([crash[key], operating_system['name']]) crash['correlation_os'] = max(crash_counts)[1] sig = crash['signature'] # Augment with bugs. if sig in bugs: if 'bugs' in crash: crash['bugs'].extend(bugs[sig]) else: crash['bugs'] = bugs[sig] # Augment with first appearance dates. if sig in sig_date_data: crash['first_report'] = sig_date_data[sig] if 'bugs' in crash: crash['bugs'].sort(reverse=True) context['tcbs'] = tcbs context['days'] = days context['report'] = 'topcrasher' context['possible_days'] = possible_days context['total_crashing_signatures'] = len(signatures) context['total_number_of_crashes'] = api_results['total'] context['process_type_values'] = [] for option in settings.PROCESS_TYPES: if option == 'all': continue if isinstance(option, (list, tuple)): value, label = option else: value = option label = option.capitalize() context['process_type_values'].append((value, label)) context['platform_values'] = settings.DISPLAY_OS_NAMES return render(request, 'topcrashers/topcrashers.html', context)
def test_signature_first_date_get_dates(self): api = models.SignatureFirstDate() now = timezone.now() tomorrow = now + datetime.timedelta(days=1) tomorrow_tomorrow = tomorrow + datetime.timedelta(days=1) def mocked_get(**kwargs): signatures = kwargs['signatures'] # This mocking function really makes sure that only what is # expected to be called for is called for. # Basically, the first time it expects to be asked # about 'Sig 1' and 'Sig 2'. # The second time it expect to only be asked about 'Sig 3'. # Anything else will raise a NotImplementedError. if sorted(signatures) == ['Sig 1', 'Sig 2']: return { 'hits': [{ 'signature': 'Sig 1', 'first_build': '201601010101', 'first_date': now, }, { 'signature': 'Sig 2', 'first_build': '201602020202', 'first_date': tomorrow, }], 'total': 2 } elif sorted(signatures) == ['Sig 3']: return { 'hits': [{ 'signature': 'Sig 3', 'first_build': '201603030303', 'first_date': tomorrow_tomorrow, }], 'total': 1 } raise NotImplementedError(signatures) models.SignatureFirstDate.implementation().get.side_effect = mocked_get r = api.get_dates(['Sig 1', 'Sig 2']) eq_( r, { 'Sig 1': { 'first_build': '201601010101', 'first_date': now, }, 'Sig 2': { 'first_build': '201602020202', 'first_date': tomorrow, }, }) r = api.get_dates(['Sig 2', 'Sig 3']) eq_( r, { 'Sig 2': { 'first_build': '201602020202', 'first_date': tomorrow, }, 'Sig 3': { 'first_build': '201603030303', 'first_date': tomorrow_tomorrow, }, })
def topcrashers(request, days=None, possible_days=None, default_context=None): context = default_context or {} product = request.GET.get('product') versions = request.GET.get('version') crash_type = request.GET.get('process_type') os_name = request.GET.get('platform') result_count = request.GET.get('_facets_size') tcbs_mode = request.GET.get('_tcbs_mode') if not tcbs_mode or tcbs_mode not in ('realtime', 'byday'): tcbs_mode = 'realtime' if product not in context['releases']: raise http.Http404('Unrecognized product') context['product'] = product if not versions: # :( # simulate what the nav.js does which is to take the latest version # for this product. for release in context['currentversions']: if release['product'] == product and release['featured']: url = '%s&version=%s' % (request.build_absolute_uri(), urlquote(release['version'])) return redirect(url) else: versions = versions.split(';') context['version'] = versions[0] if tcbs_mode == 'realtime': end_date = datetime.datetime.utcnow().replace(microsecond=0) elif tcbs_mode == 'byday': end_date = datetime.datetime.utcnow().replace(hour=0, minute=0, second=0, microsecond=0) if crash_type not in settings.PROCESS_TYPES: crash_type = 'browser' context['crash_type'] = crash_type os_api = models.Platforms() operating_systems = os_api.get() if os_name not in (os_['name'] for os_ in operating_systems): os_name = None context['os_name'] = os_name # set the result counts filter in the context to use in # the template. This way we avoid hardcoding it twice and # have it defined in one common location. context['result_counts'] = settings.TCBS_RESULT_COUNTS if result_count not in context['result_counts']: result_count = settings.TCBS_RESULT_COUNTS[0] context['result_count'] = result_count context['query'] = { 'product': product, 'versions': versions[0], 'crash_type': crash_type, 'os_name': os_name, 'result_count': unicode(result_count), 'mode': tcbs_mode, 'end_date': end_date, 'start_date': end_date - datetime.timedelta(days=days), } api_results = get_topcrashers_results( product=product, version=context['version'], platform=os_name, process_type=crash_type, date=[ '<' + end_date.isoformat(), '>=' + context['query']['start_date'].isoformat() ], _facets_size=result_count, ) if api_results['total'] > 0: tcbs = api_results['facets']['signature'] else: tcbs = [] count_of_included_crashes = 0 signatures = [] for crash in tcbs[:int(result_count)]: signatures.append(crash['signature']) count_of_included_crashes += crash['count'] context['number_of_crashes'] = count_of_included_crashes context['total_percentage'] = api_results['total'] and ( 100.0 * count_of_included_crashes / api_results['total']) # Get augmented bugs data. bugs = defaultdict(list) if signatures: bugs_api = models.Bugs() for b in bugs_api.get(signatures=signatures)['hits']: bugs[b['signature']].append(b['id']) # Get augmented signature data. sig_date_data = {} if signatures: sig_api = models.SignatureFirstDate() first_dates = sig_api.get(signatures=signatures) for sig in first_dates['hits']: sig_date_data[sig['signature']] = sig['first_date'] for crash in tcbs: crash_counts = [] # Due to the inconsistencies of OS usage and naming of # codes and props for operating systems the hacky bit below # is required. Socorro and the world will be a better place # once https://bugzilla.mozilla.org/show_bug.cgi?id=790642 lands. for operating_system in operating_systems: if operating_system['name'] == 'Unknown': # not applicable in this context continue os_code = operating_system['code'][0:3].lower() key = '%s_count' % os_code crash_counts.append([crash[key], operating_system['name']]) crash['correlation_os'] = max(crash_counts)[1] sig = crash['signature'] # Augment with bugs. if sig in bugs: if 'bugs' in crash: crash['bugs'].extend(bugs[sig]) else: crash['bugs'] = bugs[sig] # Augment with first appearance dates. if sig in sig_date_data: crash['first_report'] = isodate.parse_datetime(sig_date_data[sig]) if 'bugs' in crash: crash['bugs'].sort(reverse=True) context['tcbs'] = tcbs context['days'] = days context['report'] = 'topcrasher' context['possible_days'] = possible_days context['total_crashing_signatures'] = len(signatures) context['total_number_of_crashes'] = api_results['total'] context['process_type_values'] = (x for x in settings.PROCESS_TYPES if x != 'all') context['platform_values'] = settings.DISPLAY_OS_NAMES return render(request, 'topcrashers/topcrashers.html', context)