Metric queries
Metric queries read raw and aggregated metric data from the observability storage domain. For exporter and storage setup, see the Metrics overview. For automatic metric names and labels, see the Automatic metrics reference.
AccessAccess的直接链接
Observability storeObservability store的直接链接
Use the storage domain for in-process queries:
const observability = await mastra.getStorage()?.getStore('observability')
if (!observability) {
throw new Error('Observability storage is not configured')
}
const result = await observability.getMetricAggregate({
name: ['mastra_agent_duration_ms'],
aggregation: 'avg',
filters: {
timestamp: { start: new Date(Date.now() - 60 * 60 * 1000) },
},
})
getStore('observability') returns undefined when the storage configuration doesn't provide the observability domain.
Client SDKClient SDK的直接链接
@mastra/client-js exposes the analytics and metric discovery methods on MastraClient:
import { MastraClient } from '@mastra/client-js'
const client = new MastraClient({
baseUrl: 'http://localhost:4111',
})
const result = await client.getMetricAggregate({
name: ['mastra_agent_duration_ms'],
aggregation: 'avg',
})
The client doesn't expose a raw listMetrics() method. Use the observability store or the GET /api/observability/metrics route to list raw metric records.
Shared valuesShared values的直接链接
AggregationsAggregations的直接链接
The aggregate, breakdown, and time-series methods accept these aggregation values:
| Value | Result |
|---|---|
sum | Sum of metric values |
avg | Average metric value |
min | Minimum metric value |
max | Maximum metric value |
count | Number of matching metric records |
count_distinct | Approximate or exact number of distinct values in distinctColumn, depending on the storage backend |
last | Most recent matching metric value |
When aggregation is count_distinct, distinctColumn is required. Supported columns are:
entityType
entityName
parentEntityType
parentEntityName
rootEntityType
rootEntityName
name
provider
model
environment
executionSource
serviceName
threadId
resourceId
IntervalsIntervals的直接链接
Time-series and percentile queries accept 1m, 5m, 15m, 1h, or 1d.
FiltersFilters的直接链接
All metric operations accept the same optional filters object. Raw list requests pass these fields as query parameters. Analytics methods pass them in the JSON request body.
| Field | Type | Description |
|---|---|---|
timestamp | { start?: Date; end?: Date; startExclusive?: boolean; endExclusive?: boolean } | Timestamp range. Boundaries are inclusive unless their corresponding exclusive flag is true. HTTP requests use ISO date strings. |
traceId | string | Exact trace ID |
traceIds | string[] | One to 1,000 trace IDs |
spanId | string | Exact span ID |
entityType | EntityType | Entity type |
entityName | string | Entity name |
entityVersionId | string | Entity version ID |
parentEntityType | EntityType | Parent entity type |
parentEntityName | string | Parent entity name |
parentEntityVersionId | string | Parent entity version ID |
rootEntityType | EntityType | Root entity type |
rootEntityName | string | Root entity name |
rootEntityVersionId | string | Root entity version ID |
userId | string | User ID |
organizationId | string | Organization ID |
experimentId | string | Experiment or evaluation run ID |
experimentIds | string[] | One to 1,000 experiment IDs |
serviceName | string | Service name |
environment | string | Environment name |
resourceId | string | Resource ID |
runId | string | Run ID |
sessionId | string | Session ID |
threadId | string | Thread ID |
requestId | string | Request ID |
executionSource | string | Execution source |
tags | string[] | Records must contain all specified tags |
name | string[] | One or more metric names |
provider | string | Model provider |
model | string | Model ID |
costUnit | string | Cost unit |
labels | Record<string, string> | Exact matches for all specified metric label key-value pairs |
source | string | Deprecated. Use executionSource. |
Analytics methodsAnalytics methods的直接链接
getMetricAggregate(args)getmetricaggregateargs的直接链接
Returns one value across all matching records. The observability store and MastraClient expose this method.
ArgumentsArguments的直接链接
| Field | Type | Required | Description |
|---|---|---|---|
name | string[] | Yes | One or more metric names |
aggregation | AggregationType | Yes | Aggregation to apply |
distinctColumn | MetricDistinctColumn | For count_distinct | Column whose distinct values are counted |
filters | MetricsFilter | No | Shared metric filters |
comparePeriod | 'previous_period' | 'previous_day' | 'previous_week' | No | Adds comparison-period values. previous_period uses the duration of filters.timestamp. |
ReturnsReturns的直接链接
{
value: number | null
previousValue?: number | null
changePercent?: number | null
estimatedCost?: number | null
costUnit?: string | null
previousEstimatedCost?: number | null
costChangePercent?: number | null
}
costUnit is null when the matching records don't have one shared unit. Cost fields are optional and may be null when the records don't include cost context.
const result = await observability.getMetricAggregate({
name: ['mastra_model_total_input_tokens', 'mastra_model_total_output_tokens'],
aggregation: 'sum',
filters: {
timestamp: {
start: new Date('2026-08-24T00:00:00Z'),
end: new Date('2026-08-25T00:00:00Z'),
},
},
comparePeriod: 'previous_period',
})
HTTP: POST /api/observability/metrics/aggregate
getMetricBreakdown(args)getmetricbreakdownargs的直接链接
Groups matching records by one or more dimensions and aggregates each group. The observability store and MastraClient expose this method.
ArgumentsArguments的直接链接
| Field | Type | Required | Description |
|---|---|---|---|
name | string[] | Yes | One or more metric names |
groupBy | string[] | Yes | One or more fields to group by |
aggregation | AggregationType | Yes | Aggregation for each group |
distinctColumn | MetricDistinctColumn | For count_distinct | Column whose distinct values are counted |
filters | MetricsFilter | No | Shared metric filters |
limit | number | No | Positive integer up to 1,000. Required for high-cardinality groupings. |
orderDirection | 'ASC' | 'DESC' | No | Sort direction for the aggregated value. Storage implementations default to DESC. |
ReturnsReturns的直接链接
{
groups: Array<{
dimensions: Record<string, string | null>
value: number
estimatedCost?: number | null
costUnit?: string | null
}>
}
const result = await client.getMetricBreakdown({
name: ['mastra_model_total_input_tokens'],
groupBy: ['entityName'],
aggregation: 'sum',
limit: 10,
orderDirection: 'DESC',
})
HTTP: POST /api/observability/metrics/breakdown
getMetricTimeSeries(args)getmetrictimeseriesargs的直接链接
Buckets matching values by time interval, with optional grouping. The observability store and MastraClient expose this method.
ArgumentsArguments的直接链接
| Field | Type | Required | Description |
|---|---|---|---|
name | string[] | Yes | One or more metric names |
interval | AggregationInterval | Yes | Time bucket interval |
aggregation | AggregationType | Yes | Aggregation for each bucket |
distinctColumn | MetricDistinctColumn | For count_distinct | Column whose distinct values are counted |
filters | MetricsFilter | No | Shared metric filters |
groupBy | string[] | No | Fields used to split the result into series |
ReturnsReturns的直接链接
{
series: Array<{
name: string
costUnit?: string | null
points: Array<{
timestamp: Date
value: number
estimatedCost?: number | null
}>
}>
}
const result = await client.getMetricTimeSeries({
name: ['mastra_model_total_input_tokens'],
interval: '1h',
aggregation: 'sum',
filters: {
timestamp: { start: new Date(Date.now() - 24 * 60 * 60 * 1000) },
},
})
HTTP: POST /api/observability/metrics/timeseries
getMetricPercentiles(args)getmetricpercentilesargs的直接链接
Calculates percentile values in time buckets. The observability store and MastraClient expose this method.
ArgumentsArguments的直接链接
| Field | Type | Required | Description |
|---|---|---|---|
name | string | Yes | One metric name |
percentiles | number[] | Yes | One or more values from 0 through 1 |
interval | AggregationInterval | Yes | Time bucket interval |
filters | MetricsFilter | No | Shared metric filters |
ReturnsReturns的直接链接
{
series: Array<{
percentile: number
points: Array<{
timestamp: Date
value: number
}>
}>
}
const result = await client.getMetricPercentiles({
name: 'mastra_agent_duration_ms',
percentiles: [0.5, 0.95, 0.99],
interval: '1h',
})
HTTP: POST /api/observability/metrics/percentiles
Raw metric recordsRaw metric records的直接链接
listMetrics(args)listmetricsargs的直接链接
Returns stored metric observations without aggregating them. This method is available on the observability store. The HTTP route accepts the same fields as query parameters.
ArgumentsArguments的直接链接
Page mode is the default:
{
mode?: 'page'
filters?: MetricsFilter
pagination?: {
page?: number // Default: 0
perPage?: number // Default: 10; maximum: 100
}
orderBy?: {
field?: 'timestamp' // Default: 'timestamp'
direction?: 'ASC' | 'DESC' // Default: 'DESC'
}
}
Delta mode supports incremental polling:
{
mode: 'delta'
filters?: MetricsFilter
after?: string
limit?: number // Default: 10; maximum: 100
}
pagination and orderBy aren't allowed in delta mode. after and limit aren't allowed in page mode. A backend that doesn't support delta polling returns an unsupported-operation error.
ReturnsReturns的直接链接
{
metrics: MetricRecord[]
pagination?: {
total: number
page: number
perPage: number | false
hasMore: boolean
}
delta?: {
limit: number
hasMore: boolean
}
deltaCursor?: string
}
A MetricRecord has this shape:
{
metricId?: string | null
timestamp: Date
name: string
value: number
traceId?: string | null
spanId?: string | null
entityType?: EntityType | null
entityId?: string | null
entityName?: string | null
parentEntityType?: EntityType | null
parentEntityId?: string | null
parentEntityName?: string | null
rootEntityType?: EntityType | null
rootEntityId?: string | null
rootEntityName?: string | null
userId?: string | null
organizationId?: string | null
resourceId?: string | null
runId?: string | null
sessionId?: string | null
threadId?: string | null
requestId?: string | null
environment?: string | null
serviceName?: string | null
scope?: Record<string, unknown> | null
entityVersionId?: string | null
parentEntityVersionId?: string | null
rootEntityVersionId?: string | null
experimentId?: string | null
executionSource?: string | null
tags?: string[] | null
source?: string | null // Deprecated
provider?: string | null
model?: string | null
estimatedCost?: number | null
costUnit?: string | null
costMetadata?: Record<string, unknown> | null
labels: Record<string, string>
metadata?: Record<string, unknown> | null
}
HTTP: GET /api/observability/metrics
Metric discoveryMetric discovery的直接链接
The observability store and MastraClient expose the metric discovery methods. HTTP requests pass arguments as query parameters.
| Method | Arguments | Returns | HTTP route |
|---|---|---|---|
getMetricNames(args?) | { prefix?: string; limit?: number } | { names: string[] } | GET /api/observability/discovery/metric-names |
getMetricLabelKeys(args) | { metricName: string } | { keys: string[] } | GET /api/observability/discovery/metric-label-keys |
getMetricLabelValues(args) | { metricName: string; labelKey: string; prefix?: string; limit?: number } | { values: string[] } | GET /api/observability/discovery/metric-label-values |
limit must be a positive integer when provided.
const { names } = await client.getMetricNames({ prefix: 'mastra_model_' })
const { keys } = await client.getMetricLabelKeys({ metricName: names[0] })
const { values } = await client.getMetricLabelValues({
metricName: names[0],
labelKey: keys[0],
limit: 20,
})
The observability discovery API also exposes shared dimensions used by traces, logs, and metrics:
| Store or client method | Arguments | HTTP route |
|---|---|---|
getEntityTypes() | None in MastraClient; {} in the store | GET /api/observability/discovery/entity-types |
getEntityNames(args?) | { entityType?: EntityType } | GET /api/observability/discovery/entity-names |
getServiceNames() | None in MastraClient; {} in the store | GET /api/observability/discovery/service-names |
getEnvironments() | None in MastraClient; {} in the store | GET /api/observability/discovery/environments |
getTags(args?) | { entityType?: EntityType } | GET /api/observability/discovery/tags |
HTTP routesHTTP routes的直接链接
| Method | Route | Input |
|---|---|---|
GET | /api/observability/metrics | Query parameters |
POST | /api/observability/metrics/aggregate | JSON body |
POST | /api/observability/metrics/breakdown | JSON body |
POST | /api/observability/metrics/timeseries | JSON body |
POST | /api/observability/metrics/percentiles | JSON body |
GET | /api/observability/discovery/metric-names | Query parameters |
GET | /api/observability/discovery/metric-label-keys | Query parameters |
GET | /api/observability/discovery/metric-label-values | Query parameters |
GET | /api/observability/discovery/entity-types | None |
GET | /api/observability/discovery/entity-names | Query parameters |
GET | /api/observability/discovery/service-names | None |
GET | /api/observability/discovery/environments | None |
GET | /api/observability/discovery/tags | Query parameters |
All routes require a configured observability domain. The aggregate, breakdown, time-series, and percentile routes require the observability:read permission when runtime authorization is enabled.
Unsupported backendsUnsupported backends的直接链接
The base observability storage implementation throws *_NOT_IMPLEMENTED errors for raw listing, analytics, and discovery methods. A configured observability domain can therefore exist while its backend doesn't implement metric queries.
DuckDB, ClickHouse, Postgres v-next observability storage, and in-memory observability storage implement metric queries. Google Cloud Spanner implements them only when disableMetrics is false. Metrics are disabled by default. Other storage adapters may support tracing without supporting metrics.
CLICLI的直接链接
The mastra api metric commands cover aggregate, breakdown, time-series, percentile, metric-name, label-key, and label-value queries. See the mastra api metric CLI reference for commands, targeting, authentication, and schema inspection.