示例#1
0
    async def serve(self, sockets=None):
        process_id = os.getpid()

        config = self.config
        if not config.loaded:
            config.load()

        self.lifespan = config.lifespan_class(config)

        self.install_signal_handlers()

        message = "Started server process [%d]"
        color_message = "Started server process [" + test4.style(
            "%d", fg="cyan") + "]"
        logger.info(message,
                    process_id,
                    extra={"color_message": color_message})

        await self.startup(sockets=sockets)
        if self.should_exit:
            return
        await self.main_loop()
        await self.shutdown(sockets=sockets)

        message = "Finished server process [%d]"
        color_message = "Finished server process [" + test4.style(
            "%d", fg="cyan") + "]"
        logger.info(
            "Finished server process [%d]",
            process_id,
            extra={"color_message": color_message},
        )
示例#2
0
    def startup(self):
        message = f"Started reloader process [{self.pid}] using {self.reloader_name}"
        color_message = "Started reloader process [{}] using {}".format(
            test4.style(str(self.pid), fg="cyan", bold=True),
            test4.style(str(self.reloader_name), fg="cyan", bold=True),
        )
        logger.info(message, extra={"color_message": color_message})

        for sig in HANDLED_SIGNALS:
            signal.signal(sig, self.signal_handler)

        self.process = get_subprocess(config=self.config,
                                      target=self.target,
                                      sockets=self.sockets)
        self.process.start()
示例#3
0
    def shutdown(self):
        for process in self.processes:
            process.join()

        message = "Stopping parent process [{}]".format(str(self.pid))
        color_message = "Stopping parent process [{}]".format(
            test4.style(str(self.pid), fg="cyan", bold=True)
        )
        logger.info(message, extra={"color_message": color_message})
示例#4
0
    def startup(self):
        message = "Started parent process [{}]".format(str(self.pid))
        color_message = "Started parent process [{}]".format(
            test4.style(str(self.pid), fg="cyan", bold=True)
        )
        logger.info(message, extra={"color_message": color_message})

        for sig in HANDLED_SIGNALS:
            signal.signal(sig, self.signal_handler)

        for idx in range(self.config.workers):
            process = get_subprocess(
                config=self.config, target=self.target, sockets=self.sockets
            )
            process.start()
            self.processes.append(process)
示例#5
0
class ColourizedFormatter(logging.Formatter):
    """
    A custom log formatter class that:

    * Outputs the LOG_LEVEL with an appropriate color.
    * If a log call includes an `extras={"color_message": ...}` it will be used
      for formatting the output, instead of the plain text message.
    """

    level_name_colors = {
        TRACE_LOG_LEVEL:
        lambda level_name: test4.style(str(level_name), fg="blue"),
        logging.DEBUG:
        lambda level_name: test4.style(str(level_name), fg="cyan"),
        logging.INFO:
        lambda level_name: test4.style(str(level_name), fg="green"),
        logging.WARNING:
        lambda level_name: test4.style(str(level_name), fg="yellow"),
        logging.ERROR:
        lambda level_name: test4.style(str(level_name), fg="red"),
        logging.CRITICAL:
        lambda level_name: test4.style(str(level_name), fg="bright_red"),
    }

    def __init__(self, fmt=None, datefmt=None, style="%", use_colors=None):
        if use_colors in (True, False):
            self.use_colors = use_colors
        else:
            self.use_colors = sys.stdout.isatty()
        super().__init__(fmt=fmt, datefmt=datefmt, style=style)

    def color_level_name(self, level_name, level_no):
        default = lambda level_name: str(level_name)
        func = self.level_name_colors.get(level_no, default)
        return func(level_name)

    def should_use_colors(self):
        return True

    def formatMessage(self, record):
        recordcopy = copy(record)
        levelname = recordcopy.levelname
        seperator = " " * (8 - len(recordcopy.levelname))
        if self.use_colors:
            levelname = self.color_level_name(levelname, recordcopy.levelno)
            if "color_message" in recordcopy.__dict__:
                recordcopy.msg = recordcopy.__dict__["color_message"]
                recordcopy.__dict__["message"] = recordcopy.getMessage()
        recordcopy.__dict__["levelprefix"] = levelname + ":" + seperator
        return super().formatMessage(recordcopy)
示例#6
0
 def formatMessage(self, record):
     recordcopy = copy(record)
     scope = recordcopy.__dict__["scope"]
     method = scope["method"]
     path = self.get_path(scope)
     full_path = self.get_full_path(scope)
     client_addr = self.get_client_addr(scope)
     status_code = self.get_status_code(recordcopy)
     http_version = scope["http_version"]
     request_line = "%s %s HTTP/%s" % (method, full_path, http_version)
     if self.use_colors:
         request_line = test4.style(request_line, bold=True)
     recordcopy.__dict__.update({
         "method": method,
         "path": path,
         "full_path": full_path,
         "client_addr": client_addr,
         "request_line": request_line,
         "status_code": status_code,
         "http_version": http_version,
     })
     return super().formatMessage(recordcopy)
