Log SDK

@parallelsandbox/log 是一個很小的瀏覽器 SDK。掛在任何你在箱子裡(或其他地方)跑的網頁上,錯誤與 log 就會進到你自己的 log project。你的 agent 之後用 logs_searchlogs_errorslogs_tail 讀,不用再叫你貼 console。

Project 與 key

log project 用 POST https://log.parallelsandbox.com/v1/projects 建,帶租戶 API key:

curl -fsS -X POST https://log.parallelsandbox.com/v1/projects \
  -H "Authorization: Bearer psbx_YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "name": "example-web", "origins": ["http://localhost:8080"] }'

回應裡有 project id 與 write key。每個 project 有:

  • project id,prj_...,每次查詢都帶;
  • write key,pw_...,瀏覽器每批 log 都帶。它只能寫這個 project,所以放在網頁上沒關係;
  • origin 白名單:其他來源送的一律拒收;
  • 每把 key 的限流。

每個 project 自己一個 log group。log 不設保留期限。

安裝

用 bundler 的話從 npm 裝:

npm install @parallelsandbox/log

不用 bundler 的話用 import map:

<script type="importmap">
{ "imports": { "@parallelsandbox/log": "https://cdn.jsdelivr.net/npm/@parallelsandbox/log/+esm" } }
</script>

初始化

import { init } from '@parallelsandbox/log';

init({
  project: 'prj_...',                          // project id
  writeKey: 'pw_...',                          // write key
  endpoint: 'https://log.parallelsandbox.com', // log server
  release: 'a1b2c3d',                          // build id;要跟上傳 source map 時用的 release 一樣
});

呼叫一次,越早越好。init 之後:

  • 未捕捉的錯誤(window.onerror)、未處理的 promise rejection、console.error 會連同 stack 一起被收下;
  • 每隔幾秒與頁面隱藏時批次送出;
  • 每筆都帶 release、頁面網址、user agent,網頁從箱子供應時還會帶箱子 id,所以 logs_errors 可以用 boxId 過濾。

手動呼叫

import { log, captureError, flush } from '@parallelsandbox/log';

log('info', 'checkout started', { cart: 3 });
log('warn', 'slow response', { ms: 2400 });

try {
  riskyThing();
} catch (err) {
  captureError(err, { step: 'riskyThing' });
}

await flush(); // 測試裡離開頁面前

levelinfowarnerrorextra 是任何能轉 JSON 的物件,logs_search 查得到。

Source map

壓縮過的 stack 對 agent 沒有用。每次 build 的 source map 都用 init 那個 release 上傳,logs_errors 回來的 stack 就會還原成原始檔與行號。

curl -fsS -X POST https://log.parallelsandbox.com/v1/projects/prj_.../sourcemaps \
  -H "Authorization: Bearer psbx_YOUR_API_KEY" \
  -F "release=a1b2c3d" \
  -F "path=assets/app-ALQGRFWG.js" \
  -F "map=@dist/assets/app-ALQGRFWG.js.map;type=application/json"

一張 map 一個請求。path 是 stack 裡看到的 script 路徑(相對於頁面 origin)。上傳用租戶 API key,不是 write key。example-web-with-logs 有一支 script 會把整個 dist/ 上傳。

從 agent 查

logs_errors { "project": "prj_...", "since": "30m", "boxId": "<box id>" }
logs_search { "project": "prj_...", "since": "1h", "query": "checkout" }
logs_tail   { "project": "prj_...", "boxId": "<box id>" }

每列有 tslevelmessagereleaseurlboxIdextra,錯誤還有 stackstackResolved

費用

log 的寫入與保存跟其他用量一樣計量,成本乘 1.5:

用量 扣點
寫入 1,140 點/GB
保存 49.5 點/GB 每月

一個每天回報幾百個錯誤的網頁,一個月用不到一點。