Add goal lifecycle metrics (#20799)

## Why

Adding goal metrics makes it possible to track how often goals are
created, completed, and stopped by budget limits, plus the final token
and wall-clock usage for terminal outcomes.

## What Changed

- Added OpenTelemetry metric constants for goal lifecycle tracking:
- `codex.goal.created`: increments each time a new persisted goal is
created or an existing goal is replaced with a new objective.
- `codex.goal.completed`: increments when a goal transitions to
`complete`.
- `codex.goal.budget_limited`: increments when a goal transitions to
`budget_limited` because its token budget has been reached.
- `codex.goal.token_count`: records the final persisted token count when
a goal transitions to `complete` or `budget_limited`.
- `codex.goal.duration_s`: records the final persisted elapsed
wall-clock time, in seconds, when a goal transitions to `complete` or
`budget_limited`.
- Emitted creation metrics when a goal is created or replaced.
- Emitted terminal outcome counters and final usage histograms when a
goal transitions to `complete` or `budget_limited`, avoiding
double-counting later in-flight accounting for already budget-limited
goals.
- Added focused `codex-core` tests for create/complete metrics and
one-time budget-limit metrics.
This commit is contained in:
Eric Traut
2026-05-05 09:21:54 -07:00
committed by GitHub
Unverified
parent 69283aa1c0
commit 91b7350187
7 changed files with 201 additions and 55 deletions
+3 -2
View File
@@ -1,6 +1,7 @@
use crate::agent::AgentStatus;
use crate::config::ConstraintResult;
use crate::file_watcher::WatchRegistration;
use crate::goals::ExternalGoalSet;
use crate::goals::GoalRuntimeEvent;
use crate::session::Codex;
use crate::session::SessionSettingsUpdate;
@@ -160,11 +161,11 @@ impl CodexThread {
}
}
pub async fn apply_external_goal_set(&self, status: codex_state::ThreadGoalStatus) {
pub async fn apply_external_goal_set(&self, external_set: ExternalGoalSet) {
if let Err(err) = self
.codex
.session
.goal_runtime_apply(GoalRuntimeEvent::ExternalSet { status })
.goal_runtime_apply(GoalRuntimeEvent::ExternalSet { external_set })
.await
{
tracing::warn!("failed to apply external goal status runtime effects: {err}");