91 lines
2.7 KiB
Python
91 lines
2.7 KiB
Python
import os
|
|
import sys
|
|
import time
|
|
from logging import DEBUG, Formatter, getLogger, INFO, Logger, NOTSET, StreamHandler
|
|
from typing import TYPE_CHECKING
|
|
|
|
from .wrappers import Request, Response
|
|
|
|
if TYPE_CHECKING:
|
|
from .app import Quart # noqa
|
|
|
|
default_handler = StreamHandler(sys.stderr)
|
|
default_handler.setFormatter(Formatter('[%(asctime)s] %(levelname)s in %(module)s: %(message)s'))
|
|
|
|
serving_handler = StreamHandler(sys.stdout)
|
|
serving_handler.setFormatter(Formatter('[%(asctime)s] %(message)s'))
|
|
|
|
|
|
def create_logger(app: 'Quart') -> Logger:
|
|
"""Create a logger for the app based on the app settings.
|
|
|
|
This creates a logger named quart.app that has a log level based
|
|
on the app configuration.
|
|
"""
|
|
logger = getLogger('quart.app')
|
|
|
|
if app.debug and logger.level == NOTSET:
|
|
logger.setLevel(DEBUG)
|
|
|
|
logger.addHandler(default_handler)
|
|
return logger
|
|
|
|
|
|
def create_serving_logger() -> Logger:
|
|
"""Create a logger for serving.
|
|
|
|
This creates a logger named quart.serving.
|
|
"""
|
|
logger = getLogger('quart.serving')
|
|
|
|
if logger.level == NOTSET:
|
|
logger.setLevel(INFO)
|
|
|
|
logger.addHandler(serving_handler)
|
|
return logger
|
|
|
|
|
|
class AccessLogAtoms(dict):
|
|
|
|
def __init__(
|
|
self,
|
|
request: Request,
|
|
response: Response,
|
|
protocol: str,
|
|
request_time: float,
|
|
) -> None:
|
|
self.update({
|
|
'h': request.remote_addr,
|
|
'l': '-',
|
|
't': time.strftime('[%d/%b/%Y:%H:%M:%S %z]'),
|
|
'r': f"{request.method} {request.path} {protocol}",
|
|
's': response.status_code,
|
|
'm': request.method,
|
|
'U': request.path,
|
|
'q': request.query_string.decode('ascii'),
|
|
'H': protocol,
|
|
'b': response.headers.get('Content-Length', '-'),
|
|
'B': response.headers.get('Content-Length'),
|
|
'f': request.headers.get('Referer', '-'),
|
|
'a': request.headers.get('User-Agent', '-'),
|
|
'T': int(request_time),
|
|
'D': int(request_time * 1000000),
|
|
'L': f"{request_time:.6f}",
|
|
'p': f"<{os.getpid()}>",
|
|
})
|
|
for name, value in request.headers.items():
|
|
self[f"{{{name.lower()}}}i"] = value
|
|
for name, value in response.headers.items():
|
|
self[f"{{{name.lower()}}}o"] = value
|
|
for name, value in os.environ.items():
|
|
self[f"{{{name.lower()}}}e"] = value
|
|
|
|
def __getitem__(self, key: str) -> str:
|
|
try:
|
|
if key.startswith('{'):
|
|
return super().__getitem__(key.lower())
|
|
else:
|
|
return super().__getitem__(key)
|
|
except KeyError:
|
|
return '-'
|