add browser console log artifact (#1097)

This commit is contained in:
LawyZheng
2024-10-31 23:10:11 +08:00
committed by GitHub
parent 00549c921b
commit de8e887e0f
10 changed files with 94 additions and 2 deletions

View File

@@ -8,9 +8,10 @@ import uuid
from datetime import datetime
from typing import Any, Awaitable, Callable, Protocol
import aiofiles
import structlog
from playwright.async_api import BrowserContext, Error, Page, Playwright, async_playwright
from pydantic import BaseModel
from playwright.async_api import BrowserContext, ConsoleMessage, Error, Page, Playwright, async_playwright
from pydantic import BaseModel, PrivateAttr
from skyvern.config import settings
from skyvern.constants import REPO_ROOT_DIR
@@ -40,6 +41,23 @@ def get_download_dir(workflow_run_id: str | None, task_id: str | None) -> str:
return download_dir
def set_browser_console_log(browser_context: BrowserContext, browser_artifacts: BrowserArtifacts) -> str:
if browser_artifacts.browser_console_log_path is None:
log_path = f"{settings.LOG_PATH}/{datetime.utcnow().strftime('%Y-%m-%d')}/{uuid.uuid4()}.log"
os.makedirs(os.path.dirname(log_path), exist_ok=True)
browser_artifacts.browser_console_log_path = log_path
async def browser_console_log(msg: ConsoleMessage) -> None:
current_time = datetime.now().strftime("%Y-%m-%dT%H:%M:%S.%fZ")
key_values = " ".join([f"{key}={value}" for key, value in msg.location.items()])
format_log = f"{current_time}[{msg.type}]{msg.text} {key_values}\n"
await browser_artifacts.append_browser_console_log(format_log)
LOG.info("browser console log is saved", log_path=browser_artifacts.browser_console_log_path)
browser_context.on("console", browser_console_log)
return browser_artifacts.browser_console_log_path
class BrowserContextCreator(Protocol):
def __call__(
self, playwright: Playwright, **kwargs: dict[str, Any]
@@ -91,12 +109,14 @@ class BrowserContextFactory:
har_path: str | None = None,
traces_dir: str | None = None,
browser_session_dir: str | None = None,
browser_console_log_path: str | None = None,
) -> BrowserArtifacts:
return BrowserArtifacts(
video_artifacts=video_artifacts or [],
har_path=har_path,
traces_dir=traces_dir,
browser_session_dir=browser_session_dir,
browser_console_log_path=browser_console_log_path,
)
@classmethod
@@ -113,6 +133,7 @@ class BrowserContextFactory:
if not creator:
raise UnknownBrowserType(browser_type)
browser_context, browser_artifacts, cleanup_func = await creator(playwright, **kwargs)
set_browser_console_log(browser_context=browser_context, browser_artifacts=browser_artifacts)
return browser_context, browser_artifacts, cleanup_func
except UnknownBrowserType as e:
raise e
@@ -141,6 +162,24 @@ class BrowserArtifacts(BaseModel):
har_path: str | None = None
traces_dir: str | None = None
browser_session_dir: str | None = None
browser_console_log_path: str | None = None
_browser_console_log_lock: asyncio.Lock = PrivateAttr(default_factory=asyncio.Lock)
async def append_browser_console_log(self, msg: str) -> int:
if self.browser_console_log_path is None:
return 0
async with self._browser_console_log_lock:
async with aiofiles.open(self.browser_console_log_path, "a") as f:
return await f.write(msg)
async def read_browser_console_log(self) -> bytes:
if self.browser_console_log_path is None:
return b""
async with self._browser_console_log_lock:
async with aiofiles.open(self.browser_console_log_path, "rb") as f:
return await f.read()
async def _create_headless_chromium(