def _compute_speedscope(self): for execution in self: sp = Speedscope(init_stack_trace=json.loads(execution.init_stack_trace)) if execution.sql: sp.add('sql', json.loads(execution.sql)) if execution.traces_async: sp.add('frames', json.loads(execution.traces_async)) if execution.traces_sync: sp.add('settrace', json.loads(execution.traces_sync)) result = json.dumps(sp.add_default().make()) execution.speedscope = base64.b64encode(result.encode('utf-8'))
def test_end_priority(self): """ If a sample as a time (usually a query) we expect to keep the complete frame even if another concurent frame tics before the end of the current one: frame duration should always be more reliable. """ async_profile = self.example_profile()['result'] sql_profile = self.example_profile()['result'] # make sql_profile a single frame from 2.5 to 5.5 sql_profile = [sql_profile[1]] sql_profile[0]['start'] = 2.5 sql_profile[0]['time'] = 3 sql_profile[0]['query'] = 'SELECT 1' sql_profile[0]['full_query'] = 'SELECT 1' # some check to ensure the take makes sence self.assertEqual(async_profile[1]['start'], 3) self.assertEqual(async_profile[2]['start'], 4) self.assertNotIn('query', async_profile[1]['stack']) self.assertNotIn('time', async_profile[1]['stack']) self.assertEqual(async_profile[1]['stack'], async_profile[2]['stack']) # this last assertion is not really useful but ensures that the samples # are consistent with the sql one, just missing tue query sp = Speedscope(init_stack_trace=[]) sp.add('sql', async_profile) sp.add('traces', sql_profile) sp.add_output(['sql', 'traces'], complete=False) res = sp.make() profile_combined = res['profiles'][0] events = [(e['at'] + 2, e['type'], res['shared']['frames'][e['frame']]['name']) for e in profile_combined['events']] self.assertEqual( events, [ # pylint: disable=bad-continuation (2.0, 'O', 'main'), (2.0, 'O', 'do_stuff1'), (2.5, 'O', 'execute'), (2.5, 'O', "sql('SELECT 1')"), ( 5.5, 'C', "sql('SELECT 1')" ), # select ends at 5.5 as expected despite another concurent frame at 3 and 4 (5.5, 'C', 'execute'), (6.0, 'O', 'check'), (10.0, 'C', 'check'), (10.35, 'C', 'do_stuff1'), (10.35, 'C', 'main'), ])
def test_converts_profile_simple(self): profile = self.example_profile() sp = Speedscope(init_stack_trace=profile['init_stack_trace']) sp.add('profile', profile['result']) sp.add_output(['profile'], complete=False) res = sp.make() frames = res['shared']['frames'] self.assertEqual(len(frames), 4) profile_combined = res['profiles'][0] events = [(e['type'], e['frame']) for e in profile_combined['events']] self.assertEqual( events, [ ('O', 0), # /main ('O', 1), # /main/do_stuff1 ('O', 2), # /main/do_stuff1/execute ('C', 2), # /main/do_stuff1 ('O', 3), # /main/do_stuff1/check ('C', 3), # /main/do_stuff1 ('C', 1), # /main ('C', 0), # / ]) self.assertEqual(profile_combined['events'][0]['at'], 0.0) self.assertEqual(profile_combined['events'][-1]['at'], 8.35)
def test_converts_context(self): stack = [ ['file.py', 10, 'level1', 'level1'], ['file.py', 11, 'level2', 'level2'], ] profile = { 'init_stack_trace': [['file.py', 1, 'level0', 'level0)']], 'result': [{ # init frame 'start': 2.0, 'exec_context': ((2, {'a': '1'}), (3, {'b': '1'})), 'stack': list(stack), }, { 'start': 3.0, 'exec_context': ((2, {'a': '1'}), (3, {'b': '2'})), 'stack': list(stack), }, { # final frame 'start': 10.35, 'exec_context': (), 'stack': None, }], } sp = Speedscope(init_stack_trace=profile['init_stack_trace']) sp.add('profile', profile['result']) sp.add_output(['profile'], complete=True) res = sp.make() events = [(e['type'], res['shared']['frames'][e['frame']]['name']) for e in res['profiles'][0]['events']] self.assertEqual( events, [ # pylint: disable=bad-continuation ('O', 'level0'), ('O', 'a=1'), ('O', 'level1'), ('O', 'b=1'), ('O', 'level2'), ('C', 'level2'), ('C', 'b=1'), ('O', 'b=2'), ('O', 'level2'), ('C', 'level2'), ('C', 'b=2'), ('C', 'level1'), ('C', 'a=1'), ('C', 'level0'), ])
def test_convert_empty(self): Speedscope().make()