<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/"><channel><title>Specification on Tarragon</title><link>https://tarrragon.github.io/blog/tags/specification/</link><description>Recent content in Specification on Tarragon</description><generator>Hugo -- gohugo.io</generator><language>zh-TW</language><copyright>Tarragon (CC BY 4.0)</copyright><lastBuildDate>Fri, 19 Jun 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://tarrragon.github.io/blog/tags/specification/index.xml" rel="self" type="application/rss+xml"/><item><title>功能規格中的 log 點定義方法</title><link>https://tarrragon.github.io/blog/testing/02-client-observability/log-point-in-spec/</link><pubDate>Fri, 19 Jun 2026 00:00:00 +0000</pubDate><guid>https://tarrragon.github.io/blog/testing/02-client-observability/log-point-in-spec/</guid><description>&lt;p>Log 點定義是功能規格的一部分，和 API schema 同級。功能規格描述「這個功能做什麼」，log 點規格描述「這個功能執行時留下什麼可觀察的紀錄」。把 log 點設計前移到規格階段，讓 log 成為功能的設計產物，而非事後的 debug 工具（本章合成，TF-9 Derive）。&lt;/p>
&lt;h2 id="四類-log-點">四類 log 點&lt;/h2>
&lt;p>每個功能的 log 點按執行時機分成四類。&lt;/p>
&lt;h3 id="啟動-log">啟動 log&lt;/h3>
&lt;p>功能開始執行時記錄。回答「這個功能是否被觸發了」。&lt;/p>
&lt;p>啟動 log 包含觸發來源（使用者操作、系統排程、外部事件）和初始參數（連線目標、操作類型）。如果一個功能從未被觸發，啟動 log 的缺席就是線索。&lt;/p>
&lt;h3 id="步驟-log">步驟 log&lt;/h3>
&lt;p>功能執行過程中的每個關鍵步驟完成時記錄。回答「流程走到哪裡了」。&lt;/p>
&lt;p>步驟 log 的粒度依功能複雜度而定。三步驟的功能每步記一條；十步驟的功能可以只記關鍵的三到五步。判斷標準是：如果這一步失敗，開發者是否需要知道失敗點在哪。&lt;/p>
&lt;h3 id="錯誤-log">錯誤 log&lt;/h3>
&lt;p>步驟失敗、例外捕獲、非預期狀態出現時記錄。回答「出了什麼問題」。&lt;/p>
&lt;p>錯誤 log 必須包含足夠的 context 讓開發者不需要重現問題就能判斷原因。至少包含：哪一步失敗、失敗原因（error message）、當時的關鍵狀態值。&lt;/p>
&lt;h3 id="完成-log">完成 log&lt;/h3>
&lt;p>功能正常結束時記錄。回答「功能是否成功完成、花了多久」。&lt;/p>
&lt;p>完成 log 包含執行結果和耗時。和啟動 log 配對使用 — 有啟動但沒有完成代表功能中途異常退出。&lt;/p>
&lt;h2 id="在功能規格中加可觀測性欄位">在功能規格中加可觀測性欄位&lt;/h2>
&lt;p>以 app_tunnel 的「連線到 ttyd 終端機」功能為例，傳統規格只寫：&lt;/p>
&lt;ul>
&lt;li>輸入：使用者選擇的伺服器&lt;/li>
&lt;li>處理：建立 WebSocket 連線、發送 auth token、開始接收 terminal output&lt;/li>
&lt;li>輸出：終端機畫面顯示 terminal output&lt;/li>
&lt;/ul>
&lt;p>加上可觀測性欄位後：&lt;/p>
&lt;table>
 &lt;thead>
 &lt;tr>
 &lt;th>類型&lt;/th>
 &lt;th>log 點&lt;/th>
 &lt;th>內容&lt;/th>
 &lt;/tr>
 &lt;/thead>
 &lt;tbody>
 &lt;tr>
 &lt;td>啟動&lt;/td>
 &lt;td>connect.start&lt;/td>
 &lt;td>目標 URL、觸發來源（使用者操作 / 自動重連）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>步驟&lt;/td>
 &lt;td>connect.biometric.done&lt;/td>
 &lt;td>認證結果、耗時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>步驟&lt;/td>
 &lt;td>connect.credential.loaded&lt;/td>
 &lt;td>使用者名稱（密碼 redact）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>步驟&lt;/td>
 &lt;td>connect.ws.connected&lt;/td>
 &lt;td>連線 URL、耗時&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>步驟&lt;/td>
 &lt;td>connect.auth.sent&lt;/td>
 &lt;td>token 長度（內容 redact）&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>步驟&lt;/td>
 &lt;td>connect.stream.subscribed&lt;/td>
 &lt;td>stream 狀態&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>錯誤&lt;/td>
 &lt;td>connect.{step}.failed&lt;/td>
 &lt;td>失敗步驟、error message、retry count&lt;/td>
 &lt;/tr>
 &lt;tr>
 &lt;td>完成&lt;/td>
 &lt;td>connect.done&lt;/td>
 &lt;td>總耗時、最終狀態&lt;/td>
 &lt;/tr>
 &lt;/tbody>
