class LoggingTestServer(object): """ Class that starts an odin HTTPServer instance and allows its log output to be checked via the pytest capture log mechanism. """ def __init__(self, caplog): """Initialise the logging test server.""" self.http_server = HttpServer(adapters=[]) self.request_summary = 'request' self.request_time = 1234 self.caplog = caplog def do_log_request(self, http_status, level): """ Generate a mock request handler and verify that the logger generates the appropriate message. """ handler = MockHandler(http_status, self.request_summary, self.request_time) self.http_server.log_request(handler) msg_seen = False for record in self.caplog.records: if record.levelno == level and record.getMessage() == '{:d} {:s} {:.2f}ms'.format( http_status, self.request_summary, self.request_time*1000.0): msg_seen = True return msg_seen
def main(argv=None): """Run ODIN server. This function is the main entry point for the ODIN server. It parses configuration options from the command line and any files, resolves adapters and launches the main API server before entering the IO processing loop. :param argv: argument list to pass to parser if called programatically """ config = ConfigParser() # Define configuration options and add to the configuration parser config.define('http_addr', default='0.0.0.0', option_help='Set HTTP server address') config.define('http_port', default=8888, option_help='Set HTTP server port') config.define('debug_mode', default=False, option_help='Enable tornado debug mode') config.define('access_logging', default=None, option_help="Set the tornado access log level", metavar="debug|info|warning|error|none") config.define('static_path', default='./static', option_help='Set path for static file content') # Parse configuration options and any configuration file specified try: config.parse(argv) except ConfigError as e: logging.error('Failed to parse configuration: %s', e) return 2 # Resolve the list of adapters specified try: adapters = config.resolve_adapters() except ConfigError as e: logging.warning('Failed to resolve API adapters: %s', e) adapters = {} logging.info('Using the %s IOLoop instance', '0MQ' if using_zmq_loop else 'tornado') # Launch the HTTP server http_server = HttpServer(config.debug_mode, config.access_logging, config.static_path, adapters) http_server.listen(config.http_port, config.http_addr) logging.info('HTTP server listening on %s:%s', config.http_addr, config.http_port) # Register a SIGINT signal handler only if this is the main thread if isinstance(threading.current_thread(), threading._MainThread): # pragma: no cover signal.signal(signal.SIGINT, lambda signum, frame: shutdown_handler()) # Enter IO processing loop tornado.ioloop.IOLoop.instance().start() # At shutdown, clean up the state of the loaded adapters http_server.cleanup_adapters() logging.info('ODIN server shutdown') return 0
def test_bad_access_log_level(self, caplog): """Test that a bad access logging level generates an error.""" bad_level = 'wibble' http_server = HttpServer(adapters=[], access_logging=bad_level) assert log_message_seen( caplog, logging.ERROR, 'Access logging level {} not recognised'.format(bad_level))
def setup_class(cls): cls.http_server = HttpServer(adapters=[]) cls.handler = Mock() cls.handler.get_status = Mock(return_value=200) cls.request_summary = 'request' cls.handler._request_summary = Mock(return_value=cls.request_summary) cls.handler.request = Mock() cls.request_time = 1234 cls.handler.request.request_time = Mock(return_value=cls.request_time) cls.log_capture_filter = LogCaptureFilter()
def test_bad_access_log_level(self): """Test that a bad access logging level generates an error.""" log_capture_filter = LogCaptureFilter() bad_level='wibble' http_server = HttpServer(adapters=[], access_logging=bad_level) msg_seen = False expected_msg = 'Access logging level {} not recognised'.format(bad_level) for msg in log_capture_filter.log_error(): if msg == expected_msg: msg_seen = True assert msg_seen
def main(argv=None): """Run ODIN server. This function is the main entry point for the ODIN server. It parses configuration options from the command line and any files, resolves adapters and launches the main API server before entering the IO processing loop. :param argv: argument list to pass to parser if called programatically """ config = ConfigParser() # Define configuration options and add to the configuration parser config.define('http_addr', default='0.0.0.0', option_help='Set HTTP server address') config.define('http_port', default=8888, option_help='Set HTTP server port') config.define('debug_mode', default=False, option_help='Enable tornado debug mode') config.define('access_logging', default=None, option_help="Set the tornado access log level", metavar="debug|info|warning|error|none") config.define('static_path', default='./static', option_help='Set path for static file content') # Parse configuration options and any configuration file specified try: config.parse(argv) except ConfigError as e: logging.error('Failed to parse configuration: %s', e) return 2 # Resolve the list of adapters specified try: adapters = config.resolve_adapters() except ConfigError as e: logging.warning('Failed to resolve API adapters: %s', e) adapters = {} # Launch the HTTP server http_server = HttpServer(config.debug_mode, config.access_logging, config.static_path, adapters) http_server.listen(config.http_port, config.http_addr) logging.info('HTTP server listening on %s:%s', config.http_addr, config.http_port) # Register a SIGINT signal handler only if this is the main thread if isinstance(threading.current_thread(), threading._MainThread): # pragma: no cover signal.signal(signal.SIGINT, lambda signum, frame: shutdown_handler()) # Enter IO processing loop tornado.ioloop.IOLoop.instance().start() # At shutdown, clean up the state of the loaded adapters http_server.cleanup_adapters() logging.info('ODIN server shutdown') return 0
def __init__(self, caplog): """Initialise the logging test server.""" self.http_server = HttpServer(adapters=[]) self.request_summary = 'request' self.request_time = 1234 self.caplog = caplog