Beispiel #1
0
 def setUp(self):
     if xprofile is None:
         raise SkipTest
     self.app = ProfileMiddleware(FakeApp, {})
     self.log_files = []
     self.tempdir = tempfile.mkdtemp()
     self.log_filename_prefix = self.tempdir + '/unittest.profile'
     self.profile_log = ProfileLog(self.log_filename_prefix, False)
     self.pids = ['123', '456', str(os.getpid())]
     profiler = xprofile.get_profiler('eventlet.green.profile')
     for pid in self.pids:
         profiler.runctx('import os;os.getcwd();', globals(), locals())
         self.log_files.append(self.profile_log.dump_profile(profiler, pid))
     self.viewer = HTMLViewer('__profile__', 'eventlet.green.profile',
                              self.profile_log)
     body = "profile=123&profile=456&sort=time&sort=nc&limit=10"\
         + "&fulldirs=1&nfl_filter=getcwd&query=query&metric=nc"
     wsgi_input = StringIO.StringIO(body)
     environ = {
         'REQUEST_METHOD': 'GET',
         'QUERY_STRING': 'profile=all',
         'wsgi.input': wsgi_input
     }
     req = Request.blank('/__profile__/', environ=environ)
     self.query_dict = self.app._combine_body_qs(req)
Beispiel #2
0
 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
Beispiel #3
0
 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
Beispiel #4
0
 def setUp(self):
     self.app = ProfileMiddleware(FakeApp, {})
     self.log_files = []
     self.tempdir = tempfile.mkdtemp()
     self.log_filename_prefix = self.tempdir + '/unittest.profile'
     self.profile_log = ProfileLog(self.log_filename_prefix, False)
     self.pids = ['123', '456', str(os.getpid())]
     profiler = xprofile.get_profiler('eventlet.green.profile')
     for pid in self.pids:
         profiler.runctx('import os;os.getcwd();', globals(), locals())
         self.log_files.append(self.profile_log.dump_profile(profiler, pid))
     self.viewer = HTMLViewer('__profile__', 'eventlet.green.profile',
                              self.profile_log)
     body = (b"profile=123&profile=456&sort=time&sort=nc&limit=10"
             b"&fulldirs=1&nfl_filter=getcwd&query=query&metric=nc")
     wsgi_input = BytesIO(body)
     environ = {'REQUEST_METHOD': 'GET',
                'QUERY_STRING': 'profile=all',
                'wsgi.input': wsgi_input}
     req = Request.blank('/__profile__/', environ=environ)
     self.query_dict = self.app._combine_body_qs(req)
