def __init__(self, app, gcfg=None, host="127.0.0.1", port=None, *args, **kwargs): self.cfg = Config() self.app = app self.callable = None gcfg = gcfg or {} cfgfname = gcfg.get("__file__") if cfgfname is not None: self.cfgurl = 'config:%s' % cfgfname self.relpath = os.path.dirname(cfgfname) self.cfgfname = cfgfname cfg = kwargs.copy() if port and not host.startswith("unix:"): bind = "%s:%s" % (host, port) else: bind = host cfg["bind"] = bind if gcfg: for k, v in gcfg.items(): cfg[k] = v cfg["default_proc_name"] = cfg['__file__'] try: for k, v in cfg.items(): if k.lower() in self.cfg.settings and v is not None: self.cfg.set(k.lower(), v) except Exception, e: sys.stderr.write("\nConfig error: %s\n" % str(e)) sys.stderr.flush() sys.exit(1)
def test_atoms_defaults(): response = SimpleNamespace( status='200', response_length=1024, headers=(('Content-Type', 'application/json'), ), sent=1024, ) request = SimpleNamespace(headers=(('Accept', 'application/json'), )) environ = { 'REQUEST_METHOD': 'GET', 'RAW_URI': '/my/path?foo=bar', 'PATH_INFO': '/my/path', 'QUERY_STRING': 'foo=bar', 'SERVER_PROTOCOL': 'HTTP/1.1', } logger = Logger(Config()) atoms = logger.atoms(response, request, environ, datetime.timedelta(seconds=1)) assert isinstance(atoms, dict) assert atoms['r'] == 'GET /my/path?foo=bar HTTP/1.1' assert atoms['m'] == 'GET' assert atoms['U'] == '/my/path' assert atoms['q'] == 'foo=bar' assert atoms['H'] == 'HTTP/1.1' assert atoms['b'] == '1024' assert atoms['B'] == 1024 assert atoms['{accept}i'] == 'application/json' assert atoms['{content-type}o'] == 'application/json'
def __call__(self, app: object, host: str, port: int, workers: int) -> None: """ Start Gunicorn Server :param app: application object :param host: Host URI :param port: Network port :param workers: Number of workers """ from gunicorn import version_info if version_info < (0, 9, 0): from gunicorn.arbiter import Arbiter from gunicorn.config import Config arbiter = Arbiter( Config({ 'bind': "%s:%d" % (host, int(port)), 'workers': workers }), app) arbiter.run() else: from gunicorn.app.base import Application class FlaskApplication(Application): def init(self, parser, opts, args): return { 'bind': '{0}:{1}'.format(host, port), 'workers': workers } def load(self): return app FlaskApplication().run()
def test_instrument(): logger = Statsd(Config()) # Capture logged messages sio = io.StringIO() logger.error_log.addHandler(logging.StreamHandler(sio)) logger.sock = MockSocket(False) # Regular message logger.info("Blah", extra={"mtype": "gauge", "metric": "gunicorn.test", "value": 666}) assert logger.sock.msgs[0] == b"gunicorn.test:666|g" assert sio.getvalue() == "Blah\n" logger.sock.reset() # Only metrics, no logging logger.info("", extra={"mtype": "gauge", "metric": "gunicorn.test", "value": 666}) assert logger.sock.msgs[0] == b"gunicorn.test:666|g" assert sio.getvalue() == "Blah\n" # log is unchanged logger.sock.reset() # Debug logging also supports metrics logger.debug("", extra={"mtype": "gauge", "metric": "gunicorn.debug", "value": 667}) assert logger.sock.msgs[0] == b"gunicorn.debug:667|g" assert sio.getvalue() == "Blah\n" # log is unchanged logger.sock.reset() logger.critical("Boom") assert logger.sock.msgs[0] == b"gunicorn.log.critical:1|c|@1.0" logger.sock.reset() logger.access(SimpleNamespace(status="200 OK"), None, {}, timedelta(seconds=7)) assert logger.sock.msgs[0] == b"gunicorn.request.duration:7000.0|ms" assert logger.sock.msgs[1] == b"gunicorn.requests:1|c|@1.0" assert logger.sock.msgs[2] == b"gunicorn.request.status.200:1|c|@1.0"
def load_config(self): # init configuration self.cfg = Config(self.usage, prog=self.prog) # parse console args parser = self.cfg.parser() args = parser.parse_args() # optional settings from apps cfg = self.init(parser, args, args.args) # Load up the any app specific configuration if cfg and cfg is not None: for k, v in cfg.items(): self.cfg.set(k.lower(), v) if args.config: self.load_config_from_file(args.config) else: default_config = get_default_config_file() if default_config is not None: self.load_config_from_file(default_config) # Lastly, update the configuration with any command line # settings. for k, v in args.__dict__.items(): if v is None: continue if k == "args": continue self.cfg.set(k.lower(), v)
def __call__(self, app, host, port, workers): from gunicorn import version_info if version_info < (0, 9, 0): from gunicorn.arbiter import Arbiter from gunicorn.config import Config arbiter = Arbiter( Config({ 'bind': "%s:%d" % (host, int(port)), 'workers': workers }), app) arbiter.run() else: from gunicorn.app.base import Application class FlaskApplication(Application): def init(self, parser, opts, args): return { 'bind': '{0}:{1}'.format(host, port), 'workers': workers } def load(self): return app FlaskApplication().run()
def load_config(self): self.cfg = Config() if self.config_file and os.path.exists(self.config_file): cfg = { "__builtins__": __builtins__, "__name__": "__config__", "__file__": self.config_file, "__doc__": None, "__package__": None } try: execfile(self.config_file, cfg, cfg) except Exception: print "Failed to read config file: %s" % self.config_file traceback.print_exc() sys.exit(1) for k, v in list(cfg.items()): # Ignore unknown names if k not in self.cfg.settings: continue try: self.cfg.set(k.lower(), v) except: sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v)) raise for k, v in list(self.options.items()): if k.lower() in self.cfg.settings and v is not None: self.cfg.set(k.lower(), v)
def test_gunicorn_logger_access(environ, log): response, environ, delta, expected = access_extra_args(environ, '/') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) logger.access(response, None, environ, delta) log[0]._structured == expected
def test_gunicorn_logger_get_extra_str_status(environ): response, environ, delta, expected = access_extra_args(environ, '/') cfg = Config() logger = gunicorn.GunicornLogger(cfg) response.status = '200 OK' msg, extra = logger.get_extra(response, None, environ, delta) assert extra['status'] == '200'
def test_prefix_multiple_dots(): c = Config() c.set("statsd_prefix", "test...") logger = Statsd(c) logger.sock = MockSocket(False) logger.info("Blah", extra={"mtype": "gauge", "metric": "gunicorn.test", "value": 666}) t.eq(logger.sock.msgs[0], "test.gunicorn.test:666|g")
def test_gunicorn_logger_set_formatters_on_gunicorn_logs(): cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) error = logger._get_gunicorn_handler(logger.error_log) assert isinstance(error.formatter, logs.StructuredFormatter) access = logger._get_gunicorn_handler(logger.access_log) assert isinstance(access.formatter, logs.StructuredFormatter)
def test_gunicorn_logger_logging(level, statsd_metrics, log): cfg = Config() logger = gunicorn.GunicornLogger(cfg) getattr(logger, level)(level) expected = 'ERROR' if level == 'exception' else level.upper() assert log[0].levelname == expected assert log[0].getMessage() == level assert 'gunicorn.log.{}:1|c'.format(level) in statsd_metrics[0]
def test_factory(self): self.worker.wsgi = mock.Mock() self.worker.loop = mock.Mock() self.worker.log = mock.Mock() self.worker.cfg = Config() f = self.worker.factory(self.worker.wsgi, ('localhost', 8080)) self.assertIsInstance(f, WSGIServerHttpProtocol)
def test_prefix_nested(): c = Config() c.set("statsd_prefix", "test.asdf.") logger = Statsd(c) logger.sock = MockSocket(False) logger.info("Blah", extra={"mtype": "gauge", "metric": "gunicorn.test", "value": 666}) assert logger.sock.msgs[0] == b"test.asdf.gunicorn.test:666|g"
def load_py(fname): module_name = '__config__' mod = types.ModuleType(module_name) setattr(mod, 'uri', uri) setattr(mod, 'cfg', Config()) loader = importlib.machinery.SourceFileLoader(module_name, fname) loader.exec_module(mod) return vars(mod)
def test_gunicorn_logger_get_extra(environ): response, environ, delta, expected = access_extra_args( environ, '/foo?bar=baz') cfg = Config() logger = gunicorn.GunicornLogger(cfg) msg, extra = logger.get_extra(response, None, environ, delta, 200) assert msg == 'GET /foo?' assert extra == expected
def test_dogstatsd_tags(): c = Config() tags = 'yucatan,libertine:rhubarb' c.set('dogstatsd_tags', tags) logger = Statsd(c) logger.sock = MockSocket(False) logger.info("Twill", extra={"mtype": "gauge", "metric": "barb.westerly", "value": 2}) assert logger.sock.msgs[0] == b"barb.westerly:2|g|#" + tags.encode('ascii')
def run(self, handler): from gunicorn.arbiter import Arbiter from gunicorn.config import Config handler.cfg = Config({ 'bind': "%s:%d" % (self.host, self.port), 'workers': 4 }) arbiter = Arbiter(handler) arbiter.run()
def load_config(self): # init configuration self.cfg = Config(self.usage, prog=self.prog) config = dict([(key, value) for key, value in self.options.items() if key in self.cfg.settings and value is not None]) for key, value in config.items(): self.cfg.set(key.lower(), value)
def test_gunicorn_logger_access_forwarded(environ, context): response, environ, delta, expected = access_extra_args(environ, '/') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) context.logs[:] = [] logger.access(response, None, environ, delta) assert context.logs.exists(msg='GET /', extra=expected) assert context.statsd[0] == 'gunicorn.count.view.GET.200:1|c' assert context.statsd[1].startswith('gunicorn.latency.view.GET.200:')
def setUp(self): self.loop = asyncio.new_event_loop() asyncio.set_event_loop(None) self.worker = gaiohttp.AiohttpWorker('age', 'ppid', 'sockets', 'app', 'timeout', Config(), 'log')
def test_gunicorn_logger_access_qs(environ, context): response, environ, delta, expected = access_extra_args( environ, '/url?foo=bar') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) context.logs[:] = [] logger.access(response, None, environ, delta) assert context.logs.exists(msg='GET /url?', extra=expected)
def test_statsd_fail(): "UDP socket fails" logger = Statsd(Config()) logger.sock = MockSocket(True) logger.info("No impact on logging") logger.debug("No impact on logging") logger.critical("No impact on logging") logger.error("No impact on logging") logger.warning("No impact on logging") logger.exception("No impact on logging")
def test_gunicorn_logger_access_qs(environ, log): response, environ, delta, expected = access_extra_args( environ, '/url?foo=bar') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) log[:] = [] logger.access(response, None, environ, delta) assert log[0]._structured == expected assert log[0].msg == 'GET /url?'
def test_gunicorn_logger_status_url(environ, log, statsd_metrics): response, environ, delta, expected = access_extra_args( environ, '/_status/ping') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) statsd.get_client() # force the statsd creationg log message log[:] = [] logger.access(response, None, environ, delta) assert len(log) == 0 assert len(statsd_metrics) == 0
def test_gunicorn_logger_access_forwarded(environ, log, statsd_metrics): response, environ, delta, expected = access_extra_args(environ, '/') cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) log[:] = [] logger.access(response, None, environ, delta) assert log[0]._structured == expected assert log[0].msg == 'GET /' assert statsd_metrics[0] == 'gunicorn.count.view.GET.200:1|c' assert statsd_metrics[1].startswith('gunicorn.latency.view.GET.200:')
def test_gunicorn_logger_access_with_request_id(environ, log): rid = 'request-id' response, environ, delta, expected = access_extra_args(environ, '/') expected['request_id'] = rid cfg = Config() cfg.set('accesslog', '-') logger = gunicorn.GunicornLogger(cfg) log[:] = [] with request_id.context(rid): logger.access(response, None, environ, delta) assert log[0]._structured == expected
def worker(iterator): # Mock socket listener mock_listener = mock.Mock() sockets = [mock_listener] # Declare worker mock_log = mock.Mock() worker = SyncIteratingWorker(None, None, sockets, None, None, Config(), mock_log) worker.wsgi = iterator worker.alive = True yield worker
def check(self): cases = self.expect[:] p = RequestParser(Config(), self.send()) try: [req for req in p] except Exception, inst: exp = cases.pop(0) if not issubclass(exp, Exception): raise TypeError("Test case is not an exception calss: %s" % exp) t.istype(inst, exp) return
def load_config(self): # init configuration self.cfg = Config(self.usage, prog=self.prog) # parse console args parser = self.cfg.parser() args = parser.parse_args() # optional settings from apps cfg = self.init(parser, args, args.args) # Load up the any app specific configuration if cfg and cfg is not None: for k, v in cfg.items(): self.cfg.set(k.lower(), v) # Load up the config file if its found. if args.config: if not os.path.exists(args.config): raise RuntimeError("%r doesn't exist" % args.config) cfg = { "__builtins__": __builtins__, "__name__": "__config__", "__file__": args.config, "__doc__": None, "__package__": None } try: execfile_(args.config, cfg, cfg) except Exception: print("Failed to read config file: %s" % args.config) traceback.print_exc() sys.exit(1) for k, v in cfg.items(): # Ignore unknown names if k not in self.cfg.settings: continue try: self.cfg.set(k.lower(), v) except: sys.stderr.write("Invalid value for %s: %s\n\n" % (k, v)) raise # Lastly, update the configuration with any command line # settings. for k, v in args.__dict__.items(): if v is None: continue if k == "args": continue self.cfg.set(k.lower(), v)