[codex][otel] propagate user email in otel events (#5223)

include user email into otel events for proper user-level attribution in
case of workspace setup
This commit is contained in:
Anton Panasenko
2025-10-15 17:53:33 -07:00
committed by GitHub
parent 5fa7844ad7
commit c146585cdb
9 changed files with 29 additions and 2 deletions

View File

@@ -135,6 +135,10 @@ impl CodexAuth {
self.get_current_token_data().and_then(|t| t.account_id)
}
pub fn get_account_email(&self) -> Option<String> {
self.get_current_token_data().and_then(|t| t.id_token.email)
}
pub(crate) fn get_plan_type(&self) -> Option<PlanType> {
self.get_current_token_data()
.and_then(|t| t.id_token.chatgpt_plan_type)

View File

@@ -1030,6 +1030,7 @@ mod tests {
"test",
"test",
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -445,6 +445,7 @@ impl Session {
config.model.as_str(),
config.model_family.slug.as_str(),
auth_manager.auth().and_then(|a| a.get_account_id()),
auth_manager.auth().and_then(|a| a.get_account_email()),
auth_manager.auth().map(|a| a.mode),
config.otel.log_user_prompt,
terminal::user_agent(),
@@ -2744,6 +2745,7 @@ mod tests {
config.model.as_str(),
config.model_family.slug.as_str(),
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -79,6 +79,7 @@ async fn run_request(input: Vec<ResponseItem>) -> Value {
config.model.as_str(),
config.model_family.slug.as_str(),
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -78,6 +78,7 @@ async fn run_stream_with_bytes(sse_body: &[u8]) -> Vec<ResponseEvent> {
config.model.as_str(),
config.model_family.slug.as_str(),
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -63,6 +63,7 @@ async fn responses_stream_includes_task_type_header() {
config.model.as_str(),
config.model_family.slug.as_str(),
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -657,6 +657,7 @@ async fn azure_responses_request_includes_store_and_reasoning_ids() {
config.model.as_str(),
config.model_family.slug.as_str(),
None,
Some("test@test.com".to_string()),
Some(AuthMode::ChatGPT),
false,
"test".to_string(),

View File

@@ -33,6 +33,7 @@ pub struct OtelEventMetadata {
conversation_id: ConversationId,
auth_mode: Option<String>,
account_id: Option<String>,
account_email: Option<String>,
model: String,
slug: String,
log_user_prompts: bool,
@@ -46,11 +47,13 @@ pub struct OtelEventManager {
}
impl OtelEventManager {
#[allow(clippy::too_many_arguments)]
pub fn new(
conversation_id: ConversationId,
model: &str,
slug: &str,
account_id: Option<String>,
account_email: Option<String>,
auth_mode: Option<AuthMode>,
log_user_prompts: bool,
terminal_type: String,
@@ -60,6 +63,7 @@ impl OtelEventManager {
conversation_id,
auth_mode: auth_mode.map(|m| m.to_string()),
account_id,
account_email,
model: model.to_owned(),
slug: slug.to_owned(),
log_user_prompts,
@@ -98,6 +102,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -136,6 +141,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -205,6 +211,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -226,6 +233,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -240,6 +248,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -262,6 +271,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -286,6 +296,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -320,6 +331,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -343,6 +355,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -383,7 +396,8 @@ impl OtelEventManager {
conversation.id = %self.metadata.conversation_id,
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.account_id= self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -408,6 +422,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,
@@ -437,6 +452,7 @@ impl OtelEventManager {
app.version = %self.metadata.app_version,
auth_mode = self.metadata.auth_mode,
user.account_id = self.metadata.account_id,
user.email = self.metadata.account_email,
terminal.type = %self.metadata.terminal_type,
model = %self.metadata.model,
slug = %self.metadata.slug,

View File

@@ -509,7 +509,7 @@ crate—the events listed below—is forwarded to the exporter.
Every event shares a common set of metadata fields: `event.timestamp`,
`conversation.id`, `app.version`, `auth_mode` (when available),
`user.account_id` (when available), `terminal.type`, `model`, and `slug`.
`user.account_id` (when available), `user.email` (when available), `terminal.type`, `model`, and `slug`.
With OTEL enabled Codex emits the following event types (in addition to the
metadata above):