メトリクスのクエリ
Mastra では、5 種類の OLAP クエリ(getMetricAggregate、getMetricBreakdown、getMetricTimeSeries、getMetricPercentiles、およびディスカバリーヘルパー)を、インプロセスのストアアクセサー、ランタイム HTTP API、mastra api metric CLI という 3 つの方法で利用できます。いずれも同じ Zod 検証済みの入力形式を受け取るため、API を学び直すことなく、CLI による一度限りの調査からプログラムによるダッシュボードツールへ移行できます。
使用する場面使用する場面への直接リンク
- Studio と併用するカスタムダッシュボードや KPI タイルを構築する。
- トークンコストやレイテンシーがしきい値を超えたときに作動する定期アラートを実装する。
- Agent が自身のパフォーマンスメトリクスを読み取り、チャットで説明するための Tool を提供する。
- ターミナルから
mastra api metric ...を使って一度限りの調査を実行する。
Observability ストア自体のセットアップについては、メトリクスの概要を参照してください。クエリできるメトリクス名の一覧については、自動メトリクスのリファレンスを参照してください。
メトリクスクエリは Observability ドメインによって処理されるため、OLAP 対応のストア(ローカル環境では DuckDB、本番環境では ClickHouse)が必要です。セットアップについては、メトリクスの概要を参照してください。Observability ストアが設定されていない場合、getStore('observability') は null を返します。
利用方法利用方法への直接リンク
インプロセスインプロセスへの直接リンク
Tool、サーバールート、または Workflow のステップ内で、Mastra ストレージから Observability ストアを取得します。
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 を返します。
HTTPHTTPへの直接リンク
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/aggregatePOST /api/observability/metrics/breakdownPOST /api/observability/metrics/timeseriesPOST /api/observability/metrics/percentilesGET /api/observability/metrics(生の行、ページネーション対応)GET /api/observability/discovery/metric-namesGET /api/observability/discovery/metric-label-keysGET /api/observability/discovery/metric-label-values
@mastra/client-js SDK では、同じルートが mastraClient.getMetricAggregate(...)、getMetricBreakdown(...) などとしてラップされています。
CLICLIへの直接リンク
mastra api metric ... は、単一の JSON 引数を使って同じエンドポイントを呼び出します。そのため、Agent やシェルスクリプトはコードを書かずにメトリクスを取得できます。
mastra api metric aggregate \
'{"name":["mastra_agent_duration_ms"],"aggregation":"avg"}' \
--url http://localhost:4111
デフォルトでは、CLI はホストされている Mastra Observability(https://observability.mastra.ai)を接続先とします。ローカルの mastra dev サーバーをクエリするには、--url http://localhost:4111 を指定してください。コマンドの全一覧については、mastra api metric aggregateとその周辺の項目を参照してください。
クエリクエリへの直接リンク
getMetricAggregategetmetricaggregateへの直接リンク
KPI カードの構成要素となる単一のスカラー値を返します。
入力:
name: 1 つ以上のメトリクス名の配列。aggregation:'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct' | 'last'のいずれか。filters: 任意のフィルターオブジェクト。comparePeriod: 期間比較に使用する任意の'previous_period' | 'previous_day' | 'previous_week'。
レスポンス:
value、previousValue、changePercent。- トークンメトリクスの場合は、
estimatedCost、costUnit、previousEstimatedCost、costChangePercent。
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)
getMetricBreakdowngetmetricbreakdownへの直接リンク
1 つ以上のディメンションで行をグループ化し、各グループを集計します。「Agent 別のトークン数」など、上位 N 件を示すテーブルの構成要素になります。
入力:
name: メトリクス名の配列。groupBy: グループ化に使用するフィールドの配列(例:['entityName'])。aggregation: 上記と同じ列挙値。limit: サーバー側の上位 K 件の上限。カーディナリティの高いgroupByでは必須です。orderDirection:'ASC' | 'DESC'(デフォルトはDESC)。filters: 任意。
レスポンス: groups[]。各要素には dimensions(グループキーと値のレコード)、value、estimatedCost が含まれます。
const byAgent = await observability!.getMetricBreakdown({
name: ['mastra_model_total_input_tokens'],
groupBy: ['entityName'],
aggregation: 'sum',
limit: 10,
orderDirection: 'DESC',
})
getMetricTimeSeriesgetmetrictimeseriesへの直接リンク
固定間隔で値をバケット化します。折れ線グラフや棒グラフの構成要素になります。
入力:
name: メトリクス名の配列。interval:'1m' | '5m' | '15m' | '1h' | '1d'のいずれか。aggregation: 上記と同じ列挙値。groupBy: 任意。省略すると、複数のメトリクス名が合算されて 1 つの系列になります。個別の系列として保持するには、メトリクスごとに 1 回ずつ呼び出してください。filters: 任意。
レスポンス: series[]。各要素には name、costUnit、および { timestamp, value, estimatedCost } からなる points[] が含まれます。
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) },
},
})
getMetricPercentilesgetmetricpercentilesへの直接リンク
時間でバケット化したパーセンタイル値を返します。レイテンシーチャートの構成要素になります。
入力:
name: 単一のメトリクス名(配列ではなく文字列)。percentiles:0から1までの数値の配列(例:[0.5, 0.95, 0.99])。interval:getMetricTimeSeriesと同じ列挙値。filters: 任意。
レスポンス: series[]。各要素には percentile と、{ timestamp, value } からなる points[] が含まれます。
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-names | mastra api metric names |
getMetricLabelKeys | { metricName } | metric-label-keys | mastra api metric label-keys |
getMetricLabelValues | { metricName, labelKey, prefix?, limit? } | metric-label-values | mastra api metric label-values |
Trace およびログと共通(HTTP のみ。専用の CLI サブコマンドはありません):
| メソッド | 引数 | パスのサフィックス |
|---|---|---|
getEntityTypes | {} | entity-types |
getEntityNames | { entityType? } | entity-names |
getServiceNames | {} | service-names |
getEnvironments | {} | environments |
getTags | { entityType? } | tags |
フィルタリングフィルタリングへの直接リンク
すべてのクエリは同じ filters オブジェクトを受け取ります。特に有用なフィールドは次のとおりです。
name: 特定のメトリクス名に限定します(aggregate、breakdown、timeseries では、トップレベルのnameですでに同じ指定ができます。単一のクエリで複数のメトリクスを組み合わせる場合は、filters.nameを使用してください)。timestamp:{ start, end, startExclusive, endExclusive }。両方の境界は任意です。「現在まで」を指定するにはendを省略します。provider、model、costUnit: トークンおよびコストのメトリクス用。labels: メトリクスラベルに対するキーと値の完全一致。たとえば、duration メトリクスでは{ status: 'error' }。- 相関フィールド:
entityType、entityName、parentEntityName、rootEntityName、userId、organizationId、resourceId、runId、sessionId、threadId、requestId、executionSource、environment、serviceName、experimentId、tags。
3 つの利用方法すべてで、同じ形式の 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 は任意ですが、本番環境のストアに対して実行するクエリでは必須と考えてください。Observability テーブルは通常、イベント時刻を基準にパーティション化されます(TimescaleDB ではチャンク化)。timestamp.start(できれば end も)を指定すると、バックエンドは対象範囲と重なるパーティション(通常は 1 つか 2 つ)だけに絞り込めます。時間範囲を指定しない場合、プランナーはすべてのパーティションをスキャンする必要があり、1 年分の保持期間では数百セグメントに及ぶことがあります。これは、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)に当てはまりますが、時間境界が 1 つ欠けるたびに追加のパーティションスキャンが 1 回発生する Postgres v-next では特に重要です。
例: カスタム KPI タイルを構築する例: カスタム KPI タイルを構築するへの直接リンク
次の Tool は、直近 1 時間の入力トークン量と推定コストを返します。Agent またはダッシュボードは、クエリを再実装せずに structuredContent として呼び出せます。
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,
}
},
})