跳至主要內容

查詢指標

Mastra 透過三種介面提供相同的五種 OLAP 查詢(getMetricAggregategetMetricBreakdowngetMetricTimeSeriesgetMetricPercentiles 及探索輔助函式):行程內儲存存取器、執行階段 HTTP API,以及 mastra api metric CLI。三者接受相同並經 Zod 驗證的輸入結構,因此你可以由一次性的 CLI 調查轉移至程式化儀表板 Tool,毋須重新學習 API。

適用情況
適用情況 的直接連結

  • 在 Studio 旁建立自訂儀表板或 KPI 資訊方塊。
  • 建立排程警報,在 token 成本或延遲超出臨界值時觸發。
  • 為 Agent 提供可讀取自身效能指標並在對話中加以解釋的 Tool。
  • 從終端機使用 mastra api metric ... 進行一次性調查。

如要設定可觀測性儲存本身,請參閱指標概覽。如要查看可供查詢的指標名稱清單,請參閱自動指標參考

備註

指標查詢由可觀測性網域提供,而該網域需要支援 OLAP 的儲存(本機使用 DuckDB,正式環境使用 ClickHouse)。設定方法請參閱指標概覽。如果尚未設定可觀測性儲存,getStore('observability') 會傳回 null

介面
介面 的直接連結

行程內
行程內 的直接連結

在 Tool、伺服器路由或 Workflow 步驟中,從 Mastra 儲存取得可觀測性儲存:

src/mastra/tools/agent-latency-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const agentLatencyTool = createTool({
id: 'agentLatency',
description: 'Average agent latency over the last hour.',
inputSchema: z.object({}),
execute: async (_input, context) => {
const observability = await context.mastra!.getStorage()!.getStore('observability')
if (!observability) {
throw new Error('Observability domain is not configured (requires DuckDB or ClickHouse)')
}

const result = await observability.getMetricAggregate({
name: ['mastra_agent_duration_ms'],
aggregation: 'avg',
filters: {
timestamp: { start: new Date(Date.now() - 60 * 60 * 1000) },
},
})

return { averageMs: result.value }
},
})

當已設定的後端不支援 OLAP 查詢時,getStore('observability') 會傳回 null

HTTP
HTTP 的直接連結