Beispiel #5
0
class Test_html_viewer(unittest.TestCase):

    def setUp(self):
        if xprofile is None:
            raise SkipTest
        self.app = ProfileMiddleware(FakeApp, {})
        self.log_files = []
        self.tempdir = tempfile.mkdtemp()
        self.log_filename_prefix = self.tempdir + '/unittest.profile'
        self.profile_log = ProfileLog(self.log_filename_prefix, False)
        self.pids = ['123', '456', str(os.getpid())]
        profiler = xprofile.get_profiler('eventlet.green.profile')
        for pid in self.pids:
            profiler.runctx('import os;os.getcwd();', globals(), locals())
            self.log_files.append(self.profile_log.dump_profile(profiler, pid))
        self.viewer = HTMLViewer('__profile__', 'eventlet.green.profile',
                                 self.profile_log)
        body = (b"profile=123&profile=456&sort=time&sort=nc&limit=10"
                b"&fulldirs=1&nfl_filter=getcwd&query=query&metric=nc")
        wsgi_input = BytesIO(body)
        environ = {'REQUEST_METHOD': 'GET',
                   'QUERY_STRING': 'profile=all',
                   'wsgi.input': wsgi_input}
        req = Request.blank('/__profile__/', environ=environ)
        self.query_dict = self.app._combine_body_qs(req)

    def tearDown(self):
        shutil.rmtree(self.tempdir, ignore_errors=True)

    def fake_call_back(self):
        pass

    def test_get_param(self):
        query_dict = self.query_dict
        get_param = self.viewer._get_param
        self.assertEqual(get_param(query_dict, 'profile', 'current', True),
                         ['123', '456'])
        self.assertEqual(get_param(query_dict, 'profile', 'current'), '123')
        self.assertEqual(get_param(query_dict, 'sort', 'time'), 'time')
        self.assertEqual(get_param(query_dict, 'sort', 'time', True),
                         ['time', 'nc'])
        self.assertEqual(get_param(query_dict, 'limit', -1), 10)
        self.assertEqual(get_param(query_dict, 'fulldirs', '0'), '1')
        self.assertEqual(get_param(query_dict, 'nfl_filter', ''), 'getcwd')
        self.assertEqual(get_param(query_dict, 'query', ''), 'query')
        self.assertEqual(get_param(query_dict, 'metric', 'time'), 'nc')
        self.assertEqual(get_param(query_dict, 'format', 'default'), 'default')

    def test_render(self):
        url = 'http://localhost:8080/__profile__'
        path_entries = ['/__profile__'.split('/'),
                        '/__profile__/'.split('/'),
                        '/__profile__/123'.split('/'),
                        '/__profile__/123/'.split('/'),
                        '/__profile__/123/:0(getcwd)'.split('/'),
                        '/__profile__/all'.split('/'),
                        '/__profile__/all/'.split('/'),
                        '/__profile__/all/:0(getcwd)'.split('/'),
                        '/__profile__/current'.split('/'),
                        '/__profile__/current/'.split('/'),
                        '/__profile__/current/:0(getcwd)'.split('/')]

        content, headers = self.viewer.render(url, 'GET', path_entries[0],
                                              self.query_dict, None)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              self.query_dict, None)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        plot_dict = self.query_dict.copy()
        plot_dict['plot'] = ['plot']
        if PLOTLIB_INSTALLED:
            content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                                  plot_dict, None)
            self.assertEqual(headers, [('content-type', 'image/jpg')])
        else:
            self.assertRaises(PLOTLIBNotInstalled, self.viewer.render,
                              url, 'POST', path_entries[0], plot_dict, None)

        clear_dict = self.query_dict.copy()
        clear_dict['clear'] = ['clear']
        del clear_dict['query']
        clear_dict['profile'] = ['xxx']
        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              clear_dict, None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        download_dict = self.query_dict.copy()
        download_dict['download'] = ['download']
        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              download_dict, None)
        self.assertTrue(headers == [('content-type',
                                    self.viewer.format_dict['default'])])

        content, headers = self.viewer.render(url, 'GET', path_entries[1],
                                              self.query_dict, None)
        self.assertTrue(isinstance(json.loads(content), dict))

        for method in ['HEAD', 'PUT', 'DELETE', 'XYZMethod']:
            self.assertRaises(MethodNotAllowed, self.viewer.render, url,
                              method, path_entries[10], self.query_dict, None)

        for entry in path_entries[2:]:
            download_dict['format'] = 'default'
            content, headers = self.viewer.render(url, 'GET', entry,
                                                  download_dict, None)
            self.assertTrue(
                ('content-type', self.viewer.format_dict['default'])
                in headers, entry)
            download_dict['format'] = 'json'
            content, headers = self.viewer.render(url, 'GET', entry,
                                                  download_dict, None)
            self.assertTrue(isinstance(json.loads(content), dict))

    def test_index(self):
        content, headers = self.viewer.index_page(self.log_files[0:1],
                                                  profile_id='current')
        self.assertTrue(content.find('<html>') > -1)
        self.assertTrue(headers == [('content-type', 'text/html')])

    def test_index_all(self):
        content, headers = self.viewer.index_page(self.log_files,
                                                  profile_id='all')
        for f in self.log_files:
            self.assertTrue(content.find(f) > 0, content)
            self.assertTrue(headers == [('content-type', 'text/html')])

    def test_download(self):
        content, headers = self.viewer.download(self.log_files)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files, sort='calls',
                                                limit=10, nfl_filter='os')
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='default')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='json')
        self.assertTrue(isinstance(json.loads(content), dict))
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['json'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='csv')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['csv'])])
        if ODFLIB_INSTALLED:
            content, headers = self.viewer.download(self.log_files,
                                                    output_format='ods')
            self.assertEqual(headers, [('content-type',
                                        self.viewer.format_dict['ods'])])
        else:
            self.assertRaises(ODFLIBNotInstalled, self.viewer.download,
                              self.log_files, output_format='ods')
        content, headers = self.viewer.download(self.log_files,
                                                nfl_filter=__file__,
                                                output_format='python')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['python'])])

    def test_plot(self):
        if PLOTLIB_INSTALLED:
            content, headers = self.viewer.plot(self.log_files)
            self.assertTrue(content is not None)
            self.assertEqual(headers, [('content-type', 'image/jpg')])
            self.assertRaises(NotFoundException, self.viewer.plot, [])
        else:
            self.assertRaises(PLOTLIBNotInstalled, self.viewer.plot,
                              self.log_files)

    def test_format_source_code(self):
        nfl_os = '%s:%d(%s)' % (os.__file__[:-1], 136, 'makedirs')
        self.assertTrue('makedirs' in self.viewer.format_source_code(nfl_os))
        self.assertFalse('makedirsXYZ' in
                         self.viewer.format_source_code(nfl_os))
        nfl_illegal = '%s:136(makedirs)' % os.__file__
        self.assertTrue(_('The file type are forbidden to access!') in
                        self.viewer.format_source_code(nfl_illegal))
        nfl_not_exist = '%s.py:136(makedirs)' % os.__file__
        expected_msg = _('Can not access the file %s.') % os.__file__
        self.assertTrue(expected_msg in
                        self.viewer.format_source_code(nfl_not_exist))
