File size: 2,911 Bytes
ea39c0e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 | //! Emits bounded process lifecycle telemetry using identity captured at launch.
//! Reconnects and later process operations must not replace that identity.
use std::sync::Arc;
use codex_sandboxing::SandboxType;
use opentelemetry::trace::SpanContext;
use crate::telemetry::ExecutorRegistration;
/// Log fields captured at launch, never refreshed from a resumed session.
#[derive(Clone, Default)]
pub(crate) struct ProcessTelemetry {
pub(crate) launch_context: Option<SpanContext>,
pub(crate) thread_id: Option<String>,
pub(crate) tool_call_id: Option<String>,
pub(crate) executor_registration: Option<Arc<ExecutorRegistration>>,
}
/// Lifecycle events with outcome fields only when a process has exited.
pub(crate) enum ProcessTelemetryEvent {
Start,
SpawnFailed,
SandboxDenied,
Exit {
exit_code: i32,
termination_requested: bool,
},
}
impl ProcessTelemetry {
pub(crate) fn log(&self, event: ProcessTelemetryEvent, sandbox: SandboxType) {
let (event_name, exit_code, termination_requested, reason) = match event {
ProcessTelemetryEvent::Start => ("codex.exec_server.process_start", None, None, None),
ProcessTelemetryEvent::SpawnFailed => {
("codex.exec_server.process_spawn_failed", None, None, None)
}
ProcessTelemetryEvent::SandboxDenied => (
"codex.exec_server.sandbox_denied",
None,
None,
Some("inferred_denial"),
),
ProcessTelemetryEvent::Exit {
exit_code,
termination_requested,
} => (
"codex.exec_server.process_exit",
Some(exit_code),
Some(termination_requested),
None,
),
};
let trace_id = self
.launch_context
.as_ref()
.map(|span| span.trace_id().to_string());
let span_id = self
.launch_context
.as_ref()
.map(|span| span.span_id().to_string());
tracing::event!(
target: "codex_otel.log_only",
tracing::Level::INFO,
event.name = event_name,
launch.trace_id = trace_id.as_deref(),
launch.span_id = span_id.as_deref(),
conversation.id = self.thread_id.as_deref(),
tool.call_id = self.tool_call_id.as_deref(),
executor.environment_id = self.executor_registration.as_ref().map(|registration| registration.environment_id.as_str()),
executor.registration_id = self.executor_registration.as_ref().map(|registration| registration.executor_registration_id.as_str()),
sandbox.type = ?sandbox,
process.exit_code = exit_code,
process.termination_requested = termination_requested,
reason,
);
}
}
|