擷取任何瀏覽器自動化的完整 DevTools 協定追蹤 — CDP 事件串流、螢幕截圖和 DOM 轉儲 — 然後將串流分割成每個頁面可搜尋的區塊。當使用者想要偵錯失敗的執行、稽核網路/主控台/DOM 活動、將追蹤附加到進行中的工作階段,或將結構化的每頁摘要回饋到代理循環中,以便下一次迭代從上一次學習時使用。
Browser Trace
將第二個唯讀 CDP 客戶端附加到已由主要自動化驅動的瀏覽器工作階段。追蹤會將完整的 DevTools 事件串流記錄到 NDJSON,同時輪詢螢幕截圖和 DOM 轉儲,並將所有內容切割成 bash 工具可搜尋的目錄樹。
此技能不驅動頁面 — 它僅監聽。請搭配 browser 技能、browse、Stagehand、Playwright 或任何其他支援 CDP 的工具使用。
使用時機
- 使用者想要偵錯瀏覽器自動化執行(表單失敗、元素遺失、導覽卡住、JS 例外)。
- 使用者有正在執行的自動化,並希望在不重新啟動的情況下附加追蹤。
- 使用者想要將 CDP 事件串流分割成網路/主控台/DOM/頁面區塊。
- 使用者想要隨時間變化的螢幕截圖 + DOM 快照,並透過時間戳記與 CDP 事件關聯。
如果使用者只想驅動瀏覽器,請改用 browser 技能。
設定檢查
node --version # 需要 Node 18+
which browse || npm install -g browse
which jq || true # 可選 — 僅用於臨時查詢
驗證 browse cdp 存在:
browse --help | grep -q "^\s*cdp " || echo "browse cdp 不可用 — 請更新 browse"
運作方式
每個 Chrome DevTools 目標都接受多個並發 CDP 客戶端。您的主要自動化是一個客戶端;此技能新增第二個客戶端,僅啟用觀察領域(Network、Console、Runtime、Log、Page),且絕不發送動作命令。
追蹤器包含三個部分:
- 事件串流:
browse cdp <target>將每個 CDP 事件以一行一個 JSON 物件串流到cdp/raw.ndjson。 - 取樣器:輪詢迴圈會定期呼叫
browse screenshot --cdp <target> --path <file>和browse get html body --cdp <target>(預設間隔 2 秒)。輔助程式在取樣時傳遞--cdp,以便從自己的程序附加到被追蹤的目標;一旦 browse 守護程序工作階段附加到 CDP 目標,該工作階段的後續命令無需重複--cdp。 - 分割器:執行結束後,
bisect-cdp.mjs會遍歷raw.ndjson一次,根據 CDP 方法將其分割成每個區塊的 JSONL 檔案,並另外使用頂層Page.frameNavigated事件作為邊界,按頁面分割。
快速入門
本機 Chrome
# 1. 啟動 Chrome 並開啟偵錯埠(任何 user-data-dir 可保持隔離)。
"/Applications/Google Chrome.app/Contents/MacOS/Google Chrome" \
--remote-debugging-port=9222 \
--user-data-dir=/tmp/chrome-o11y \
about:blank &
# 2. 啟動追蹤器。
node scripts/start-capture.mjs 9222 my-run
# 3. 針對埠 9222 執行您的主要自動化。
browse open https://example.com --cdp 9222
# ...執行任何操作...
# 4. 停止並分割。
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
Browserbase 遠端
兩個輔助程式封裝了平台端的簿記:bb-capture.mjs 建立或附加到工作階段並啟動追蹤器;bb-finalize.mjs 在執行結束時將平台工件(最終工作階段元資料、伺服器日誌、下載)拉取到執行目錄中。
Browserbase 會在其最後一個 CDP 客戶端斷開連線時結束工作階段。使用
--keep-alive建立,然後在追蹤器之前或同時將自動化附加到工作階段的connectUrl。bb-capture.mjs --new處理保持連線的工作階段和追蹤器設定;您的自動化仍需附加。
export BROWSERBASE_API_KEY=...
# 1. 一步建立保持連線的工作階段並啟動追蹤器。
# 列印工作階段 ID、connectUrl 前綴,以及一個即時偵錯程式 URL,
# 您可以在瀏覽器中開啟以互動方式觀看執行。
node scripts/bb-capture.mjs --new my-run
# 2. 驅動自動化。bb-capture 已將工作階段 ID 寫入 manifest。
SID=$(jq -r .browserbase.session_id .o11y/my-run/manifest.json)
CONNECT_URL="$(browse cloud sessions get "$SID" | jq -r .connectUrl)"
BROWSE_NAME=my-run-browser
browse open https://example.com --cdp "$CONNECT_URL" --session "$BROWSE_NAME"
browse open https://news.ycombinator.com --session "$BROWSE_NAME"
# 3. 停止追蹤器、分割,然後拉取平台工件並釋放。
node scripts/stop-capture.mjs my-run
node scripts/bisect-cdp.mjs my-run
node scripts/bb-finalize.mjs my-run --release
附加到已經在執行的工作階段(例如您的生產工作者建立的)— bb-capture.mjs 接受工作階段 ID 而非 --new:
# 選擇一個正在執行的工作階段(客戶端過濾;browse cloud sessions list 沒有 --status 旗標)
browse cloud sessions list | jq -r '.[] | select(.status == "RUNNING") | .id'
node scripts/bb-capture.mjs <session-id> mid-flight-debug
# ...追蹤器與現有自動化客戶端並行執行;不會中斷...
node scripts/stop-capture.mjs mid-flight-debug
node scripts/bisect-cdp.mjs mid-flight-debug
node scripts/bb-finalize.mjs mid-flight-debug # 不加 --release:保持工作階段執行
從 Browserbase 平台獲得的內容
bb-capture.mjs 在 manifest.json 中新增一個 browserbase 區塊(工作階段 ID、專案、區域、started_at、expires_at、偵錯程式 URL)。bb-finalize.mjs 寫入:
<run>/browserbase/session.json— 最終的browse cloud sessions get快照(proxyBytes、狀態、ended_at、viewport 等)<run>/browserbase/logs.json—browse cloud sessions logs輸出。通常為空。 CDP 事件串流cdp/raw.ndjson是真相來源;這是側通道。<run>/browserbase/downloads.zip— 工作階段下載的檔案(如果有的話;腳本會丟棄當沒有檔案時得到的空 22 位元組 zip)
工作階段重播工件擷取已棄用,不會被擷取。請使用 screenshots/ 和 dom/ 中的螢幕截圖和 DOM 轉儲作為視覺真相。
manifest 中的即時 debugger_url 會開啟一個由 Browserbase 提供的互動式 Chrome DevTools 檢視 — 方便在追蹤器將事件串流擷取到磁碟時觀看長時間執行的自動化。
檔案系統佈局
.o11y/<run-id>/
manifest.json 執行元資料:目標、領域、started_at、stopped_at
index.jsonl 每個樣本一行:{ts, screenshot, dom, url}
cdp/
raw.ndjson 完整 CDP 事件串流(每行一個 JSON 物件)
summary.json {sessionId, duration, totalEvents, pages[]} — 請參閱下方結構
network/{requests,responses,finished,failed,websocket}.jsonl 工作階段範圍的區塊(總是寫入)
console/{logs,exceptions}.jsonl
runtime/all.jsonl
log/entries.jsonl
page/{navigations,lifecycle,frames,dialogs,all}.jsonl
dom/all.jsonl (僅當 O11Y_DOMAINS 包含 DOM 時)
target/{attached,detached}.jsonl
pages/ 按頁面分割,以頂層 frameNavigated 邊界索引
000/ 第一個具體頁面
url.txt 此頁面的 URL
summary.json 此頁面的 domains/network/timing 區塊(與 pages[] 條目結構相同)
raw.jsonl 限於此頁面的事件串流
network/, console/, page/, runtime/, log/, target/, dom/ 相同區塊,僅非空檔案
screenshots/<iso-ts>.png 每個取樣間隔一個 PNG
dom/<iso-ts>.html 每個取樣間隔一個 HTML 轉儲
browserbase/ 由 bb-finalize.mjs 新增(僅 Browserbase 執行)
session.json 最終的 `browse cloud sessions get` 快照(proxyBytes、狀態、ended_at 等)
logs.json `browse cloud sessions logs` 輸出(通常為 [])
downloads.zip `browse cloud sessions downloads get` 輸出(僅當工作階段下載了檔案)
當執行是透過 bb-capture.mjs 啟動時,manifest.json 也會攜帶一個頂層的 browserbase 區塊:session_id、project_id、region、started_at、expires_at、keep_alive、debugger_url。
摘要結構
cdp/summary.json 是任何分析的入口點:它包含工作階段層級的總計和一個由頂層 Page.frameNavigated 索引的 pages[] 陣列。每個頁面的條目按導覽順序發出(頁面 0 = 第一個具體 URL)。
{
"sessionId": "45f28023-…",
"duration": { "startMs": 1777312533000, "endMs": 1777312609000, "totalMs": 76000 },
"totalEvents": 420,
"pages": [
{
"pageId": 0,
"url": "https://example.com/",
"startMs": 1777312533000, "endMs": 1777312538886, "durationMs": 5886,
"eventCount": 60,
"domains": {
"Network": { "count": 18, "errors": 1 },
"Console": { "count": 2 },
"Page": { "count": 24 },
"Runtime": { "count": 13 }
},
"network": { "requests": 4, "failed": 1, "byType": { "Document": 2, "Script": 1, "Other": 1 } }
}
]
}
startMs / endMs / durationMs 是牆上時鐘毫秒,源自 manifest.started_at 加上每個事件的 CDP 單調時間戳記偏移。domains[*] 僅在非零時包含 errors/warnings 鍵。
使用 query.mjs 深入查詢
對於互動式探索,請使用 scripts/query.mjs <run-id> <command> 而不是記住路徑:
node scripts/query.mjs my-run list # 頁面的單行表格
node scripts/query.mjs my-run page 1 # 頁面 1 的完整摘要
node scripts/query.mjs my-run page 1 network/failed # 顯示頁面 1 的 failed.jsonl
node scripts/query.mjs my-run errors # 所有頁面的錯誤,按 pid 歸因
node scripts/query.mjs my-run errors 2 # 僅頁面 2 的錯誤
node scripts/query.mjs my-run hosts # 按請求計數排列的頂級主機
node scripts/query.mjs my-run host api.example.com # 特定主機的所有請求/回應
node scripts/query.mjs my-run summary # 完整的 summary.json
幕後它僅讀取 cdp/summary.json 和 cdp/pages/<pid>/ 樹 — 一旦您熟悉結構,可以隨意使用原始 jq/rg 繞過它。
頂層遍歷技巧
# 所有失敗的網路請求(使用 jq -c 保持行分隔)
jq -c '.params' .o11y/<run>/cdp/network/failed.jsonl
# 尋找對特定主機的請求
jq -c 'select(.params.request.url | test("api\\.example\\.com"))' \
.o11y/<run>/cdp/network/requests.jsonl
# 4xx/5xx 回應
jq -c 'select(.params.response.status >= 400)
| {status: .params.response.status, url: .params.response.url}' \
.o11y/<run>/cdp/network/responses.jsonl
# 僅主控台錯誤
jq -c 'select(.params.type == "error")' .o11y/<run>/cdp/console/logs.jsonl
# 造訪的 URL 順序
jq -r '.params.frame.url' .o11y/<run>/cdp/page/navigations.jsonl
# 尋找最接近某個時間戳記的螢幕截圖(例如,當例外發生時)
ls .o11y/<run>/screenshots/ | sort | awk -v t=20260427T1714123NZ '
$0 >= t { print; exit }'
請參閱 REFERENCE.md 以取得完整的 jq 技巧庫和按方法分割的對應表。請參閱 EXAMPLES.md 以取得端到端偵錯情境。
最佳實踐
- 在 Browserbase 上使用
bb-capture.mjs:它會強制使用--keep-alive、擷取 connectUrl、取得偵錯程式 URL,並在 manifest 中標記。手動操作容易出錯。 - 不要
--release您不擁有的工作階段:bb-finalize.mjs --release適用於您使用--new建立的工作階段。當透過bb-capture.mjs <session-id>附加到生產工作階段時,請執行bb-finalize.mjs而不加--release,以便原始自動化繼續執行。 - 遠端時順序很重要:在 Browserbase 上,在追蹤器之前(或同時)附加主要自動化客戶端,並使用
--keep-alive建立工作階段。否則,工作階段會在追蹤器的 WebSocket 關閉時立即結束。 - 不要輪詢快於約 1 秒:每個樣本都會執行瀏覽器 CLI 讀取命令並對 Chrome 進行螢幕截圖。2 秒是良好的預設值。
- 刻意選擇領域:預設值(
Network Console Runtime Log Page)涵蓋大多數偵錯。透過O11Y_DOMAINS="$O11Y_DOMAINS DOM"新增DOM以取得 DOM 樹變更(非常嘈雜)。 - 在遠端重複使用同一個 Browserbase 工作階段,方法是使用
browse open ... --cdp "$CONNECT_URL" --session <name>附加到該工作階段的connectUrl。--session旗標命名本機 browse 守護程序;它不是 Browserbase 工作階段附加旗標。 - 始終執行
stop-capture.mjs,即使在崩潰後也是如此,這樣背景程序就不會殘留,且 manifest 會取得stopped_at。 - 每個執行分割一次:
bisect-cdp.mjs是冪等的 — 它每次都會從raw.ndjson覆寫每個區塊的檔案。
疑難排解
browse cdp exited immediately:通常表示目標無法連線(錯誤的埠)或 Browserbase 工作階段已結束。對於遠端,請使用browse cloud sessions get <id>驗證 — 如果status是COMPLETED,請使用--keep-alive重新建立並先附加自動化。- 即使程序在執行,
raw.ndjson也是空的:確認 CDP 客戶端確實正在驅動頁面。追蹤器僅發出瀏覽器產生的事件,因此閒置的瀏覽器只會產生約 5 行附加/發現訊息,沒有其他內容。 - 所有螢幕截圖看起來都一樣:檢查
index.jsonl— 如果url沒有改變,表示頁面尚未導覽。輪詢迴圈獨立於主要自動化的節奏執行。 - Browserbase 工作階段中途結束:可能已達到
--timeout。使用更高的逾時值重新建立(BB_SESSION_TIMEOUT=1800 node scripts/bb-capture.mjs --new ...)或移除逾時旗標。 bb-capture.mjs <id>顯示 "not RUNNING":您嘗試附加的工作階段已結束。使用browse cloud sessions list | jq '.[] | select(.status == "RUNNING")'列出候選項目,然後重試。browserbase/logs.json是空的[]:這是預期的 —browse cloud sessions logs在實務上內容稀疏。CDP 事件串流cdp/raw.ndjson是真相來源。- 工作階段錄製(rrweb)在哪裡?:工作階段重播工件擷取已棄用;此技能不會擷取它。請使用
screenshots/中的螢幕截圖串流和dom/中的 DOM 轉儲。
如需完整參考,請參閱 REFERENCE.md。
如需範例偵錯執行,請參閱 EXAMPLES.md。