Beispiel #6
0
class Test_html_viewer(unittest.TestCase):

    def setUp(self):
        if xprofile is None:
            raise SkipTest
        self.app = ProfileMiddleware(FakeApp, {})
        self.log_files = []
        self.tempdir = tempfile.mkdtemp()
        self.log_filename_prefix = self.tempdir + '/unittest.profile'
        self.profile_log = ProfileLog(self.log_filename_prefix, False)
        self.pids = ['123', '456', str(os.getpid())]
        profiler = xprofile.get_profiler('eventlet.green.profile')
        for pid in self.pids:
            profiler.runctx('import os;os.getcwd();', globals(), locals())
            self.log_files.append(self.profile_log.dump_profile(profiler, pid))
        self.viewer = HTMLViewer('__profile__', 'eventlet.green.profile',
                                 self.profile_log)
        body = (b"profile=123&profile=456&sort=time&sort=nc&limit=10"
                b"&fulldirs=1&nfl_filter=getcwd&query=query&metric=nc")
        wsgi_input = BytesIO(body)
        environ = {'REQUEST_METHOD': 'GET',
                   'QUERY_STRING': 'profile=all',
                   'wsgi.input': wsgi_input}
        req = Request.blank('/__profile__/', environ=environ)
        self.query_dict = self.app._combine_body_qs(req)

    def tearDown(self):
        shutil.rmtree(self.tempdir, ignore_errors=True)

    def fake_call_back(self):
        pass

    def test_get_param(self):
        query_dict = self.query_dict
        get_param = self.viewer._get_param
        self.assertEqual(get_param(query_dict, 'profile', 'current', True),
                         ['123', '456'])
        self.assertEqual(get_param(query_dict, 'profile', 'current'), '123')
        self.assertEqual(get_param(query_dict, 'sort', 'time'), 'time')
        self.assertEqual(get_param(query_dict, 'sort', 'time', True),
                         ['time', 'nc'])
        self.assertEqual(get_param(query_dict, 'limit', -1), 10)
        self.assertEqual(get_param(query_dict, 'fulldirs', '0'), '1')
        self.assertEqual(get_param(query_dict, 'nfl_filter', ''), 'getcwd')
        self.assertEqual(get_param(query_dict, 'query', ''), 'query')
        self.assertEqual(get_param(query_dict, 'metric', 'time'), 'nc')
        self.assertEqual(get_param(query_dict, 'format', 'default'), 'default')

    def test_render(self):
        url = 'http://localhost:8080/__profile__'
        path_entries = ['/__profile__'.split('/'),
                        '/__profile__/'.split('/'),
                        '/__profile__/123'.split('/'),
                        '/__profile__/123/'.split('/'),
                        '/__profile__/123/:0(getcwd)'.split('/'),
                        '/__profile__/all'.split('/'),
                        '/__profile__/all/'.split('/'),
                        '/__profile__/all/:0(getcwd)'.split('/'),
                        '/__profile__/current'.split('/'),
                        '/__profile__/current/'.split('/'),
                        '/__profile__/current/:0(getcwd)'.split('/')]

        content, headers = self.viewer.render(url, 'GET', path_entries[0],
                                              self.query_dict, None)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              self.query_dict, None)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        plot_dict = self.query_dict.copy()
        plot_dict['plot'] = ['plot']
        if PLOTLIB_INSTALLED:
            content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                                  plot_dict, None)
            self.assertEqual(headers, [('content-type', 'image/jpg')])
        else:
            self.assertRaises(PLOTLIBNotInstalled, self.viewer.render,
                              url, 'POST', path_entries[0], plot_dict, None)

        clear_dict = self.query_dict.copy()
        clear_dict['clear'] = ['clear']
        del clear_dict['query']
        clear_dict['profile'] = ['xxx']
        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              clear_dict, None)
        self.assertEqual(headers, [('content-type', 'text/html')])

        download_dict = self.query_dict.copy()
        download_dict['download'] = ['download']
        content, headers = self.viewer.render(url, 'POST', path_entries[0],
                                              download_dict, None)
        self.assertTrue(headers == [('content-type',
                                    self.viewer.format_dict['default'])])

        content, headers = self.viewer.render(url, 'GET', path_entries[1],
                                              self.query_dict, None)
        self.assertTrue(isinstance(json.loads(content), dict))

        for method in ['HEAD', 'PUT', 'DELETE', 'XYZMethod']:
            self.assertRaises(MethodNotAllowed, self.viewer.render, url,
                              method, path_entries[10], self.query_dict, None)

        for entry in path_entries[2:]:
            download_dict['format'] = 'default'
            content, headers = self.viewer.render(url, 'GET', entry,
                                                  download_dict, None)
            self.assertTrue(
                ('content-type', self.viewer.format_dict['default'])
                in headers, entry)
            download_dict['format'] = 'json'
            content, headers = self.viewer.render(url, 'GET', entry,
                                                  download_dict, None)
            self.assertTrue(isinstance(json.loads(content), dict))

    def test_index(self):
        content, headers = self.viewer.index_page(self.log_files[0:1],
                                                  profile_id='current')
        self.assertTrue(content.find('<html>') > -1)
        self.assertTrue(headers == [('content-type', 'text/html')])

    def test_index_all(self):
        content, headers = self.viewer.index_page(self.log_files,
                                                  profile_id='all')
        for f in self.log_files:
            self.assertTrue(content.find(f) > 0, content)
            self.assertTrue(headers == [('content-type', 'text/html')])

    def test_download(self):
        content, headers = self.viewer.download(self.log_files)
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files, sort='calls',
                                                limit=10, nfl_filter='os')
        self.assertTrue(content is not None)
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='default')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['default'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='json')
        self.assertTrue(isinstance(json.loads(content), dict))
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['json'])])
        content, headers = self.viewer.download(self.log_files,
                                                output_format='csv')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['csv'])])
        if ODFLIB_INSTALLED:
            content, headers = self.viewer.download(self.log_files,
                                                    output_format='ods')
            self.assertEqual(headers, [('content-type',
                                        self.viewer.format_dict['ods'])])
        else:
            self.assertRaises(ODFLIBNotInstalled, self.viewer.download,
                              self.log_files, output_format='ods')
        content, headers = self.viewer.download(self.log_files,
                                                nfl_filter=__file__,
                                                output_format='python')
        self.assertEqual(headers, [('content-type',
                                    self.viewer.format_dict['python'])])

    def test_plot(self):
        if PLOTLIB_INSTALLED:
            content, headers = self.viewer.plot(self.log_files)
            self.assertTrue(content is not None)
            self.assertEqual(headers, [('content-type', 'image/jpg')])
            self.assertRaises(NotFoundException, self.viewer.plot, [])
        else:
            self.assertRaises(PLOTLIBNotInstalled, self.viewer.plot,
                              self.log_files)

    def test_format_source_code(self):
        osfile = os.__file__.rstrip('c')
        nfl_os = '%s:%d(%s)' % (osfile, 136, 'makedirs')
        self.assertIn('makedirs', self.viewer.format_source_code(nfl_os))
        self.assertNotIn('makedirsXYZ', self.viewer.format_source_code(nfl_os))
        nfl_illegal = '%sc:136(makedirs)' % osfile
        self.assertIn(_('The file type are forbidden to access!'),
                      self.viewer.format_source_code(nfl_illegal))
        nfl_not_exist = '%s.py:136(makedirs)' % osfile
        expected_msg = _('Can not access the file %s.py.') % osfile
        self.assertIn(expected_msg,
                      self.viewer.format_source_code(nfl_not_exist))
Beispiel #7
0
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)
Beispiel #8
0
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)