add cli.py
This commit is contained in:
@@ -0,0 +1,154 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
CLI для парсинга логов HTTP API с использованием discriminated union в LangChain
|
||||
"""
|
||||
|
||||
import sys
|
||||
import argparse
|
||||
from typing import List
|
||||
from tabulate import tabulate
|
||||
|
||||
from models import ApiEvent, HttpOkEvent, HttpErrorEvent
|
||||
from parser import LogEventParser
|
||||
|
||||
# Пример лога (разные форматы для демонстрации гибкости)
|
||||
EXAMPLE_LOG = """GET /api/users 200 duration=45ms
|
||||
POST /api/products/123 404 error="Product not found" time=12ms
|
||||
DELETE /api/sessions 500 Internal Server Error (duration=230ms)
|
||||
GET /health 200 2ms
|
||||
PUT /api/config 400 Invalid request body, duration=67"""
|
||||
|
||||
class LogCLI:
|
||||
def __init__(self):
|
||||
self.parser = LogEventParser()
|
||||
|
||||
def display_results(self, events: List[ApiEvent]) -> None:
|
||||
"""Выводит результаты в читаемом виде"""
|
||||
if not events:
|
||||
print("❌ Нет успешно обработанных событий")
|
||||
return
|
||||
|
||||
print("\n" + "="*80)
|
||||
print(f"📊 Обработано событий: {len(events)}")
|
||||
print("="*80)
|
||||
|
||||
# Таблица для компактного отображения
|
||||
table_data = []
|
||||
for event in events:
|
||||
if isinstance(event, HttpOkEvent):
|
||||
table_data.append([
|
||||
event.kind.upper(),
|
||||
event.path,
|
||||
event.status,
|
||||
f"{event.duration_ms}ms",
|
||||
"-"
|
||||
])
|
||||
elif isinstance(event, HttpErrorEvent):
|
||||
table_data.append([
|
||||
event.kind.upper(),
|
||||
event.path,
|
||||
event.status,
|
||||
"-",
|
||||
event.error_message[:50] + ("..." if len(event.error_message) > 50 else "")
|
||||
])
|
||||
|
||||
headers = ["Kind", "Path", "Status", "Duration", "Error Message"]
|
||||
print(tabulate(table_data, headers=headers, tablefmt="grid"))
|
||||
|
||||
# Подробный вывод
|
||||
print("\n📋 Детализация:")
|
||||
for i, event in enumerate(events, 1):
|
||||
print(f"{i}. {event}")
|
||||
|
||||
def run_interactive(self):
|
||||
"""Интерактивный режим"""
|
||||
print("🔄 HTTP Log Parser (Structured Output with Discriminated Union)")
|
||||
print("Введите лог (пустая строка для завершения):")
|
||||
|
||||
lines = []
|
||||
while True:
|
||||
line = input("> ")
|
||||
if not line:
|
||||
break
|
||||
lines.append(line)
|
||||
|
||||
if lines:
|
||||
log_text = "\n".join(lines)
|
||||
events = self.parser.parse_multiple_events(log_text)
|
||||
self.display_results(events)
|
||||
|
||||
def run_example(self):
|
||||
"""Запуск на примере"""
|
||||
print("🚀 Запуск на примере лога:")
|
||||
print("─" * 80)
|
||||
print(EXAMPLE_LOG)
|
||||
print("─" * 80)
|
||||
|
||||
events = self.parser.parse_multiple_events(EXAMPLE_LOG)
|
||||
self.display_results(events)
|
||||
|
||||
def run_from_file(self, filename: str):
|
||||
"""Парсинг лога из файла"""
|
||||
try:
|
||||
with open(filename, 'r', encoding='utf-8') as f:
|
||||
log_text = f.read()
|
||||
events = self.parser.parse_multiple_events(log_text)
|
||||
self.display_results(events)
|
||||
except FileNotFoundError:
|
||||
print(f"❌ Файл не найден: {filename}")
|
||||
sys.exit(1)
|
||||
except Exception as e:
|
||||
print(f"❌ Ошибка чтения файла: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
def main():
|
||||
parser = argparse.ArgumentParser(
|
||||
description="Парсинг логов HTTP API с discriminated union в LangChain",
|
||||
formatter_class=argparse.RawDescriptionHelpFormatter
|
||||
)
|
||||
|
||||
parser.add_argument(
|
||||
"-f", "--file",
|
||||
help="Файл с логами (каждое событие на новой строке)"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-i", "--interactive",
|
||||
action="store_true",
|
||||
help="Интерактивный режим ввода"
|
||||
)
|
||||
parser.add_argument(
|
||||
"-e", "--example",
|
||||
action="store_true",
|
||||
help="Запустить на встроенном примере"
|
||||
)
|
||||
parser.add_argument(
|
||||
"--model",
|
||||
default="gpt-3.5-turbo",
|
||||
help="Модель OpenAI (по умолчанию: gpt-3.5-turbo)"
|
||||
)
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
# Если нет аргументов, показываем help
|
||||
if len(sys.argv) == 1:
|
||||
parser.print_help()
|
||||
print("\n" + "="*80)
|
||||
print("Пример использования:")
|
||||
print(" python cli.py --example # Запуск на примере")
|
||||
print(" python cli.py -i # Интерактивный режим")
|
||||
print(" python cli.py -f logs.txt # Парсинг файла")
|
||||
return
|
||||
|
||||
cli = LogCLI()
|
||||
|
||||
if args.example:
|
||||
cli.run_example()
|
||||
elif args.interactive:
|
||||
cli.run_interactive()
|
||||
elif args.file:
|
||||
cli.run_from_file(args.file)
|
||||
else:
|
||||
parser.print_help()
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user