iT邦幫忙

2026 iThome 鐵人賽

DAY 4
0

無論你對產品工程師有沒有興趣,只要你做的產品真的有人使用,大概都遇過使用者或其他同事跑來回報:

「這裡好像壞掉了。」

有些問題很單純,光看錯誤訊息就知道發生在哪裡,也能很快進行處理。但更多時候,拿到的資訊可能只有「按了沒反應」、「剛才不能用」甚至「好像怪怪的」。如果程式碼又經過編譯與打包,想單靠錯誤訊息裡的 Stack Trace 找到原始碼位置,就更加困難。

當然,也可以回頭詢問使用者是怎麼觸發的,但如果是一個面向公眾的產品,每次出問題都要請使用者協助工程師重現,多少還是會損害使用者對產品的信任。

因此,收集真實使用者環境中的錯誤,一直是軟體工程中很重要的一環,也有很多產品專門處理這件事情。

我自己最早接觸的是 Sentry。如果單獨比較 Error Tracking,我不認為 PostHog 有非常顯著的功能優勢,甚至在不少工程與 Observability 能力上,Sentry 都更加完整。

但即便如此,我現在還是會優先考慮 PostHog Error Tracking。

原因很簡單:

免費額度真的太香了。

Sentry 的 Developer 免費方案只允許一名使用者,每月包含 5,000 筆 Error;PostHog 不限制團隊成員數,Error Tracking 的免費額度則直接給到每月 100,000 Exceptions。

Session Replay 的差距更明顯:Sentry 免費方案每月包含 50 個 Replay,而 PostHog 則是 5,000 個。

當然,我並不是說 PostHog 可以完全取代 Sentry。單看錯誤追蹤與系統監控,Sentry 的功能仍然更完整,支援的語言與框架也更多。如果你的團隊已經大量使用 Sentry,而且現有流程運作得很好,那就不見得有必要只是為了免費額度而更換。

但如果還沒引進錯誤追蹤系統,或者是不排斥更換,我認為 PostHog Error Tracking 相當值得嘗試。

如果前一篇已經使用 PostHog Wizard 完成安裝,它可能已經順便幫你設定好 Error Tracking。以 Next.js 來說,可以先在專案中搜尋 captureException,確認前後端的 Exception 是否都有被捕捉。PostHog 的 Next.js 安裝流程本身也會要求確認 Exception 已經成功送進 Activity Feed。

例如可以在 Error Boundary 中額外捕捉錯誤:

componentDidCatch(error: globalThis.Error, errorInfo: ErrorInfo) {
  // ...
  posthog.captureException(error, {
    component: this.props.componentName ?? "ErrorBoundary",
    component_name: this.props.componentName ?? "ErrorBoundary",
    componentStack: errorInfo.componentStack,
    screen: `${window.screen.width}x${window.screen.height}`,
    screen_height: window.screen.height,
    screen_width: window.screen.width,
    url: window.location.href,
    viewport: `${window.innerWidth}x${window.innerHeight}`,
    viewport_height: window.innerHeight,
    viewport_width: window.innerWidth,
    $current_url: window.location.href,
  });
}

除了 Exception 本身之外,也可以附加更多與當下操作有關的資訊。這些 Properties 往往比單純的錯誤訊息更有用,例如交易失敗時,可以一起留下金額、付款管道、訂單類型等資訊。

另一個非常重要的設定是 Source Map

正式環境中的 JavaScript 通常經過編譯、壓縮與切割,如果沒有 Source Map,即使拿到了 Stack Trace,也可能只看到壓縮後的檔案位置。PostHog 的 Next.js Integration 可以在 Build 時自動產生並上傳 Source Map,再用它還原實際的程式碼位置。

在 Next.js Config 中大致會是:

