start project
This commit is contained in:
@@ -0,0 +1,47 @@
|
||||
"""Log parser abstraction (Chapter 07)."""
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from datetime import datetime
|
||||
from typing import Protocol, TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.models.log_file import LogFile
|
||||
|
||||
|
||||
@dataclass
|
||||
class ParsedEntry:
|
||||
timestamp: datetime
|
||||
ip: str
|
||||
method: str
|
||||
path: str
|
||||
status_code: int
|
||||
bytes_sent: int
|
||||
referrer: str | None
|
||||
user_agent: str | None
|
||||
|
||||
|
||||
class LogParser(Protocol):
|
||||
def parse_line(self, line: str) -> ParsedEntry | None: ...
|
||||
|
||||
|
||||
def get_parser_for(log_file: "LogFile") -> LogParser:
|
||||
"""Build the right LogParser for a given upload's format_string.
|
||||
|
||||
ASSUMPTION (flagged): a blank format_string — which the upload form
|
||||
allows — falls back to Combined, since Chapter 07 states no default
|
||||
for that case. Anything else is compiled as-is; a real custom
|
||||
LiteSpeed format is never silently replaced by a preset.
|
||||
"""
|
||||
# Imported lazily to avoid a circular import (apache.py imports
|
||||
# ParsedEntry from this module).
|
||||
from app.services.log_parser.apache import FormatCompiledParser, combined_parser, common_parser
|
||||
from app.services.log_parser.format_compiler import compile_format
|
||||
|
||||
fmt = (log_file.format_string or "").strip()
|
||||
key = fmt.lower()
|
||||
if key in ("", "combined"):
|
||||
return combined_parser()
|
||||
if key == "common":
|
||||
return common_parser()
|
||||
return FormatCompiledParser(compile_format(fmt))
|
||||
Reference in New Issue
Block a user