diff --git a/config.py b/config.py index 727c756..8ddd31e 100644 --- a/config.py +++ b/config.py @@ -32,6 +32,7 @@ class Config: OPENAI_URL = os.getenv("OPENAI_URL", "https://api.openai.com/v1/chat/completions") OPENAI_MODEL = os.getenv("OPENAI_MODEL", "gpt-4o-mini") OPENAI_TIMEOUT = int(os.getenv("OPENAI_TIMEOUT", "30")) + OPENAI_LOG_PAYLOAD = os.getenv("OPENAI_LOG_PAYLOAD", "false").lower() == "true" # YouTube settings YOUTUBE_LANGUAGE = os.getenv("YOUTUBE_LANGUAGE", "en") diff --git a/main.py b/main.py index 19ce12d..3c60f59 100644 --- a/main.py +++ b/main.py @@ -14,6 +14,7 @@ Usage: import argparse import sys +import logging from pathlib import Path from datetime import datetime from typing import Optional @@ -53,6 +54,15 @@ def extract_content(url: str, source_type: str) -> dict: def main(): + logging.basicConfig( + level=getattr(logging, Config.LOG_LEVEL.upper(), logging.INFO), + format="%(asctime)s %(levelname)s [%(name)s] %(message)s", + handlers=[ + logging.StreamHandler(), + logging.FileHandler(Config.LOG_FILE), + ], + ) + parser = argparse.ArgumentParser( description="Extract content from URLs and save to Obsidian notes" ) diff --git a/summarizer.py b/summarizer.py index 84d6c77..d9e212b 100644 --- a/summarizer.py +++ b/summarizer.py @@ -7,6 +7,7 @@ Uses OPENAI_API_KEY and OPENAI_URL from environment (via Config). from __future__ import annotations import json +import logging from typing import Dict, List import requests @@ -18,6 +19,9 @@ class SummarizationError(RuntimeError): """Raised when summarization fails.""" +logger = logging.getLogger(__name__) + + def summarize_text(text: str, max_points: int = 3) -> Dict[str, List[str] | str]: """ Summarize text into a short summary and key points. @@ -63,15 +67,28 @@ def summarize_text(text: str, max_points: int = 3) -> Dict[str, List[str] | str] } try: + logger.info( + "OpenAI request: url=%s model=%s timeout=%ss input_chars=%s", + Config.OPENAI_URL, + Config.OPENAI_MODEL, + Config.OPENAI_TIMEOUT, + len(text), + ) + if Config.OPENAI_LOG_PAYLOAD: + logger.debug("OpenAI request payload: %s", json.dumps(payload, ensure_ascii=False)) response = requests.post( Config.OPENAI_URL, headers=headers, json=payload, timeout=Config.OPENAI_TIMEOUT, ) + logger.info("OpenAI response: status=%s", response.status_code) + if Config.OPENAI_LOG_PAYLOAD: + logger.debug("OpenAI response body: %s", response.text) response.raise_for_status() data = response.json() except Exception as exc: + logger.exception("OpenAI request failed") raise SummarizationError(f"Request failed: {exc}") from exc try: @@ -129,14 +146,27 @@ def format_markdown_content(text: str) -> str: } try: + logger.info( + "OpenAI format request: url=%s model=%s timeout=%ss input_chars=%s", + Config.OPENAI_URL, + Config.OPENAI_MODEL, + Config.OPENAI_TIMEOUT, + len(text), + ) + if Config.OPENAI_LOG_PAYLOAD: + logger.debug("OpenAI format request payload: %s", json.dumps(payload, ensure_ascii=False)) response = requests.post( Config.OPENAI_URL, headers=headers, json=payload, timeout=Config.OPENAI_TIMEOUT, ) + logger.info("OpenAI format response: status=%s", response.status_code) + if Config.OPENAI_LOG_PAYLOAD: + logger.debug("OpenAI format response body: %s", response.text) response.raise_for_status() data = response.json() return data["choices"][0]["message"]["content"].strip() except Exception as exc: + logger.exception("OpenAI format request failed") raise SummarizationError(f"Formatting request failed: {exc}") from exc