class Test_profile_log(unittest.TestCase): def setUp(self): if xprofile is None: raise SkipTest self.dir1 = tempfile.mkdtemp() self.log_filename_prefix1 = self.dir1 + '/unittest.profile' self.profile_log1 = ProfileLog(self.log_filename_prefix1, False) self.pids1 = ['123', '456', str(os.getpid())] profiler1 = xprofile.get_profiler('eventlet.green.profile') for pid in self.pids1: profiler1.runctx('import os;os.getcwd();', globals(), locals()) self.profile_log1.dump_profile(profiler1, pid) self.dir2 = tempfile.mkdtemp() self.log_filename_prefix2 = self.dir2 + '/unittest.profile' self.profile_log2 = ProfileLog(self.log_filename_prefix2, True) self.pids2 = ['321', '654', str(os.getpid())] profiler2 = xprofile.get_profiler('eventlet.green.profile') for pid in self.pids2: profiler2.runctx('import os;os.getcwd();', globals(), locals()) self.profile_log2.dump_profile(profiler2, pid) def tearDown(self): self.profile_log1.clear('all') self.profile_log2.clear('all') shutil.rmtree(self.dir1, ignore_errors=True) shutil.rmtree(self.dir2, ignore_errors=True) def test_get_all_pids(self): self.assertEquals(self.profile_log1.get_all_pids(), sorted(self.pids1, reverse=True)) for pid in self.profile_log2.get_all_pids(): self.assertTrue(pid.split('-')[0] in self.pids2) def test_clear(self): self.profile_log1.clear('123') self.assertFalse(os.path.exists(self.log_filename_prefix1 + '123')) self.profile_log1.clear('current') self.assertFalse(os.path.exists(self.log_filename_prefix1 + str(os.getpid()))) self.profile_log1.clear('all') for pid in self.pids1: self.assertFalse(os.path.exists(self.log_filename_prefix1 + pid)) self.profile_log2.clear('321') self.assertFalse(os.path.exists(self.log_filename_prefix2 + '321')) self.profile_log2.clear('current') self.assertFalse(os.path.exists(self.log_filename_prefix2 + str(os.getpid()))) self.profile_log2.clear('all') for pid in self.pids2: self.assertFalse(os.path.exists(self.log_filename_prefix2 + pid)) def test_get_logfiles(self): log_files = self.profile_log1.get_logfiles('all') self.assertEqual(len(log_files), 3) self.assertEquals(len(log_files), len(self.pids1)) log_files = self.profile_log1.get_logfiles('current') self.assertEqual(len(log_files), 1) self.assertEquals(log_files, [self.log_filename_prefix1 + str(os.getpid())]) log_files = self.profile_log1.get_logfiles(self.pids1[0]) self.assertEqual(len(log_files), 1) self.assertEquals(log_files, [self.log_filename_prefix1 + self.pids1[0]]) log_files = self.profile_log2.get_logfiles('all') self.assertEqual(len(log_files), 3) self.assertEquals(len(log_files), len(self.pids2)) log_files = self.profile_log2.get_logfiles('current') self.assertEqual(len(log_files), 1) self.assertTrue(log_files[0].find(self.log_filename_prefix2 + str(os.getpid())) > -1) log_files = self.profile_log2.get_logfiles(self.pids2[0]) self.assertEqual(len(log_files), 1) self.assertTrue(log_files[0].find(self.log_filename_prefix2 + self.pids2[0]) > -1) def test_dump_profile(self): prof = xprofile.get_profiler('eventlet.green.profile') prof.runctx('import os;os.getcwd();', globals(), locals()) prof.create_stats() pfn = self.profile_log1.dump_profile(prof, os.getpid()) self.assertTrue(os.path.exists(pfn)) os.remove(pfn) pfn = self.profile_log2.dump_profile(prof, os.getpid()) self.assertTrue(os.path.exists(pfn)) os.remove(pfn)
class ProfileMiddleware(object): def __init__(self, app, conf): self.app = app self.logger = get_logger(conf, log_route='profile') self.log_filename_prefix = conf.get('log_filename_prefix', DEFAULT_PROFILE_PREFIX) dirname = os.path.dirname(self.log_filename_prefix) # Notes: this effort may fail due to permission denied. # it is better to be created and authorized to current # user in advance. if not os.path.exists(dirname): os.makedirs(dirname) self.dump_interval = float(conf.get('dump_interval', 5.0)) self.dump_timestamp = config_true_value(conf.get( 'dump_timestamp', 'no')) self.flush_at_shutdown = config_true_value(conf.get( 'flush_at_shutdown', 'no')) self.path = conf.get('path', '__profile__').replace('/', '') self.unwind = config_true_value(conf.get('unwind', 'no')) self.profile_module = conf.get('profile_module', 'eventlet.green.profile') self.profiler = get_profiler(self.profile_module) self.profile_log = ProfileLog(self.log_filename_prefix, self.dump_timestamp) self.viewer = HTMLViewer(self.path, self.profile_module, self.profile_log) self.dump_pool = GreenPool(1000) self.last_dump_at = None def __del__(self): if self.flush_at_shutdown: self.profile_log.clear(str(os.getpid())) def _combine_body_qs(self, request): wsgi_input = request.environ['wsgi.input'] query_dict = request.params qs_in_body = wsgi_input.read().decode('utf-8') query_dict.update(urllib.parse.parse_qs(qs_in_body, keep_blank_values=True, strict_parsing=False)) return query_dict def dump_checkpoint(self): current_time = time.time() if self.last_dump_at is None or self.last_dump_at +\ self.dump_interval < current_time: self.dump_pool.spawn_n(self.profile_log.dump_profile, self.profiler, os.getpid()) self.last_dump_at = current_time def __call__(self, environ, start_response): request = Request(environ) path_entry = request.path_info.split('/') # hijack favicon request sent by browser so that it doesn't # invoke profiling hook and contaminate the data. if path_entry[1] == 'favicon.ico': start_response('200 OK', []) return '' elif path_entry[1] == self.path: try: self.dump_checkpoint() query_dict = self._combine_body_qs(request) content, headers = self.viewer.render(request.url, request.method, path_entry, query_dict, self.renew_profile) start_response('200 OK', headers) if isinstance(content, six.text_type): content = content.encode('utf-8') return [content] except MethodNotAllowed as mx: start_response('405 Method Not Allowed', []) return '%s' % mx except NotFoundException as nx: start_response('404 Not Found', []) return '%s' % nx except ProfileException as pf: start_response('500 Internal Server Error', []) return '%s' % pf except Exception as ex: start_response('500 Internal Server Error', []) return _('Error on render profiling results: %s') % ex else: _locals = locals() code = self.unwind and PROFILE_EXEC_EAGER or\ PROFILE_EXEC_LAZY self.profiler.runctx(code, globals(), _locals) app_iter = _locals['app_iter_'] self.dump_checkpoint() return app_iter def renew_profile(self): self.profiler = get_profiler(self.profile_module)
class Test_profile_log(unittest.TestCase): def setUp(self): if xprofile is None: raise SkipTest self.dir1 = tempfile.mkdtemp() self.log_filename_prefix1 = self.dir1 + '/unittest.profile' self.profile_log1 = ProfileLog(self.log_filename_prefix1, False) self.pids1 = ['123', '456', str(os.getpid())] profiler1 = xprofile.get_profiler('eventlet.green.profile') for pid in self.pids1: profiler1.runctx('import os;os.getcwd();', globals(), locals()) self.profile_log1.dump_profile(profiler1, pid) self.dir2 = tempfile.mkdtemp() self.log_filename_prefix2 = self.dir2 + '/unittest.profile' self.profile_log2 = ProfileLog(self.log_filename_prefix2, True) self.pids2 = ['321', '654', str(os.getpid())] profiler2 = xprofile.get_profiler('eventlet.green.profile') for pid in self.pids2: profiler2.runctx('import os;os.getcwd();', globals(), locals()) self.profile_log2.dump_profile(profiler2, pid) def tearDown(self): self.profile_log1.clear('all') self.profile_log2.clear('all') shutil.rmtree(self.dir1, ignore_errors=True) shutil.rmtree(self.dir2, ignore_errors=True) def test_get_all_pids(self): self.assertEqual(self.profile_log1.get_all_pids(), sorted(self.pids1, reverse=True)) for pid in self.profile_log2.get_all_pids(): self.assertTrue(pid.split('-')[0] in self.pids2) def test_clear(self): self.profile_log1.clear('123') self.assertFalse(os.path.exists(self.log_filename_prefix1 + '123')) self.profile_log1.clear('current') self.assertFalse(os.path.exists(self.log_filename_prefix1 + str(os.getpid()))) self.profile_log1.clear('all') for pid in self.pids1: self.assertFalse(os.path.exists(self.log_filename_prefix1 + pid)) self.profile_log2.clear('321') self.assertFalse(os.path.exists(self.log_filename_prefix2 + '321')) self.profile_log2.clear('current') self.assertFalse(os.path.exists(self.log_filename_prefix2 + str(os.getpid()))) self.profile_log2.clear('all') for pid in self.pids2: self.assertFalse(os.path.exists(self.log_filename_prefix2 + pid)) def test_get_logfiles(self): log_files = self.profile_log1.get_logfiles('all') self.assertEqual(len(log_files), 3) self.assertEqual(len(log_files), len(self.pids1)) log_files = self.profile_log1.get_logfiles('current') self.assertEqual(len(log_files), 1) self.assertEqual(log_files, [self.log_filename_prefix1 + str(os.getpid())]) log_files = self.profile_log1.get_logfiles(self.pids1[0]) self.assertEqual(len(log_files), 1) self.assertEqual(log_files, [self.log_filename_prefix1 + self.pids1[0]]) log_files = self.profile_log2.get_logfiles('all') self.assertEqual(len(log_files), 3) self.assertEqual(len(log_files), len(self.pids2)) log_files = self.profile_log2.get_logfiles('current') self.assertEqual(len(log_files), 1) self.assertTrue(log_files[0].find(self.log_filename_prefix2 + str(os.getpid())) > -1) log_files = self.profile_log2.get_logfiles(self.pids2[0]) self.assertEqual(len(log_files), 1) self.assertTrue(log_files[0].find(self.log_filename_prefix2 + self.pids2[0]) > -1) def test_dump_profile(self): prof = xprofile.get_profiler('eventlet.green.profile') prof.runctx('import os;os.getcwd();', globals(), locals()) prof.create_stats() pfn = self.profile_log1.dump_profile(prof, os.getpid()) self.assertTrue(os.path.exists(pfn)) os.remove(pfn) pfn = self.profile_log2.dump_profile(prof, os.getpid()) self.assertTrue(os.path.exists(pfn)) os.remove(pfn)
class ProfileMiddleware(object): def __init__(self, app, conf): self.app = app self.logger = get_logger(conf, log_route='profile') self.log_filename_prefix = conf.get('log_filename_prefix', DEFAULT_PROFILE_PREFIX) dirname = os.path.dirname(self.log_filename_prefix) # Notes: this effort may fail due to permission denied. # it is better to be created and authorized to current # user in advance. if not os.path.exists(dirname): os.makedirs(dirname) self.dump_interval = float(conf.get('dump_interval', 5.0)) self.dump_timestamp = config_true_value( conf.get('dump_timestamp', 'no')) self.flush_at_shutdown = config_true_value( conf.get('flush_at_shutdown', 'no')) self.path = conf.get('path', '__profile__').replace('/', '') self.unwind = config_true_value(conf.get('unwind', 'no')) self.profile_module = conf.get('profile_module', 'eventlet.green.profile') self.profiler = get_profiler(self.profile_module) self.profile_log = ProfileLog(self.log_filename_prefix, self.dump_timestamp) self.viewer = HTMLViewer(self.path, self.profile_module, self.profile_log) self.dump_pool = GreenPool(1000) self.last_dump_at = None def __del__(self): if self.flush_at_shutdown: self.profile_log.clear(str(os.getpid())) def _combine_body_qs(self, request): wsgi_input = request.environ['wsgi.input'] query_dict = request.params qs_in_body = wsgi_input.read().decode('utf-8') query_dict.update( urllib.parse.parse_qs(qs_in_body, keep_blank_values=True, strict_parsing=False)) return query_dict def dump_checkpoint(self): current_time = time.time() if self.last_dump_at is None or self.last_dump_at +\ self.dump_interval < current_time: self.dump_pool.spawn_n(self.profile_log.dump_profile, self.profiler, os.getpid()) self.last_dump_at = current_time def __call__(self, environ, start_response): request = Request(environ) path_entry = request.path_info.split('/') # hijack favicon request sent by browser so that it doesn't # invoke profiling hook and contaminate the data. if path_entry[1] == 'favicon.ico': start_response('200 OK', []) return '' elif path_entry[1] == self.path: try: self.dump_checkpoint() query_dict = self._combine_body_qs(request) content, headers = self.viewer.render(request.url, request.method, path_entry, query_dict, self.renew_profile) start_response('200 OK', headers) if isinstance(content, six.text_type): content = content.encode('utf-8') return [content] except MethodNotAllowed as mx: start_response('405 Method Not Allowed', []) return '%s' % mx except NotFoundException as nx: start_response('404 Not Found', []) return '%s' % nx except ProfileException as pf: start_response('500 Internal Server Error', []) return '%s' % pf except Exception as ex: start_response('500 Internal Server Error', []) return _('Error on render profiling results: %s') % ex else: _locals = locals() code = self.unwind and PROFILE_EXEC_EAGER or\ PROFILE_EXEC_LAZY self.profiler.runctx(code, globals(), _locals) app_iter = _locals['app_iter_'] self.dump_checkpoint() return app_iter def renew_profile(self): self.profiler = get_profiler(self.profile_module)