ranchimallflo-api/py3.7/lib/python3.7/site-packages/hypercorn/logging.py

85 lines
3.1 KiB
Python

import logging
import os
import sys
import time
from typing import Any, Optional, Union
class AccessLogger:
def __init__(self, log_format: str, target: Union[logging.Logger, str, None]) -> None:
self.logger: Optional[logging.Logger] = None
self.log_format = log_format
if isinstance(target, logging.Logger):
self.logger = target
elif target is not None:
self.logger = logging.getLogger("hypercorn.access")
self.logger.propagate = False
self.logger.handlers = []
if target == "-":
self.logger.addHandler(logging.StreamHandler(sys.stdout))
else:
self.logger.addHandler(logging.FileHandler(target))
self.logger.setLevel(logging.INFO)
def access(self, request: dict, response: dict, request_time: float) -> None:
if self.logger is not None:
self.logger.info(self.log_format, AccessLogAtoms(request, response, request_time))
def __getattr__(self, name: str) -> Any:
if self.logger is None:
return lambda *_: None
else:
return getattr(self.logger, name)
class AccessLogAtoms(dict):
def __init__(self, request: dict, response: dict, request_time: float) -> None:
for name, value in request["headers"]:
self[f"{{{name.decode().lower()}}}i"] = value.decode()
for name, value in response["headers"]:
self[f"{{{name.decode().lower()}}}o"] = value.decode()
for name, value in os.environ.items():
self[f"{{{name.lower()}}}e"] = value
protocol = request.get("http_version", "ws")
client = request.get("client")
if client is None:
remote_addr = None
elif len(client) == 2:
remote_addr = f"{client[0]}:{client[1]}"
elif len(client) == 1:
remote_addr = client[0]
else: # make sure not to throw UnboundLocalError
remote_addr = f"<???{client}???>"
method = request.get("method", "GET")
self.update(
{
"h": remote_addr,
"l": "-",
"t": time.strftime("[%d/%b/%Y:%H:%M:%S %z]"),
"r": f"{method} {request['path']} {protocol}",
"s": response["status"],
"S": request["scheme"],
"m": method,
"U": request["path"],
"q": request["query_string"].decode(),
"H": protocol,
"b": self["{Content-Length}o"],
"B": self["{Content-Length}o"],
"f": self["{Referer}i"],
"a": self["{User-Agent}i"],
"T": int(request_time),
"D": int(request_time * 1_000_000),
"L": f"{request_time:.6f}",
"p": f"<{os.getpid()}>",
}
)
def __getitem__(self, key: str) -> str:
try:
if key.startswith("{"):
return super().__getitem__(key.lower())
else:
return super().__getitem__(key)
except KeyError:
return "-"