mastra dev 伺服器(以及任何已部署的 Mastra 執行階段)會在 /api/observability/metrics/* 下提供相同的查詢。彙總、細分、時間序列及百分位數端點會透過 POST 接收 JSON 內文。探索端點則使用帶有查詢參數的 GET

curl -sS -X POST http://localhost:4111/api/observability/metrics/aggregate \
-H "content-type: application/json" \
-d '{"name":["mastra_agent_duration_ms"],"aggregation":"avg"}'

可用路由:

  • POST /api/observability/metrics/aggregate
  • POST /api/observability/metrics/breakdown
  • POST /api/observability/metrics/timeseries
  • POST /api/observability/metrics/percentiles
  • GET /api/observability/metrics(原始資料列,已分頁)
  • GET /api/observability/discovery/metric-names
  • GET /api/observability/discovery/metric-label-keys
  • GET /api/observability/discovery/metric-label-values

@mastra/client-js SDK 會將相同的路由封裝為 mastraClient.getMetricAggregate(...)getMetricBreakdown(...) 等方法。

CLI
CLI 的直接連結

mastra api metric ... 會以單一 JSON 參數呼叫相同的端點,因此 Agent 或 shell 腳本毋須編寫任何程式碼即可擷取指標:

mastra api metric aggregate \
'{"name":["mastra_agent_duration_ms"],"aggregation":"avg"}' \
--url http://localhost:4111

CLI 預設以託管的 Mastra 可觀測性服務(https://observability.mastra.ai)為目標。傳入 --url http://localhost:4111 即可查詢本機 mastra dev 伺服器。如要查看完整命令清單,請參閱 mastra api metric aggregate 及其附近的條目。

查詢
查詢 的直接連結

getMetricAggregate
getmetricaggregate 的直接連結

傳回單一純量,是建立 KPI 卡片的基礎。

輸入:

  • name:包含一個或多個指標名稱的陣列。
  • aggregation:可選 'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct' | 'last' 其中之一。
  • filters:可選的篩選物件
  • comparePeriod:可選 'previous_period' | 'previous_day' | 'previous_week',用於比較不同期間。

回應:

  • valuepreviousValuechangePercent
  • token 指標的 estimatedCostcostUnitpreviousEstimatedCostcostChangePercent
src/mastra/tools/token-cost-tool.ts
const observability = await mastra.getStorage()!.getStore('observability')

const cost = await observability!.getMetricAggregate({
name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],
aggregation: 'sum',
comparePeriod: 'previous_day',
})

console.log(cost.value, cost.estimatedCost, cost.costUnit, cost.changePercent)

getMetricBreakdown
getmetricbreakdown 的直接連結

按照一個或多個維度將資料列分組,並彙總每個群組,是建立前 N 名表格(例如「按 Agent 劃分的 token」)的基礎。

輸入:

  • name:指標名稱陣列。
  • groupBy:用於分組的欄位陣列(例如 ['entityName'])。
  • aggregation:與上述相同的列舉值。
  • limit:伺服器端的前 K 名上限。使用高基數 groupBy 時必須提供。
  • orderDirection'ASC' | 'DESC'(預設為 DESC)。
  • filters:可選。

回應:groups[],每項均包含 dimensions(由群組鍵對應至值的記錄)、valueestimatedCost

const byAgent = await observability!.getMetricBreakdown({
name: ['mastra_model_total_input_tokens'],
groupBy: ['entityName'],
aggregation: 'sum',
limit: 10,
orderDirection: 'DESC',
})

getMetricTimeSeries
getmetrictimeseries 的直接連結

以固定間隔將值分桶,是建立折線圖及棒形圖的基礎。

輸入:

  • name:指標名稱陣列。
  • interval:可選 '1m' | '5m' | '15m' | '1h' | '1d' 其中之一。
  • aggregation:相同的列舉值。
  • groupBy:可選。省略時,多個指標名稱會合計為一個序列。如要將各指標分開,請為每個指標各呼叫一次。
  • filters:可選。

回應:series[],每項均包含 namecostUnitpoints[],當中的資料點結構為 { timestamp, value, estimatedCost }

const inputTokens = await observability!.getMetricTimeSeries({
name: ['mastra_model_total_input_tokens'],
aggregation: 'sum',
interval: '1h',
filters: {
timestamp: { start: new Date(Date.now() - 24 * 60 * 60 * 1000) },
},
})

getMetricPercentiles
getmetricpercentiles 的直接連結

傳回按時間分桶的百分位數值,是建立延遲圖表的基礎。

輸入:

  • name:單一指標名稱(字串,而非陣列)。
  • percentiles:介乎 01 之間的數字陣列,例如 [0.5, 0.95, 0.99]
  • interval:與 getMetricTimeSeries 相同的列舉值。
  • filters:可選。

回應:series[],每項均包含 percentilepoints[],當中的資料點結構為 { timestamp, value }

const latency = await observability!.getMetricPercentiles({
name: 'mastra_agent_duration_ms',
percentiles: [0.5, 0.95],
interval: '1h',
})

探索
探索 的直接連結

使用這些端點填入下拉式選單,或為 Agent 提供可供篩選的值清單。所有探索路由均使用 GET,並位於 /api/observability/discovery/ 下。

指標專用(亦以 mastra api metric 子命令提供):

方法參數路徑後綴CLI
getMetricNames{ prefix?, limit? }metric-namesmastra api metric names
getMetricLabelKeys{ metricName }metric-label-keysmastra api metric label-keys
getMetricLabelValues{ metricName, labelKey, prefix?, limit? }metric-label-valuesmastra api metric label-values

與 Trace 及日誌共用(僅限 HTTP,沒有專用 CLI 子命令):

方法參數路徑後綴
getEntityTypes{}entity-types
getEntityNames{ entityType? }entity-names
getServiceNames{}service-names
getEnvironments{}environments
getTags{ entityType? }tags

篩選
篩選 的直接連結

每種查詢都接受相同的 filters 物件。最實用的欄位包括:

  • name:限制為指定的指標名稱。(對於彙總/細分/時間序列,頂層 name 已可達到此目的。如要在單一查詢中混合多個指標,請使用 filters.name。)
  • timestamp{ start, end, startExclusive, endExclusive }。兩個界限均為可選。省略 end 即表示「直至現在」。
  • providermodelcostUnit:用於 token 及成本指標。
  • labels:與指標標籤進行精確鍵值配對,例如持續時間指標可使用 { status: 'error' }
  • 關聯欄位:entityTypeentityNameparentEntityNamerootEntityNameuserIdorganizationIdresourceIdrunIdsessionIdthreadIdrequestIdexecutionSourceenvironmentserviceNameexperimentIdtags

相同的 filters 結構適用於全部三種介面:

// In-process
await observability!.getMetricAggregate({
name: ['mastra_tool_duration_ms'],
aggregation: 'avg',
filters: { entityName: 'weatherTool', labels: { status: 'error' } },
})
# CLI
mastra api metric aggregate \
'{"name":["mastra_tool_duration_ms"],"aggregation":"avg","filters":{"entityName":"weatherTool","labels":{"status":"error"}}}' \
--url http://localhost:4111
# HTTP
curl -sS -X POST http://localhost:4111/api/observability/metrics/aggregate \
-H "content-type: application/json" \
-d '{"name":["mastra_tool_duration_ms"],"aggregation":"avg","filters":{"entityName":"weatherTool","labels":{"status":"error"}}}'

一律提供時間範圍
一律提供時間範圍 的直接連結

filters.timestamp 屬於可選項目,但對於任何在正式環境儲存上運行的查詢,你都應將其視為必要項目。可觀測性資料表通常會按事件時間分割(TimescaleDB 則會分塊)。提供 timestamp.start(最好亦提供 end)後,後端可將查詢範圍縮減至與該範圍重疊的分割區,通常只有一至兩個。如果不提供時間範圍,規劃器便必須掃描每個分割區;若保留期為一年,可能涉及數百個區段,這亦是採用 Postgres 後端的儲存出現 OLAP 查詢緩慢的最常見原因。

臨時查詢的穩妥預設值是過去 24 小時;警報及儀表板則應配合其實際評估時段:

await observability!.getMetricAggregate({
name: ['mastra_agent_duration_ms'],
aggregation: 'p95',
filters: {
timestamp: { start: new Date(Date.now() - 24 * 60 * 60 * 1000) },
},
})

這項指引適用於所有後端(ClickHouse、Postgres v-next、DuckDB),但對 Postgres v-next 最為重要,因為每缺少一個時間界限,都會直接增加一次分割區掃描。

範例:建立自訂 KPI 資訊方塊
範例:建立自訂 KPI 資訊方塊 的直接連結

以下 Tool 會傳回過去一小時的輸入 token 數量及估算成本。Agent 或儀表板可透過 structuredContent 呼叫此 Tool,毋須重新實作查詢。

src/mastra/tools/token-kpi-tool.ts
import { createTool } from '@mastra/core/tools'
import { z } from 'zod'

export const tokenKpiTool = createTool({
id: 'tokenKpi',
description: 'Returns input-token volume and estimated cost for the last hour.',
inputSchema: z.object({}),
outputSchema: z.object({
inputTokens: z.number().nullable(),
estimatedCost: z.number().nullable(),
costUnit: z.string().nullable(),
changePercent: z.number().nullable(),
}),
execute: async (_input, context) => {
const observability = await context.mastra!.getStorage()!.getStore('observability')
if (!observability) {
throw new Error('Observability domain is not configured (requires DuckDB or ClickHouse)')
}

const result = await observability.getMetricAggregate({
name: ['mastra_model_total_input_tokens'],
aggregation: 'sum',
filters: {
timestamp: { start: new Date(Date.now() - 60 * 60 * 1000) },
},
comparePeriod: 'previous_period',
})

return {
inputTokens: result.value,
estimatedCost: result.estimatedCost ?? null,
costUnit: result.costUnit ?? null,
changePercent: result.changePercent ?? null,
}
},
})