mirror of
https://github.com/openai/codex.git
synced 2026-11-13 14:46:14 +00:00
Export turn cost as an OTEL metric (#40488)
## What changed - Emit `codex.turn.cost_microusd` as a counter with turn, conversation, interruption, speed, and reasoning-effort attributes. Convert the estimated USD string to microdollars, rounding to the nearest microdollar and skipping values that cannot be represented safely. - Start turn-cost collection when an OTLP metrics exporter is configured, even when the OTEL log exporter is disabled. ## Testing - Verify cost conversion, rounding, and metric attributes with an in-memory metrics snapshot. - Verify that a metrics-only OTLP configuration starts the turn-cost worker. GitOrigin-RevId: e60587079f097f10cc1b6d1bf889d3f7a0dc3d5f
This commit is contained in:
1 parent
fb9311db5c
commit
2497518490
7 files changed
+151
-2
No files matched your search
@@ -155,3 +155,68 @@ fn manager_snapshot_metrics_collects_without_shutdown() -> Result<()> {
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn manager_turn_cost_records_microusd_metric() -> Result<()> {
|
||||
let exporter = InMemoryMetricExporter::default();
|
||||
let config = MetricsConfig::in_memory("test", "codex-cli", env!("CARGO_PKG_VERSION"), exporter)
|
||||
.with_runtime_reader();
|
||||
let metrics = MetricsClient::new(config)?;
|
||||
let thread_id = ThreadId::new();
|
||||
let conversation_id = thread_id.to_string();
|
||||
let manager = SessionTelemetry::new(
|
||||
thread_id,
|
||||
"gpt-5.6",
|
||||
"gpt-5.6",
|
||||
/*account_id*/ None,
|
||||
/*account_email*/ None,
|
||||
Some(TelemetryAuthMode::ApiKey),
|
||||
"test_originator".to_string(),
|
||||
/*log_user_prompts*/ false,
|
||||
"tty".to_string(),
|
||||
SessionSource::Cli,
|
||||
)
|
||||
.with_metrics(metrics);
|
||||
|
||||
manager.record_turn_cost(
|
||||
"turn-123",
|
||||
"0.0001245",
|
||||
/*interrupted*/ false,
|
||||
Some("fast"),
|
||||
Some("high"),
|
||||
);
|
||||
|
||||
let snapshot = manager.snapshot_metrics()?;
|
||||
let metric = find_metric(&snapshot, "codex.turn.cost_microusd")
|
||||
.expect("turn-cost microdollar metric missing");
|
||||
let point = match metric.data() {
|
||||
AggregatedMetrics::U64(MetricData::Sum(sum)) => {
|
||||
sum.data_points().next().expect("turn-cost data point")
|
||||
}
|
||||
_ => panic!("unexpected turn-cost metric data type"),
|
||||
};
|
||||
assert_eq!(point.value(), 125);
|
||||
assert_eq!(
|
||||
attributes_to_map(point.attributes()),
|
||||
BTreeMap::from([
|
||||
(
|
||||
"app.version".to_string(),
|
||||
env!("CARGO_PKG_VERSION").to_string(),
|
||||
),
|
||||
(
|
||||
"auth_mode".to_string(),
|
||||
TelemetryAuthMode::ApiKey.to_string(),
|
||||
),
|
||||
("conversation.id".to_string(), conversation_id),
|
||||
("model".to_string(), "gpt-5.6".to_string()),
|
||||
("originator".to_string(), "test_originator".to_string()),
|
||||
("reasoning_effort".to_string(), "high".to_string()),
|
||||
("session_source".to_string(), "cli".to_string()),
|
||||
("speed".to_string(), "fast".to_string()),
|
||||
("turn.id".to_string(), "turn-123".to_string()),
|
||||
("turn.interrupted".to_string(), "false".to_string()),
|
||||
])
|
||||
);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
Reference in new issue
Block a user