add cli.py

This commit is contained in:
2026-06-04 16:22:52 +00:00
parent 4a990628a0
commit 4e401719e8
+154
View File
@@ -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()