&lt;/table>
&lt;p>這張表在功能規格階段就能寫出來，因為它只依賴功能的流程設計，不依賴實作細節。功能流程確定後，每一步在哪裡需要 log 點就確定了。&lt;/p>
&lt;h2 id="log-點命名規則">log 點命名規則&lt;/h2>
&lt;p>統一的命名規則讓 log 可以被 grep、過濾和統計。&lt;/p>
&lt;p>&lt;strong>階層式命名&lt;/strong>：&lt;code>{功能}.{步驟}.{事件}&lt;/code>。例如 &lt;code>connect.ws.connected&lt;/code>、&lt;code>connect.auth.failed&lt;/code>。&lt;/p>
&lt;p>&lt;strong>事件後綴統一&lt;/strong>：&lt;code>start&lt;/code>（啟動）、&lt;code>done&lt;/code>（步驟完成）、&lt;code>failed&lt;/code>（失敗）、&lt;code>complete&lt;/code>（功能完成）。&lt;/p>
&lt;p>&lt;strong>和程式碼結構對應&lt;/strong>：log 點名稱對應到程式碼中的函式或模組。&lt;code>connect.biometric.done&lt;/code> 對應 &lt;code>BiometricService.authenticate()&lt;/code> 的成功路徑。這讓開發者看到 log 名稱就知道去哪裡找程式碼。&lt;/p>
&lt;h2 id="log-點規格的-review-檢查">log 點規格的 review 檢查&lt;/h2>
&lt;p>功能規格 review 時，可觀測性欄位的檢查要點：&lt;/p>
&lt;p>&lt;strong>每步都有 log&lt;/strong>：流程中的每個步驟在成功和失敗時都有對應的 log 點。遺漏的步驟意味著該步驟出問題時無法從 log 判斷。&lt;/p>
&lt;p>&lt;strong>錯誤 log 有足夠 context&lt;/strong>：error log 只寫「連線失敗」不夠；需要寫「連線失敗」加上 error code、目標 URL、已完成的步驟。&lt;/p>
&lt;p>&lt;strong>敏感欄位有 redaction 標記&lt;/strong>：密碼、token、個人資料在 log 規格中標記為 redact，實作時用 redaction 機制處理。&lt;/p>
&lt;p>&lt;strong>啟動和完成配對&lt;/strong>：每個功能有啟動 log 就應該有完成 log，形成完整的生命週期。&lt;/p>
&lt;h2 id="下一步路由">下一步路由&lt;/h2>
&lt;ul>
&lt;li>三層 log 的詳細設計 → &lt;a href="https://tarrragon.github.io/blog/testing/02-client-observability/three-layer-log-design/" data-link-title="三層 log 設計" data-link-desc="連線生命週期 log、protocol 訊息 log、使用者行為 log — 三層各自的職責、詳細程度和啟停控制">三層 log 設計&lt;/a>&lt;/li>
&lt;li>事後補 log 和設計產物 log 的差異 → &lt;a href="https://tarrragon.github.io/blog/testing/02-client-observability/hotfix-log-vs-designed-log/" data-link-title="「事後補 log」vs「設計產物 log」的品質差異" data-link-desc="事後補的 log 是救火工具、設計產物的 log 是可觀測性基礎設施 — 從 app_tunnel 的 W2 hotfix log 拆解兩者在格式、覆蓋率、維護成本上的差異">「事後補 log」vs「設計產物 log」的品質差異&lt;/a>&lt;/li>
&lt;li>Log 中的敏感資訊處理 → &lt;a href="https://tarrragon.github.io/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">monitoring 模組七 資安&lt;/a>&lt;/li>
&lt;/ul></description><content:encoded><![CDATA[<p>Log 點定義是功能規格的一部分，和 API schema 同級。功能規格描述「這個功能做什麼」，log 點規格描述「這個功能執行時留下什麼可觀察的紀錄」。把 log 點設計前移到規格階段，讓 log 成為功能的設計產物，而非事後的 debug 工具（本章合成，TF-9 Derive）。</p>
<h2 id="四類-log-點">四類 log 點</h2>
<p>每個功能的 log 點按執行時機分成四類。</p>
<h3 id="啟動-log">啟動 log</h3>
<p>功能開始執行時記錄。回答「這個功能是否被觸發了」。</p>
<p>啟動 log 包含觸發來源（使用者操作、系統排程、外部事件）和初始參數（連線目標、操作類型）。如果一個功能從未被觸發，啟動 log 的缺席就是線索。</p>
<h3 id="步驟-log">步驟 log</h3>
<p>功能執行過程中的每個關鍵步驟完成時記錄。回答「流程走到哪裡了」。</p>
<p>步驟 log 的粒度依功能複雜度而定。三步驟的功能每步記一條；十步驟的功能可以只記關鍵的三到五步。判斷標準是：如果這一步失敗，開發者是否需要知道失敗點在哪。</p>
<h3 id="錯誤-log">錯誤 log</h3>
<p>步驟失敗、例外捕獲、非預期狀態出現時記錄。回答「出了什麼問題」。</p>
<p>錯誤 log 必須包含足夠的 context 讓開發者不需要重現問題就能判斷原因。至少包含：哪一步失敗、失敗原因（error message）、當時的關鍵狀態值。</p>
<h3 id="完成-log">完成 log</h3>
<p>功能正常結束時記錄。回答「功能是否成功完成、花了多久」。</p>
<p>完成 log 包含執行結果和耗時。和啟動 log 配對使用 — 有啟動但沒有完成代表功能中途異常退出。</p>
<h2 id="在功能規格中加可觀測性欄位">在功能規格中加可觀測性欄位</h2>
<p>以 app_tunnel 的「連線到 ttyd 終端機」功能為例，傳統規格只寫：</p>
<ul>
<li>輸入：使用者選擇的伺服器</li>
<li>處理：建立 WebSocket 連線、發送 auth token、開始接收 terminal output</li>
<li>輸出：終端機畫面顯示 terminal output</li>
</ul>
<p>加上可觀測性欄位後：</p>
<table>
  <thead>
      <tr>
          <th>類型</th>
          <th>log 點</th>
          <th>內容</th>
      </tr>
  </thead>
  <tbody>
      <tr>
          <td>啟動</td>
          <td>connect.start</td>
          <td>目標 URL、觸發來源（使用者操作 / 自動重連）</td>
      </tr>
      <tr>
          <td>步驟</td>
          <td>connect.biometric.done</td>
          <td>認證結果、耗時</td>
      </tr>
      <tr>
          <td>步驟</td>
          <td>connect.credential.loaded</td>
          <td>使用者名稱（密碼 redact）</td>
      </tr>
      <tr>
          <td>步驟</td>
          <td>connect.ws.connected</td>
          <td>連線 URL、耗時</td>
      </tr>
      <tr>
          <td>步驟</td>
          <td>connect.auth.sent</td>
          <td>token 長度（內容 redact）</td>
      </tr>
      <tr>
          <td>步驟</td>
          <td>connect.stream.subscribed</td>
          <td>stream 狀態</td>
      </tr>
      <tr>
          <td>錯誤</td>
          <td>connect.{step}.failed</td>
          <td>失敗步驟、error message、retry count</td>
      </tr>
      <tr>
          <td>完成</td>
          <td>connect.done</td>
          <td>總耗時、最終狀態</td>
      </tr>
  </tbody>
</table>
<p>這張表在功能規格階段就能寫出來，因為它只依賴功能的流程設計，不依賴實作細節。功能流程確定後，每一步在哪裡需要 log 點就確定了。</p>
<h2 id="log-點命名規則">log 點命名規則</h2>
<p>統一的命名規則讓 log 可以被 grep、過濾和統計。</p>
<p><strong>階層式命名</strong>：<code>{功能}.{步驟}.{事件}</code>。例如 <code>connect.ws.connected</code>、<code>connect.auth.failed</code>。</p>
<p><strong>事件後綴統一</strong>：<code>start</code>（啟動）、<code>done</code>（步驟完成）、<code>failed</code>（失敗）、<code>complete</code>（功能完成）。</p>
<p><strong>和程式碼結構對應</strong>：log 點名稱對應到程式碼中的函式或模組。<code>connect.biometric.done</code> 對應 <code>BiometricService.authenticate()</code> 的成功路徑。這讓開發者看到 log 名稱就知道去哪裡找程式碼。</p>
<h2 id="log-點規格的-review-檢查">log 點規格的 review 檢查</h2>
<p>功能規格 review 時，可觀測性欄位的檢查要點：</p>
<p><strong>每步都有 log</strong>：流程中的每個步驟在成功和失敗時都有對應的 log 點。遺漏的步驟意味著該步驟出問題時無法從 log 判斷。</p>
<p><strong>錯誤 log 有足夠 context</strong>：error log 只寫「連線失敗」不夠；需要寫「連線失敗」加上 error code、目標 URL、已完成的步驟。</p>
<p><strong>敏感欄位有 redaction 標記</strong>：密碼、token、個人資料在 log 規格中標記為 redact，實作時用 redaction 機制處理。</p>
<p><strong>啟動和完成配對</strong>：每個功能有啟動 log 就應該有完成 log，形成完整的生命週期。</p>
<h2 id="下一步路由">下一步路由</h2>
<ul>
<li>三層 log 的詳細設計 → <a href="/blog/testing/02-client-observability/three-layer-log-design/" data-link-title="三層 log 設計" data-link-desc="連線生命週期 log、protocol 訊息 log、使用者行為 log — 三層各自的職責、詳細程度和啟停控制">三層 log 設計</a></li>
<li>事後補 log 和設計產物 log 的差異 → <a href="/blog/testing/02-client-observability/hotfix-log-vs-designed-log/" data-link-title="「事後補 log」vs「設計產物 log」的品質差異" data-link-desc="事後補的 log 是救火工具、設計產物的 log 是可觀測性基礎設施 — 從 app_tunnel 的 W2 hotfix log 拆解兩者在格式、覆蓋率、維護成本上的差異">「事後補 log」vs「設計產物 log」的品質差異</a></li>
<li>Log 中的敏感資訊處理 → <a href="/blog/monitoring/07-security-privacy/" data-link-title="模組七：資安與隱私" data-link-desc="SDK redaction / transport 加密 / collector access control / 去識別化 — 蒐集的資料本身就是風險資產">monitoring 模組七 資安</a></li>
</ul>
]]></content:encoded></item></channel></rss>