> Discover all available pages from the documentation index: https://mastra.zisheng.pro/zh-HK/llms.txt # Tracing Tracing 是一種可觀測性訊號,用以記錄請求如何流經 Agent、Workflow、Tool 及模型調用。Mastra 會將每項操作表示為 span,並把相關 span 組成 Trace,讓你檢視完整的執行路徑。 本頁聚焦於 Trace 特有的概念:span 階層、取樣、metadata、篩選、Trace ID,以及第三方 Trace context。 **供 AI Agent 使用:** 執行 `npx mastra api trace list '{"page":0,"perPage":20}'`,即可直接檢視近期的 Trace,毋須開啟 Studio 或編寫臨時腳本。此命令需要正在運行且已設定可觀測性的 Mastra 伺服器;你可以用 `npx mastra dev` 啟動本機伺服器,或透過 `--url` 傳入可連線伺服器的基礎 URL。建立其他篩選條件前,請先執行 `npx mastra api trace list --schema`。使用 `npx skills add mastra-ai/skills --skill mastra` 安裝 Mastra Skill,以取得完整的 API CLI 探索、目標指定、schema、驗證及錯誤處理指引。 ## 何時使用 tracing - 檢視完整執行路徑,以偵錯 Agent 或 Workflow 的非預期行為。 - 追蹤單一請求內的模型調用、Tool 調用及 Workflow 步驟。 - 加入 Trace 專用的 metadata 及標籤,以便篩選和調查。 - 將 Mastra Trace 連接至第三方 tracing 系統。 ## 開始使用 要開始使用 tracing,請在 Mastra instance 中設定可觀測性,然後運行 Agent 或 Workflow。你可以透過以下功能設定其行為: - [設定](https://mastra.zisheng.pro/zh-HK/docs/observability/overview):基礎可觀測性設定、多組設定,以及無伺服器環境的資料送出 - [儲存空間](https://mastra.zisheng.pro/zh-HK/docs/observability/overview):Trace、日誌及指標的儲存路由 - [整合概覽](https://mastra.zisheng.pro/zh-HK/docs/observability/integrations/overview):exporter、bridge 及 processor ## 取樣策略 取樣讓你控制要收集哪些 Trace,協助你在可觀測性需求與資源成本之間取得平衡。 在高流量的生產環境中,收集每個 Trace 可能成本高昂,而且並非必要。 取樣策略可擷取具代表性的 Trace 子集,同時確保不會遺漏錯誤或重要操作的關鍵資訊。 你可以在可觀測性設定層級配置取樣: ```ts export const mastra = new Mastra({ observability: new Observability({ configs: { '10_percent': { serviceName: 'my-service', // Sample 10% of traces sampling: { type: 'ratio', probability: 0.1, }, exporters: [new MastraStorageExporter()], }, }, }), }) ``` `sampling` 選項讓你控制要收集哪些 Trace,協助你在可觀測性需求與資源成本之間取得平衡。Mastra 支援四種取樣策略: 1. **一律取樣**:收集 100% 的 Trace。最適合需要完整可見性的開發、偵錯或低流量情境。 ```ts sampling: { type: 'always' } ``` 2. **永不取樣**:完全停用 tracing。適用於 tracing 沒有額外價值的特定環境,或需要在不移除設定的情況下暫時停用 tracing。 ```ts sampling: { type: 'never' } ``` 3. **按比例取樣**:隨機抽取一定百分比的 Trace。適合希望取得統計洞見、但不想承擔完整 tracing 成本的生產環境。機率值由 0(不取樣任何 Trace)至 1(取樣所有 Trace)。 ```ts sampling: { type: 'ratio', probability: 0.1 // Sample 10% of traces } ``` 4. **自訂取樣**:根據請求 context、metadata 或業務規則實作自己的取樣邏輯。非常適合按用戶層級、請求類型或錯誤條件取樣等複雜情境。 ```ts sampling: { type: 'custom', sampler: (options) => { // Sample premium users at higher rate if (options?.metadata?.userTier === 'premium') { return Math.random() < 0.5; // 50% sampling } // Default 1% sampling for others return Math.random() < 0.01; } } ``` ## 加入自訂 metadata 自訂 metadata 讓你為 Trace 附加額外 context,方便在生產環境中偵錯問題及了解系統行為。 Metadata 可以包含業務邏輯及效能指標,亦可帶有用戶 context,或任何可解釋執行期間所發生情況的其他資訊。 你可以使用 tracing context 為任何 span 加入 metadata: ```ts execute: async (inputData, context) => { const startTime = Date.now() const response = await fetch(inputData.endpoint) // Add custom metadata to the current span context?.tracingContext.currentSpan?.update({ metadata: { apiStatusCode: response.status, endpoint: inputData.endpoint, responseTimeMs: Date.now() - startTime, userTier: inputData.userTier, region: process.env.AWS_REGION, }, }) return await response.json() } ``` 此處設定的 metadata 會顯示於所有已配置的 exporter。 ### 以部署環境標記 Trace 在 Mastra 設定頂層 `environment` 欄位,即可自動將部署環境附加至所有可觀測性訊號,而毋須在每次調用時傳入 `tracingOptions.metadata.environment`。 ```ts export const mastra = new Mastra({ environment: 'production', observability: new Observability({ configs: { default: { serviceName: 'my-service', exporters: [new MastraStorageExporter()], }, }, }), }) ``` 如未設定 `environment`,Mastra 會改用 `process.env.NODE_ENV`。如兩者皆未設定,該欄位會維持 undefined,而不會猜測其值。 每次調用所傳入的 `tracingOptions.metadata.environment` 一律具有較高優先級,因此個別調用可按需要覆寫此值。 ### 從 `RequestContext` 自動取得 metadata 你毋須手動為每個 span 加入 metadata,可以設定 Mastra 自動從 RequestContext 擷取值,並將其作為 metadata 附加至 Trace 中的所有 span。這有助於在整個 Trace 中一致地追蹤用戶識別碼、環境資訊、功能旗標或任何請求範圍內的資料。 #### 設定層級擷取 在 tracing 設定中定義要擷取的 RequestContext key。以此設定建立的所有 span,都會自動將這些 key 納入 metadata: ```ts export const mastra = new Mastra({ observability: new Observability({ configs: { default: { serviceName: 'my-service', requestContextKeys: ['userId', 'environment', 'tenantId'], exporters: [new MastraStorageExporter()], }, }, }), }) ``` 現在,當你使用 RequestContext 執行 Agent 或 Workflow 時,系統會自動擷取這些值: ```ts const requestContext = new RequestContext() requestContext.set('userId', 'user-123') requestContext.set('environment', 'production') requestContext.set('tenantId', 'tenant-456') // All spans in this trace automatically get userId, environment, and tenantId metadata const result = await agent.generate('Hello', { requestContext, }) ``` #### 按請求加入額外項目 你可以使用 `tracingOptions.requestContextKeys` 加入 Trace 專用的 key。這些 key 會與設定層級的 key 合併: ```ts const requestContext = new RequestContext() requestContext.set('userId', 'user-123') requestContext.set('environment', 'production') requestContext.set('experimentId', 'exp-789') const result = await agent.generate('Hello', { requestContext, tracingOptions: { requestContextKeys: ['experimentId'], // Adds to configured keys }, }) // All spans now have: userId, environment, AND experimentId ``` #### 擷取巢狀值 使用點號標記法從 RequestContext 擷取巢狀值: ```ts export const mastra = new Mastra({ observability: new Observability({ configs: { default: { requestContextKeys: ['user.id', 'session.data.experimentId'], exporters: [new MastraStorageExporter()], }, }, }), }) const requestContext = new RequestContext() requestContext.set('user', { id: 'user-456', name: 'John Doe' }) requestContext.set('session', { data: { experimentId: 'exp-999' } }) // Metadata will include: { user: { id: 'user-456' }, session: { data: { experimentId: 'exp-999' } } } ``` #### 運作方式 1. **TraceState 計算**:Trace 開始時(建立根 span),Mastra 會合併設定層級與按請求指定的 key,以計算要擷取哪些 key 2. **自動擷取**:根 span(Agent 運行、Workflow 執行)會自動從 RequestContext 擷取 metadata 3. **子 span 擷取**:如建立子 span 時傳入 `requestContext`,子 span 亦可擷取 metadata 4. **Metadata 優先級**:明確傳入 span 選項的 metadata,一律優先於擷取所得的 metadata ### 為 Trace 加入標籤 標籤是字串標記,可協助你分類及篩選 Trace。與包含結構化 key-value 資料的 metadata 不同,標籤是純字串,專為快速篩選及整理而設。 執行 Agent 或 Workflow 時,使用 `tracingOptions.tags` 加入標籤: ```ts // With agents const result = await agent.generate('Hello', { tracingOptions: { tags: ['production', 'experiment-v2', 'user-request'], }, }) // With workflows const run = await mastra.getWorkflow('myWorkflow').createRun() const result = await run.start({ inputData: { data: 'process this' }, tracingOptions: { tags: ['batch-processing', 'priority-high'], }, }) ``` #### 標籤的運作方式 - **只套用至根 span**:標籤只會套用至 Trace 的根 span(Agent 運行或 Workflow 運行 span) - **廣泛支援**:大部分 exporter 均支援以標籤篩選及搜尋 Trace: - **Braintrust**:原生 `tags` 欄位 - **Langfuse**:Trace 上的原生 `tags` 欄位 - **ArizeExporter**:`tag.tags` OpenInference attribute - **OtelExporter**:`mastra.tags` span attribute - **OtelBridge**:`mastra.tags` span attribute - **可與 metadata 組合使用**:你可以在同一個 `tracingOptions` 中同時使用 `tags` 及 `metadata` ```ts const result = await agent.generate([{ role: 'user', content: 'Analyze this' }], { tracingOptions: { tags: ['production', 'analytics'], metadata: { userId: 'user-123', experimentId: 'exp-456' }, }, }) ``` #### 常見標籤模式 - **環境**:`"production"`、`"staging"`、`"development"` - **功能旗標**:`"feature-x-enabled"`、`"beta-user"` - **請求類型**:`"user-request"`、`"batch-job"`、`"scheduled-task"` - **優先級**:`"priority-high"`、`"priority-low"` - **實驗**:`"experiment-v1"`、`"control-group"`、`"treatment-a"` ### 隱藏敏感輸入/輸出 處理敏感資料時,你可能不希望可觀測性平台記錄輸入及輸出值。請在 `tracingOptions` 中使用 `hideInput` 及 `hideOutput`,從 Trace 的所有 span 排除此類資料: ```ts // Hide input data (e.g., user credentials, PII) const result = await agent.generate([{ role: 'user', content: 'Process this sensitive data' }], { tracingOptions: { hideInput: true, // Input will be hidden from all spans }, }) // Hide output data (e.g., generated secrets, confidential results) const result = await agent.generate([{ role: 'user', content: 'Generate API keys' }], { tracingOptions: { hideOutput: true, // Output will be hidden from all spans }, }) // Hide both input and output const result = await agent.generate([{ role: 'user', content: 'Handle confidential request' }], { tracingOptions: { hideInput: true, hideOutput: true, }, }) ``` #### 運作方式 - **整個 Trace 生效**:在根 span 設定後,這些選項會套用至 Trace 中所有子 span(Tool 調用、模型生成等) - **匯出時篩選**:資料在執行期間仍可供內部使用,但 span 匯出至可觀測性平台時會排除這些資料 - **可與其他選項組合使用**:你可以將 `hideInput`/`hideOutput` 與 `tags`、`metadata` 及其他 `tracingOptions` 一併使用 ```ts const result = await agent.generate([{ role: 'user', content: 'Sensitive operation' }], { tracingOptions: { hideInput: true, hideOutput: true, tags: ['sensitive-operation', 'pii-handling'], metadata: { operationType: 'credential-processing' }, }, }) ``` 如需更精細地控制敏感資料,可考慮使用 [Sensitive Data Filter](https://mastra.zisheng.pro/zh-HK/docs/observability/integrations/processors/sensitive-data-filter) processor。它可遮蓋特定欄位(例如密碼、token 及金鑰),同時保留輸入/輸出的其餘部分。 #### 子 span 與 metadata 擷取 在 Tool 或 Workflow 步驟內建立子 span 時,可以傳入 `requestContext` 參數以啟用 metadata 擷取: ```ts execute: async (inputData, context) => { // Create child span WITH requestContext - gets metadata extraction const dbSpan = context?.tracingContext.currentSpan?.createChildSpan({ type: 'generic', name: 'database-query', requestContext: context?.requestContext, // Pass to enable metadata extraction }) const results = await db.query('SELECT * FROM users') dbSpan?.end({ output: results }) // Or create child span WITHOUT requestContext - no metadata extraction const cacheSpan = context?.tracingContext.currentSpan?.createChildSpan({ type: 'generic', name: 'cache-check', // No requestContext - won't extract metadata }) return results } ``` 你可以精細控制哪些子 span 包含 RequestContext metadata。根 span(Agent/Workflow 執行)一律會自動擷取 metadata,而子 span 只會在你明確傳入 `requestContext` 時擷取。 ## 建立子 span 子 span 讓你追蹤 Workflow 步驟或 Tool 內的精細操作,並提供資料庫查詢、API 調用、檔案操作或複雜計算等子操作的可見性。這種階層結構有助你找出效能樽頸,並了解操作的確切次序。 在 Tool 調用或 Workflow 步驟內建立子 span,以追蹤特定操作: ```ts execute: async (inputData, context) => { // Create another child span for the main database operation const querySpan = context?.tracingContext.currentSpan?.createChildSpan({ type: 'generic', name: 'database-query', input: { query: inputData.query }, metadata: { database: 'production' }, }) try { const results = await db.query(inputData.query) querySpan?.end({ output: results.data, metadata: { rowsReturned: results.length, queryTimeMs: results.executionTime, cacheHit: results.fromCache, }, }) return results } catch (error) { querySpan?.error({ error, metadata: { retryable: isRetryableError(error) }, }) throw error } } ``` 子 span 會自動繼承其父項的 Trace context,從而在可觀測性平台中維持關係階層。 ## Span 格式化 Mastra 提供兩種方法,讓你在 span 資料到達可觀測性平台前進行轉換:**span processor** 及**自訂 span formatter**。兩者均可修改、篩選或豐富 Trace 資料,但運作層級及用途各有不同。 | 功能 | Span processor | 自訂 span formatter | | ----- | -------------- | ---------------------- | | 設定層級 | 可觀測性設定 | 按 exporter 設定 | | 操作對象 | 內部 `Span` 物件 | 已匯出的 `ExportedSpan` 資料 | | 套用範圍 | 所有 exporter | 單一 exporter | | 非同步支援 | 否 | 是 | | 使用情境 | 保安、篩選、資料豐富化 | 平台專用格式、非同步資料豐富化 | 如同步轉換應套用至所有 exporter(例如遮蓋敏感資料),請使用 **span processor**。如不同 exporter 需要以不同方式表示相同資料(例如一個平台使用純文字,另一個使用結構化資料),或需要執行從外部 API 擷取資料等非同步操作,請使用**自訂 span formatter**。 ### Span processor Span processor 會在 Trace 資料匯出前轉換、篩選或豐富資料。它們是 span 建立與匯出之間的管線,讓你可基於保安、合規或偵錯需要修改 span。Processor 只會運行一次,並影響所有 exporter。 #### 內置 processor - [Sensitive Data Filter](https://mastra.zisheng.pro/zh-HK/docs/observability/integrations/processors/sensitive-data-filter) 會遮蓋敏感資訊,並已在預設可觀測性設定中啟用。 #### 建立自訂 processor 你可以實作 `SpanOutputProcessor` interface 來建立自訂 span processor。以下基本範例會將 span 中所有輸入文字轉為小寫: ```ts import type { SpanOutputProcessor, AnySpan } from '@mastra/observability' export class LowercaseInputProcessor implements SpanOutputProcessor { name = 'lowercase-processor' process(span: AnySpan): AnySpan { span.input = `${span.input}`.toLowerCase() return span } async shutdown(): Promise { // Cleanup if needed } } // Use the custom processor export const mastra = new Mastra({ observability: new Observability({ configs: { development: { spanOutputProcessors: [new LowercaseInputProcessor(), new SensitiveDataFilter()], exporters: [new MastraStorageExporter()], }, }, }), }) ``` Processor 會按定義次序執行,讓你串連多項轉換。常見使用情境包括: - 遮蓋敏感資料(密碼、token、API 金鑰) - 加入環境專用 metadata - 按條件篩走 span - 標準化資料格式 - 使用業務 context 豐富 span 如需了解更廣泛的 exporter、bridge 及 processor 模型,請參閱[整合概覽](https://mastra.zisheng.pro/zh-HK/docs/observability/integrations/overview)。 ## Span 篩選 Span 篩選讓你在資料到達可觀測性平台前減少雜訊及每個 span 的成本。你可以按可觀測性 instance 設定,讓不同 exporter 或環境保留不同詳細程度的資料。 - 使用 `excludeSpanTypes`,以最少設定捨棄整個 span 類別。 - 如需按已匯出的 span 資料套用自訂邏輯,請使用 `spanFilter`。 以下範例示範如何在單一設定中組合兩個選項: ```ts import { Mastra } from '@mastra/core' import { SpanType } from '@mastra/core/observability' import { Observability, MastraStorageExporter } from '@mastra/observability' import { LangfuseExporter } from '@mastra/langfuse' export const mastra = new Mastra({ observability: new Observability({ configs: { default: { serviceName: 'my-app', exporters: [new MastraStorageExporter(), new LangfuseExporter()], excludeSpanTypes: [SpanType.MODEL_CHUNK, SpanType.MODEL_STEP], spanFilter: span => { if (span.type === SpanType.TOOL_CALL && span.attributes?.success) { return false } return true }, }, }, }), }) ``` 篩選會在匯出時按以下次序進行: 1. 除非 `includeInternalSpans` 為 `true`,否則捨棄內部 span。 2. `excludeSpanTypes` 移除相符的 span 類型。 3. `spanOutputProcessors` 轉換餘下的 span。 4. `spanFilter` 決定是否保留最終匯出的 span。 如 `spanFilter` 擲出錯誤,Mastra 會保留該 span 並記錄錯誤,以避免資料在沒有提示下遺失。如需完整 span 類型清單及更多範例,請參閱 [Span 篩選參考](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/span-filtering)。 ### 自訂 span formatter 自訂 span formatter 可轉換 span 在特定可觀測性平台中的顯示方式。Formatter 與 span processor 不同,會按 exporter 設定,因此可為不同目的地採用不同格式。Formatter 同時支援同步及非同步操作。 #### 使用情境 - **從 AI SDK 訊息擷取純文字**:將結構化訊息陣列轉換為易讀文字 - **轉換輸入/輸出格式**:自訂資料在特定平台中的顯示方式 - **平台專用欄位配對**:按平台要求加入或移除欄位 - **非同步資料豐富化**:從外部 API 或資料庫擷取額外 context #### 設定 在任何 exporter 設定中加入 `customSpanFormatter`: ```ts import { BraintrustExporter } from '@mastra/braintrust' import { LangfuseExporter } from '@mastra/langfuse' import { SpanType } from '@mastra/core/observability' import type { CustomSpanFormatter } from '@mastra/core/observability' // Formatter that extracts plain text from AI messages const plainTextFormatter: CustomSpanFormatter = span => { if (span.type === SpanType.AGENT_RUN && Array.isArray(span.input)) { const userMessage = span.input.find(m => m.role === 'user') return { ...span, input: userMessage?.content ?? span.input, } } return span } export const mastra = new Mastra({ observability: new Observability({ configs: { default: { serviceName: 'my-service', exporters: [ // Braintrust gets plain text formatting new BraintrustExporter({ customSpanFormatter: plainTextFormatter, }), // Langfuse keeps the original structured format new LangfuseExporter(), ], }, }, }), }) ``` #### 串連多個 formatter 使用 `chainFormatters` 組合多個 formatter。Formatter 鏈同時支援同步及非同步 formatter: ```ts import { chainFormatters } from '@mastra/observability' const inputFormatter: CustomSpanFormatter = span => ({ ...span, input: extractPlainText(span.input), }) const outputFormatter: CustomSpanFormatter = span => ({ ...span, output: extractPlainText(span.output), }) const exporter = new BraintrustExporter({ customSpanFormatter: chainFormatters([inputFormatter, outputFormatter]), }) ``` #### 非同步 formatter 自訂 span formatter 支援非同步操作,可用於從外部 API 或資料庫擷取資料以豐富 span 等情境: ```ts import type { CustomSpanFormatter } from '@mastra/core/observability' // Async formatter that enriches spans with user data const userEnrichmentFormatter: CustomSpanFormatter = async span => { const userId = span.metadata?.userId if (!userId) return span // Fetch user data from your API or database const userData = await fetchUserData(userId) return { ...span, metadata: { ...span.metadata, userName: userData.name, userEmail: userData.email, department: userData.department, }, } } // Async formatter that looks up additional context const contextEnrichmentFormatter: CustomSpanFormatter = async span => { if (span.type !== SpanType.AGENT_RUN) return span // Fetch experiment configuration const experimentConfig = await getExperimentConfig(span.metadata?.experimentId) return { ...span, metadata: { ...span.metadata, experimentVariant: experimentConfig?.variant, experimentGroup: experimentConfig?.group, }, } } // Use async formatters with an exporter const exporter = new BraintrustExporter({ customSpanFormatter: userEnrichmentFormatter, }) // Or chain sync and async formatters together const exporter = new LangfuseExporter({ customSpanFormatter: chainFormatters([ plainTextFormatter, // sync userEnrichmentFormatter, // async contextEnrichmentFormatter, // async ]), }) ``` > **備註:** 非同步 formatter 會增加 span 匯出的延遲。請確保非同步操作快速完成(100 毫秒以內),以免拖慢應用程式。對經常存取的資料,可考慮使用快取。 ## 序列化選項 序列化選項控制 span 資料(輸入、輸出及 attribute)在匯出前如何截斷。處理大型 payload、深層巢狀物件,或需要最佳化 Trace 儲存時,這項功能十分實用。 ### 設定 在可觀測性設定中加入 `serializationOptions`: ```ts export const mastra = new Mastra({ observability: new Observability({ configs: { default: { serviceName: 'my-service', serializationOptions: { maxStringLength: 2048, // Maximum length for string values (default: 1024) maxDepth: 10, // Maximum depth for nested objects (default: 6) maxArrayLength: 100, // Maximum number of items in arrays (default: 50) maxObjectKeys: 75, // Maximum number of keys in objects (default: 50) }, exporters: [new MastraStorageExporter()], }, }, }), }) ``` ### 可用選項 | 選項 | 預設值 | 說明 | | ----------------- | ---- | ------------------------- | | `maxStringLength` | 1024 | 字串值的最大長度。較長的字串會被截斷。 | | `maxDepth` | 6 | 巢狀物件的最大深度。更深層級會被省略。 | | `maxArrayLength` | 50 | 陣列的最大項目數目。額外項目會被省略。 | | `maxObjectKeys` | 50 | 物件的最大 key 數目。額外 key 會被省略。 | ### 使用情境 **提高限制以便偵錯**:如 Agent 或 Tool 會處理大型文件、API 回應或資料結構,請提高這些限制,以在 Trace 中擷取更多 context: ```ts serializationOptions: { maxStringLength: 8192, // Capture longer text content maxDepth: 12, // Handle deeply nested JSON responses maxArrayLength: 200, // Keep more items from large lists } ``` **縮減生產環境的 Trace 大小**:如毋須查看完整 payload,可降低這些值,以減少儲存成本並改善效能: ```ts serializationOptions: { maxStringLength: 256, // Truncate strings aggressively maxDepth: 3, // Shallow object representation maxArrayLength: 10, // Keep only first few items maxObjectKeys: 20, // Limit object keys } ``` 所有選項均為選填;如未指定,便會使用上方所示的預設值。 ## 取得 Trace ID 啟用 tracing 後執行 Agent 或 Workflow,回應會包含 `traceId`,你可以用它在可觀測性平台查找完整 Trace。這有助於偵錯或客戶支援,亦可用來將 Trace 與系統中的其他事件關聯起來。 ### Agent Trace ID `generate` 及 `stream` 方法都會在回應中傳回 Trace ID: ```ts // Using generate const result = await agent.generate('Hello') console.log('Trace ID:', result.traceId) // Using stream const streamResult = await agent.stream('Tell me a story') console.log('Trace ID:', streamResult.traceId) ``` ### Workflow Trace ID Workflow 執行亦會傳回 Trace ID: ```ts // Create a workflow run const run = await mastra.getWorkflow('myWorkflow').createRun() // Start the workflow const result = await run.start({ inputData: { data: 'process this' }, }) console.log('Trace ID:', result.traceId) // Or stream the workflow const { stream, getWorkflowState } = run.stream({ inputData: { data: 'process this' }, }) // Get the final state which includes the trace ID const finalState = await getWorkflowState() console.log('Trace ID:', finalState.traceId) ``` ### 使用 Trace ID 取得 Trace ID 後,你可以: 1. **在 Studio 查找 Trace**:前往 Trace 檢視畫面並按 ID 搜尋 2. **在外部平台查詢 Trace**:在 Langfuse、Braintrust、MLflow 或你的可觀測性平台中使用該 ID 3. **與日誌建立關聯**:在應用程式日誌中加入 Trace ID,以便互相參照 4. **分享以供偵錯**:向支援團隊或開發人員提供 Trace ID 以作調查 Trace ID 只會在啟用 tracing 時提供。如 tracing 已停用,或取樣排除了該請求,`traceId` 便會是 `undefined`。 ## 與外部 tracing 系統整合 在已有分散式 tracing(OpenTelemetry、Datadog 等)的應用程式內運行 Mastra Agent 或 Workflow 時,你可以將 Mastra Trace 連接至父 Trace context。這會為整個請求流程建立統一檢視,讓你更容易了解 Mastra 操作如何配合整體系統運作。 ### 傳入外部 Trace ID 使用 `tracingOptions` 參數,指定來自父系統的 Trace context: ```ts // Get trace context from your existing tracing system const parentTraceId = getCurrentTraceId() // Your tracing system const parentSpanId = getCurrentSpanId() // Your tracing system // Execute Mastra operations as part of the parent trace const result = await agent.generate('Analyze this data', { tracingOptions: { traceId: parentTraceId, parentSpanId: parentSpanId, }, }) // The Mastra trace will now appear as a child in your distributed trace ``` ### OpenTelemetry 整合 與 OpenTelemetry 整合後,Mastra Trace 可直接顯示於現有的可觀測性平台: ```ts import { trace } from '@opentelemetry/api' // Get the current OpenTelemetry span const currentSpan = trace.getActiveSpan() const spanContext = currentSpan?.spanContext() if (spanContext) { const result = await agent.generate(userMessage, { tracingOptions: { traceId: spanContext.traceId, parentSpanId: spanContext.spanId, }, }) } ``` ### Workflow 整合 Workflow 支援相同的 Trace 傳播模式: ```ts const workflow = mastra.getWorkflow('data-pipeline') const run = await workflow.createRun() const result = await run.start({ inputData: { data: '...' }, tracingOptions: { traceId: externalTraceId, parentSpanId: externalSpanId, }, }) ``` ### ID 格式要求 Mastra 會驗證 Trace 及 span ID,以確保兼容性: - **Trace ID**:1 至 32 個十六進制字元(OpenTelemetry 使用 32 個) - **Span ID**:1 至 16 個十六進制字元(OpenTelemetry 使用 16 個) Mastra 會妥善處理無效 ID,記錄錯誤後繼續運行: - 無效 Trace ID → 產生新的 Trace ID - 無效父 span ID → 忽略父項關係 因此,即使輸入格式錯誤,tracing 亦不會令應用程式崩潰。 ### 範例:Express middleware 以下完整範例展示如何在 Express 應用程式中傳播 Trace: ```ts import { trace } from '@opentelemetry/api' import express from 'express' const app = express() app.post('/api/analyze', async (req, res) => { // Get current OpenTelemetry context const currentSpan = trace.getActiveSpan() const spanContext = currentSpan?.spanContext() const result = await agent.generate(req.body.message, { tracingOptions: spanContext ? { traceId: spanContext.traceId, parentSpanId: spanContext.spanId, } : undefined, }) res.json(result) }) ``` 這會建立單一分散式 Trace,同時包含 HTTP 請求處理及 Mastra Agent 執行,並可在你選用的可觀測性平台中檢視。 ## 會追蹤甚麼 Mastra 會自動為以下項目建立 span: ### Agent 操作 - **Agent 運行**:包含指示及 Tool 的完整執行過程 - **LLM 調用**:包含 token 及參數的模型互動 - **Tool 執行**:包含輸入及輸出的函數調用 - **記憶體操作**:thread 及語義回憶 ### Workflow 操作 - **Workflow 運行**:從開始至結束的完整執行過程 - **個別步驟**:包含輸入/輸出的步驟處理 - **控制流程**:條件、循環及並行執行 - **等待操作**:延遲及事件等待 ## 另請參閱 ### 參考文件 - [設定 API](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/configuration):ObservabilityConfig 詳細資料 - [Tracing class](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/instances):核心 class 及方法 - [Span interface](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/spans):Span 類型及生命週期 - [類型定義](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/interfaces):完整 interface 參考 - [Span 篩選](https://mastra.zisheng.pro/zh-HK/reference/observability/tracing/span-filtering):篩選行為、span 類型及範例