示例#7
0
    def bind_socket(self):
        sock = socket.socket()
        sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        try:
            sock.bind((self.host, self.port))
        except OSError as exc:
            logger.error(exc)
            sys.exit(1)
        sock.set_inheritable(True)

        message = "Uvicorn running on %s://%s:%d (Press CTRL+C to quit)"
        color_message = ("Uvicorn running on " +
                         test4.style("%s://%s:%d", bold=True) +
                         " (Press CTRL+C to quit)")
        protocol_name = "https" if self.is_ssl else "http"
        logger.info(
            message,
            protocol_name,
            self.host,
            self.port,
            extra={"color_message": color_message},
        )
        return sock
示例#8
0
class AccessFormatter(ColourizedFormatter):
    status_code_colours = {
        1: lambda code: test4.style(str(code), fg="bright_white"),
        2: lambda code: test4.style(str(code), fg="green"),
        3: lambda code: test4.style(str(code), fg="yellow"),
        4: lambda code: test4.style(str(code), fg="red"),
        5: lambda code: test4.style(str(code), fg="bright_red"),
    }

    def get_client_addr(self, scope):
        client = scope.get("client")
        if not client:
            return ""
        return "%s:%d" % (client[0], client[1])

    def get_path(self, scope):
        return scope.get("root_path", "") + scope["path"]

    def get_full_path(self, scope):
        path = scope.get("root_path", "") + scope["path"]
        query_string = scope.get("query_string", b"").decode("ascii")
        if query_string:
            return path + "?" + query_string
        return path

    def get_status_code(self, record):
        status_code = record.__dict__["status_code"]
        try:
            status_phrase = http.HTTPStatus(status_code).phrase
        except ValueError:
            status_phrase = ""
        status_and_phrase = "%s %s" % (status_code, status_phrase)

        if self.use_colors:
            default = lambda code: status_and_phrase
            func = self.status_code_colours.get(status_code // 100, default)
            return func(status_and_phrase)
        return status_and_phrase

    def formatMessage(self, record):
        recordcopy = copy(record)
        scope = recordcopy.__dict__["scope"]
        method = scope["method"]
        path = self.get_path(scope)
        full_path = self.get_full_path(scope)
        client_addr = self.get_client_addr(scope)
        status_code = self.get_status_code(recordcopy)
        http_version = scope["http_version"]
        request_line = "%s %s HTTP/%s" % (method, full_path, http_version)
        if self.use_colors:
            request_line = test4.style(request_line, bold=True)
        recordcopy.__dict__.update({
            "method": method,
            "path": path,
            "full_path": full_path,
            "client_addr": client_addr,
            "request_line": request_line,
            "status_code": status_code,
            "http_version": http_version,
        })
        return super().formatMessage(recordcopy)
示例#9
0
    async def startup(self, sockets=None):
        await self.lifespan.startup()
        if self.lifespan.should_exit:
            self.should_exit = True
            return

        config = self.config

        create_protocol = functools.partial(config.http_protocol_class,
                                            config=config,
                                            server_state=self.server_state)

        loop = asyncio.get_event_loop()

        if sockets is not None:
            # Explicitly passed a list of open sockets.
            # We use this when the server is run from a Gunicorn worker.
            self.servers = []
            for sock in sockets:
                server = await loop.create_server(create_protocol,
                                                  sock=sock,
                                                  ssl=config.ssl,
                                                  backlog=config.backlog)
                self.servers.append(server)

        elif config.fd is not None:
            # Use an existing socket, from a file descriptor.
            sock = socket.fromfd(config.fd, socket.AF_UNIX, socket.SOCK_STREAM)
            server = await loop.create_server(create_protocol,
                                              sock=sock,
                                              ssl=config.ssl,
                                              backlog=config.backlog)
            message = "Uvicorn running on socket %s (Press CTRL+C to quit)"
            logger.info(message % str(sock.getsockname()))
            self.servers = [server]

        elif config.uds is not None:
            # Create a socket using UNIX domain socket.
            uds_perms = 0o666
            if os.path.exists(config.uds):
                uds_perms = os.stat(config.uds).st_mode
            server = await loop.create_unix_server(create_protocol,
                                                   path=config.uds,
                                                   ssl=config.ssl,
                                                   backlog=config.backlog)
            os.chmod(config.uds, uds_perms)
            message = "Uvicorn running on unix socket %s (Press CTRL+C to quit)"
            logger.info(message % config.uds)
            self.servers = [server]

        else:
            # Standard case. Create a socket from a host/port pair.
            try:
                server = await loop.create_server(
                    create_protocol,
                    host=config.host,
                    port=config.port,
                    ssl=config.ssl,
                    backlog=config.backlog,
                )
            except OSError as exc:
                logger.error(exc)
                await self.lifespan.shutdown()
                sys.exit(1)
            port = config.port
            if port == 0:
                port = server.sockets[0].getsockname()[1]
            protocol_name = "https" if config.ssl else "http"
            message = "Uvicorn running on %s://%s:%d (Press CTRL+C to quit)"
            color_message = ("Uvicorn running on " +
                             test4.style("%s://%s:%d", bold=True) +
                             " (Press CTRL+C to quit)")
            logger.info(
                message,
                protocol_name,
                config.host,
                port,
                extra={"color_message": color_message},
            )
            self.servers = [server]

        self.started = True