mirror of
https://github.com/openai/codex.git
synced 2026-11-12 21:20:34 +00:00
core: emit responses api call analytics
This commit is contained in:
@@ -10,7 +10,6 @@ use crate::facts::AppMentionedInput;
|
||||
use crate::facts::AppUsedInput;
|
||||
use crate::facts::CodexResponsesApiCallFact;
|
||||
use crate::facts::CodexResponsesApiCallInput;
|
||||
use crate::facts::CodexResponsesApiItemPhase;
|
||||
use crate::facts::CustomAnalyticsFact;
|
||||
use crate::facts::HookRunFact;
|
||||
use crate::facts::HookRunInput;
|
||||
@@ -23,7 +22,6 @@ use crate::facts::TrackEventsContext;
|
||||
use crate::facts::TurnResolvedConfigFact;
|
||||
use crate::facts::TurnTokenUsageFact;
|
||||
use crate::reducer::AnalyticsReducer;
|
||||
use crate::response_items::response_items_metadata;
|
||||
use codex_app_server_protocol::ClientRequest;
|
||||
use codex_app_server_protocol::ClientResponse;
|
||||
use codex_app_server_protocol::InitializeParams;
|
||||
@@ -42,6 +40,7 @@ use tokio::sync::mpsc;
|
||||
const ANALYTICS_EVENTS_QUEUE_SIZE: usize = 256;
|
||||
const ANALYTICS_EVENTS_TIMEOUT: Duration = Duration::from_secs(10);
|
||||
const ANALYTICS_EVENT_DEDUPE_MAX_KEYS: usize = 4096;
|
||||
const RESPONSES_API_ERROR_MAX_BYTES: usize = 1024;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct AnalyticsEventsQueue {
|
||||
@@ -223,25 +222,20 @@ impl AnalyticsEventsClient {
|
||||
tracking: TrackEventsContext,
|
||||
input: CodexResponsesApiCallInput,
|
||||
) {
|
||||
let mut items =
|
||||
response_items_metadata(CodexResponsesApiItemPhase::Input, &input.input_items);
|
||||
items.extend(response_items_metadata(
|
||||
CodexResponsesApiItemPhase::Output,
|
||||
&input.output_items,
|
||||
));
|
||||
let token_usage = input.token_usage;
|
||||
let error = input.error.map(truncate_responses_api_error);
|
||||
let event = CodexResponsesApiCallFact {
|
||||
thread_id: tracking.thread_id,
|
||||
turn_id: tracking.turn_id,
|
||||
responses_id: input.responses_id,
|
||||
turn_responses_call_index: input.turn_responses_call_index,
|
||||
status: input.status,
|
||||
error: input.error,
|
||||
error,
|
||||
started_at: input.started_at,
|
||||
completed_at: input.completed_at,
|
||||
duration_ms: input.duration_ms,
|
||||
input_item_count: input.input_items.len(),
|
||||
output_item_count: input.output_items.len(),
|
||||
input_item_count: input.input_item_count,
|
||||
output_item_count: input.output_item_count,
|
||||
input_tokens: token_usage.as_ref().map(|usage| usage.input_tokens),
|
||||
cached_input_tokens: token_usage.as_ref().map(|usage| usage.cached_input_tokens),
|
||||
output_tokens: token_usage.as_ref().map(|usage| usage.output_tokens),
|
||||
@@ -249,7 +243,7 @@ impl AnalyticsEventsClient {
|
||||
.as_ref()
|
||||
.map(|usage| usage.reasoning_output_tokens),
|
||||
total_tokens: token_usage.as_ref().map(|usage| usage.total_tokens),
|
||||
items,
|
||||
items: input.items,
|
||||
};
|
||||
|
||||
self.record_fact(AnalyticsFact::Custom(
|
||||
@@ -339,6 +333,18 @@ impl AnalyticsEventsClient {
|
||||
}
|
||||
}
|
||||
|
||||
fn truncate_responses_api_error(mut error: String) -> String {
|
||||
if error.len() <= RESPONSES_API_ERROR_MAX_BYTES {
|
||||
return error;
|
||||
}
|
||||
let mut truncate_at = RESPONSES_API_ERROR_MAX_BYTES;
|
||||
while !error.is_char_boundary(truncate_at) {
|
||||
truncate_at -= 1;
|
||||
}
|
||||
error.truncate(truncate_at);
|
||||
error
|
||||
}
|
||||
|
||||
async fn send_track_events(
|
||||
auth_manager: &Arc<AuthManager>,
|
||||
base_url: &str,
|
||||
|
||||
@@ -14,7 +14,6 @@ use codex_protocol::config_types::Personality;
|
||||
use codex_protocol::config_types::ReasoningSummary;
|
||||
use codex_protocol::config_types::ServiceTier;
|
||||
use codex_protocol::models::MessagePhase;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use codex_protocol::openai_models::ReasoningEffort;
|
||||
use codex_protocol::protocol::AskForApproval;
|
||||
use codex_protocol::protocol::HookEventName;
|
||||
@@ -322,8 +321,9 @@ pub struct CodexResponsesApiCallInput {
|
||||
pub started_at: u64,
|
||||
pub completed_at: Option<u64>,
|
||||
pub duration_ms: Option<u64>,
|
||||
pub input_items: Vec<ResponseItem>,
|
||||
pub output_items: Vec<ResponseItem>,
|
||||
pub input_item_count: usize,
|
||||
pub output_item_count: usize,
|
||||
pub items: Vec<CodexResponsesApiItemMetadata>,
|
||||
pub token_usage: Option<TokenUsage>,
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ mod facts;
|
||||
mod reducer;
|
||||
mod response_items;
|
||||
|
||||
use codex_protocol::models::ResponseItem;
|
||||
use serde::Serialize;
|
||||
use std::time::SystemTime;
|
||||
use std::time::UNIX_EPOCH;
|
||||
@@ -22,6 +23,7 @@ pub use facts::AppInvocation;
|
||||
pub use facts::CodexCompactionEvent;
|
||||
pub use facts::CodexResponsesApiCallInput;
|
||||
pub use facts::CodexResponsesApiCallStatus;
|
||||
pub use facts::CodexResponsesApiItemMetadata;
|
||||
pub use facts::CodexTurnSteerEvent;
|
||||
pub use facts::CompactionImplementation;
|
||||
pub use facts::CompactionPhase;
|
||||
@@ -54,6 +56,23 @@ pub fn now_unix_seconds() -> u64 {
|
||||
.as_secs()
|
||||
}
|
||||
|
||||
pub fn responses_api_input_items_metadata(
|
||||
items: &[ResponseItem],
|
||||
) -> Vec<CodexResponsesApiItemMetadata> {
|
||||
response_items::response_items_metadata(facts::CodexResponsesApiItemPhase::Input, items)
|
||||
}
|
||||
|
||||
pub fn responses_api_output_item_metadata(
|
||||
item_index: usize,
|
||||
item: &ResponseItem,
|
||||
) -> CodexResponsesApiItemMetadata {
|
||||
response_items::response_item_metadata(
|
||||
facts::CodexResponsesApiItemPhase::Output,
|
||||
item_index,
|
||||
item,
|
||||
)
|
||||
}
|
||||
|
||||
pub(crate) fn serialized_string<T: Serialize>(value: &T) -> Option<String> {
|
||||
match serde_json::to_value(value).ok()? {
|
||||
serde_json::Value::String(value) => Some(value),
|
||||
|
||||
@@ -13,7 +13,7 @@ use codex_protocol::models::ReasoningItemContent;
|
||||
use codex_protocol::models::ReasoningItemReasoningSummary;
|
||||
use codex_protocol::models::ResponseItem;
|
||||
|
||||
pub fn response_items_metadata(
|
||||
pub(crate) fn response_items_metadata(
|
||||
phase: CodexResponsesApiItemPhase,
|
||||
items: &[ResponseItem],
|
||||
) -> Vec<CodexResponsesApiItemMetadata> {
|
||||
@@ -24,7 +24,7 @@ pub fn response_items_metadata(
|
||||
.collect()
|
||||
}
|
||||
|
||||
fn response_item_metadata(
|
||||
pub(crate) fn response_item_metadata(
|
||||
item_phase: CodexResponsesApiItemPhase,
|
||||
item_index: usize,
|
||||
item: &ResponseItem,
|
||||
|
||||
Reference in New Issue
Block a user