メインコンテンツへ移動

メトリクスのクエリ

Mastra では、5 種類の OLAP クエリ(getMetricAggregategetMetricBreakdowngetMetricTimeSeriesgetMetricPercentiles、およびディスカバリーヘルパー)を、インプロセスのストアアクセサー、ランタイム 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 ストアを取得します。

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 やシェルスクリプトはコードを書かずにメトリクスを取得できます。

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とその周辺の項目を参照してください。

クエリ
クエリへの直接リンク

getMetricAggregate
getmetricaggregateへの直接リンク

KPI カードの構成要素となる単一のスカラー値を返します。

入力:

  • name: 1 つ以上のメトリクス名の配列。
  • aggregation: 'sum' | 'avg' | 'min' | 'max' | 'count' | 'count_distinct' | 'last' のいずれか。
  • filters: 任意のフィルターオブジェクト
  • comparePeriod: 期間比較に使用する任意の 'previous_period' | 'previous_day' | 'previous_week'

レスポンス:

  • valuepreviousValuechangePercent
  • トークンメトリクスの場合は、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への直接リンク

1 つ以上のディメンションで行をグループ化し、各グループを集計します。「Agent 別のトークン数」など、上位 N 件を示すテーブルの構成要素になります。

入力:

  • 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: 任意。省略すると、複数のメトリクス名が合算されて 1 つの系列になります。個別の系列として保持するには、メトリクスごとに 1 回ずつ呼び出してください。
  • filters: 任意。

レスポンス: series[]。各要素には namecostUnit、および { 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) },
},
})

getMetricPercentiles
getmetricpercentilesへの直接リンク

時間でバケット化したパーセンタイル値を返します。レイテンシーチャートの構成要素になります。

入力:

  • 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-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: 特定のメトリクス名に限定します(aggregate、breakdown、timeseries では、トップレベルの name ですでに同じ指定ができます。単一のクエリで複数のメトリクスを組み合わせる場合は、filters.name を使用してください)。
  • timestamp: { start, end, startExclusive, endExclusive }。両方の境界は任意です。「現在まで」を指定するには end を省略します。
  • providermodelcostUnit: トークンおよびコストのメトリクス用。
  • labels: メトリクスラベルに対するキーと値の完全一致。たとえば、duration メトリクスでは { status: 'error' }
  • 相関フィールド: entityTypeentityNameparentEntityNamerootEntityNameuserIdorganizationIdresourceIdrunIdsessionIdthreadIdrequestIdexecutionSourceenvironmentserviceNameexperimentIdtags

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 として呼び出せます。

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,
}
},
})