Custom metric reference
Use this reference when choosing a measurement or interpreting its result. For the ordered Console procedure, see Create and verify a custom metric. These settings describe Console behavior, not a public write-API schema.
Coverage and retention
A custom metric selects recorded spans. A span contributes to the bin containing its end. Spans arriving more than ten minutes after that bin ends, or lasting more than one hour, are not guaranteed to be counted. New attribute paths have no values on traces recorded before those attributes were introduced.
Retention defaults to 90 days and accepts 1 to 365 days. It includes the current UTC day plus the preceding days needed to reach that total. This is retention of computed data, not a guarantee of equally long raw trace history. Backfill uses only traces the platform still holds.
Each read window is at most 30 days long. Older retained custom data can be read through additional windows. Reducing retention makes older values unreadable without necessarily deleting them immediately. Increasing retention does not recreate expired data. See Time windows and bins for read-boundary alignment.
Choose an aggregation
| Console choice | What it computes | Field required | Result type |
|---|---|---|---|
| Count | Number of matching spans | No | Counter |
| Sum | Sum of a numeric field | Yes | Counter |
| Average | Average of a numeric field | Yes | Gauge |
| Minimum | Smallest numeric value | Yes | Gauge |
| Maximum | Largest numeric value | Yes | Gauge |
| Unique count | Approximate number of distinct field values | Yes | Gauge |
| Percentiles | p50, p90, p95, and p99 of a numeric field | Yes | Percentiles |
Numeric aggregations skip missing or unparseable numeric values. Unique count skips missing values. Custom distribution and ratio aggregations are not supported. Built-in duration distributions are separate metrics.
Filter and field vocabulary
A filter evaluates one recorded span at a time. At least one span path must occur in the filter, aggregation, or dimensions. A definition referencing only session paths is rejected. The UserFn custom-metric context is the canonical explanation of supported syntax and missing-value comparisons.
| Path | Type | Meaning | Allowed as a dimension |
|---|---|---|---|
$.span.operation | String | Operation recorded by the span | Yes |
$.span.status | String | ok, error, or unset | Yes |
$.span.tool_name | String | Tool name on a tool-execution span | Yes |
$.span.tool_key | String | Tool configuration key on a tool-execution span | Yes |
$.span.tool_error_type | String | Failed tool call's error type | Yes |
$.span.error_type | String | Span's error type | Yes |
$.span.duration_ms | Number | Span duration in milliseconds | No |
$.span.model | String | Model requested for the invocation or model call | Yes |
$.span.input_tokens | Number | Input tokens consumed by a model-call span | No |
$.span.output_tokens | Number | Output tokens produced by a model-call span | No |
$.span.time_to_first_token_ms | Number | Time from the start of a streamed model call to its first provider output | No |
$.session.key | String | Session key | No |
$.session.agent_key | String | Agent running the session | Yes |
$.session.parent_key | String | Calling session for a sub-agent session, absent at depth zero | No |
$.session.depth | Number | Zero for a top-level session, increasing with sub-agent nesting | Yes |
$.session.caller_id_hash | String | Keyed hash of the caller, present on invocation spans | No |
$.session.caller_type | String | Caller kind, present on invocation spans | Yes |
Documented operation values include invoke_agent, chat, execute_tool, thinking, output, step_transition, evaluate_run_condition, image_read, and compaction. Model-call tokens and time to first token are measured on chat spans. Time to first token is absent for non-streamed calls and is not whole-invocation duration.
Caller kinds are user, anonymous, api_key, app_client, agent, and service_account. A caller hash identifies a principal, not necessarily a person. Requests sharing an API key can share a caller identity.
Requests rejected before an agent runs
An evaluate_run_condition span records evaluation of an agent's run condition, whether it allows the request, rejects it, or encounters an evaluation error. When the condition rejects the request, session creation stops before an agent invocation begins.
These spans record the agent key but no session key or session depth. Top-level sessions only therefore excludes them. Turning that setting off lets an operation-based metric include run-condition evaluations, not specifically rejected requests.
The current custom-metric vocabulary does not expose the run-condition result or rejection indicator, so it cannot isolate rejected outcomes. An ordinary false result is not automatically an error-status span. Do not label a count of evaluate_run_condition observations as a rejected-request count.
These spans cannot currently be inspected through View traces or the trace span API, which omit the operation. Trace summaries also require an agent invocation. A metric selecting run-condition evaluations can therefore include observations that the inspection workflow cannot show. This is a current trace-read limitation, not a behavior to depend on.
Top-level sessions only
The creation wizard enables Top-level sessions only by default. It appends get('$.session.depth') == 0. This excludes sub-agent sessions and missing depth values. It does not select only a root span: model and tool calls within a top-level session still qualify if the expression matches them.
Turn it off before creation when you need sub-agent session activity. Keep the same depth choice when comparing custom metrics. Built-in metrics do not apply this wizard setting.
Dimensions
A dimension has a user-chosen name and a field it reads. For example, a dimension named agent_key can read $.session.agent_key. Its chosen name appears in the public metric descriptor and is the name used when reading it. Built-in metrics have the separate fixed name agent_keys.
- At most four dimensions are allowed, with distinct names.
- Only paths marked Yes above can be dimensions. Session keys, caller hashes, token counts, and durations cannot be dimensions.
- Missing values are represented by the empty string. Values are truncated to 256 characters.
- A read merges unfiltered values into one series. Dimensions enable filtering, not a request for native multi-series group-by.
- An all-agent metric needs a dimension reading
$.session.agent_keyif the dashboard agent selector is to narrow it. Without one, it remains account-wide.
Lifecycle
| Console status | Meaning |
|---|---|
| Backfilling | Historical computation is in progress. Recent data is computed while older bins may be incomplete. |
| Active | New data is being computed. Not every chosen window necessarily contains matching observations. |
| Disabled | No new data is computed. Previously computed values remain readable within retention. |
| Error | Computation failed. Inspect the error detail beside the status. |
Creation and re-enabling schedule backfill over traces still available. There is no guaranteed time-to-first-chart stated here.
Data since reports the earliest retained time bin when that metadata is available. No data yet can also appear when the timestamp is unavailable. Use the series and status together instead of treating the label alone as proof of zero data.
Measurement recipes
Use these settings in the creation wizard. Agent scope and the depth choice must be consistent between measurements you intend to compare.
| Measurement | Filter expression | Aggregation and field |
|---|---|---|
| Tool calls | get('$.span.operation') == 'execute_tool' | Count |
| Tool calls with an error type | get('$.span.operation') == 'execute_tool' && get('$.span.tool_error_type', '') != '' | Count |
| Model input tokens | get('$.span.operation') == 'chat' | Sum, $.span.input_tokens |
| Model output tokens | get('$.span.operation') == 'chat' | Sum, $.span.output_tokens |
| Sessions containing model calls | get('$.span.operation') == 'chat' | Unique count, $.session.key |
| Agent invocation duration | get('$.span.operation') == 'invoke_agent' | Percentiles, $.span.duration_ms |
To calculate a tool error rate externally, read aligned error and call counts and divide errors by calls. A zero denominator makes the rate undefined. This rate measures reported tool errors, not whether a user's request was ultimately resolved.
To calculate approximate input tokens per session containing model calls, read the input-token sum and approximate unique-session count with the same chat filter, scope, and whole-window boundaries, then divide externally. This is not a per-session distribution. Do not sum distinct counts from smaller bins. Missing token attributes do not contribute to the sum, so verify token coverage before interpreting the result.
Filter limits
Only the listed paths are available. Tool arguments, tool results, arbitrary session metadata, evaluation verdicts, window functions, and cross-span calculations are not available in the metric-filter context. Use the restricted UserFn syntax, not the full function catalog.
What a metric measures is immutable. See Plan before you create before changing scope, filter, aggregation, or dimensions.