module.exports = withPostHogConfig(config, {
  personalApiKey: process.env.POSTHOG_CLI_API_KEY,
  projectId: process.env.POSTHOG_CLI_PROJECT_ID,
  host:
    process.env.POSTHOG_CLI_HOST ||
    process.env.NEXT_PUBLIC_POSTHOG_HOST ||
    "https://us.posthog.com",
  sourcemaps: {
    releaseName: process.env.POSTHOG_SOURCEMAP_RELEASE_NAME,
    releaseVersion: process.env.POSTHOG_SOURCEMAP_RELEASE_VERSION,
    deleteAfterUpload: true,
  },
});

releaseNamereleaseVersion 也可以協助區分不同應用程式與不同版本,例如前端、後端,或不同的 Deployment。

完成之後,就可以故意觸發一個錯誤,再到 PostHog 的 Error Tracking 頁面看看實際效果。

https://ithelp.ithome.com.tw/upload/images/20260906/20102556vCz98Skk8b.png

(Error Tracking 應該預設會開啟。如果沒有,可以在 MY TOOLS 旁邊的齒輪把它啟用。剛開始其實可以全部打開,之後再依照使用情況把不需要的功能關掉。)

https://ithelp.ithome.com.tw/upload/images/20260906/20102556qd1xcR1V4W.png

如果有在 captureException 中附帶額外資訊,就可以在 Properties Tab 中查看。例如我們在交易相關的錯誤裡,會另外記錄金額、付款管道等資訊。

https://ithelp.ithome.com.tw/upload/images/20260906/20102556ya6kx4saUK.png

Session Tab 則可以把錯誤放回使用者當時的操作脈絡中,看到自訂事件、頁面瀏覽、Console Log,以及最後發生的 Exception。

這也是我覺得 PostHog Error Tracking 很方便的地方。除了錯誤本身之外,你還能往前看到使用者在出錯之前做了哪些操作,而不是只拿著一段 Stack Trace 猜測問題是怎麼發生的。

https://ithelp.ithome.com.tw/upload/images/20260906/20102556qHhOOhYTKQ.png

由於 Console Log 很容易包含 Token、使用者資料或其他敏感資訊,因此 PostHog 預設不會捕捉。如果確定內容適合上傳,可以在 posthog.init 中加入:

enable_recording_console_log: true

也可以直接從 Session Replay 的設定中開啟。

https://ithelp.ithome.com.tw/upload/images/20260906/20102556qe6T00PFAy.png

比較美中不足的是,目前 Error Tracking 裡的 Session Timeline 沒有顯示 Autocapture 事件。

這代表如果某個錯誤是由 UI 操作觸發,例如使用者點了某個按鈕、展開某個選單之後發生 Exception,光看這個 Timeline 有時候還是不容易知道完整的觸發流程。

目前我找到的一個替代方式,是先透過使用者來定位。

首先從 Error Tracking 的錯誤資訊進入對應的使用者頁面:

https://ithelp.ithome.com.tw/upload/images/20260906/20102556ptcqucKfpk.png

接著到 Events Tab 找到同一時間附近的 Exception,再直接觀察它前後出現了哪些 Autocapture Event。

https://ithelp.ithome.com.tw/upload/images/20260906/20102556X7cHrOUasX.png

這時我們終於有機會回答那個最麻煩的問題:

「使用者到底做了什麼,才把它弄壞的?」

知道之後,就可以重現、定位,接著安排修復。

不過,到這裡其實還只解決了一半的問題。

Error Tracking 能幫我們知道使用者有沒有因為程式錯誤而失敗,但一個完全沒有 Exception 的產品,也不代表使用者真的完成了他想做的事情。

使用者順利打開頁面、點擊按鈕、API 全部回傳 200,最後卻沒有完成他原本想完成的事——從系統角度來看一切正常,從使用者角度來看,產品仍然可能是失敗的。

所以接下來,我們要開始處理另一個問題:

使用者來到我們的產品,到底是想完成什麼?


如果你願意花 30 秒留下回饋,我會用這些意見來調整後續文章:分享你的意見


上一篇
Day 3|PostHog 安裝
下一篇
Day 5|讓使用者成功(上):JTBD / Job Story
系列文
成為產品型工程師吧!從培養產品思維到 PostHog 數據實戰20
圖片
  熱門推薦
圖片
{{ item.channelVendor }} | {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言