Commit Graph

59 Commits

  • fix(otel): make HTTP trace export survive app-server runtimes (#14300)
    ## Summary
    
    This PR fixes OTLP HTTP trace export in runtimes where the previous
    exporter setup was unreliable, especially around app-server usage. It
    also removes the old `codex_otel::otel_provider` compatibility shim and
    switches remaining call sites over to the crate-root
    `codex_otel::OtelProvider` export.
    
    ## What changed
    
    - Use a runtime-safe OTLP HTTP trace exporter path for Tokio runtimes.
    - Add an async HTTP client path for trace export when we are already
    inside a multi-thread Tokio runtime.
    - Make provider shutdown flush traces before tearing down the tracer
    provider.
    - Add loopback coverage that verifies traces are actually sent to
    `/v1/traces`:
      - outside Tokio
      - inside a multi-thread Tokio runtime
      - inside a current-thread Tokio runtime
    - Remove the `codex_otel::otel_provider` shim and update remaining
    imports.
    
    ## Why
    
    I hit cases where spans were being created correctly but never made it
    to the collector. The issue turned out to be in exporter/runtime
    behavior rather than the span plumbing itself. This PR narrows that gap
    and gives us regression coverage for the actual export path.
  • feat(otel): Centralize OTEL metric names and shared tag builders (#14117)
    This cleans up a bunch of metric plumbing that had started to drift.
    
    The main change is making `codex-otel` the canonical home for shared
    metric definitions and metric tag helpers. I moved the `turn/thread`
    metric names that were still duplicated into the OTEL metric registry,
    added a shared `metrics::tags` module for common tag keys and session
    tag construction, and updated `SessionTelemetry` to build its metadata
    tags through that shared path.
    
    On the codex-core side, TTFT/TTFM now use the shared metric-name
    constants instead of local string definitions. I also switched the
    obvious remaining turn/thread metric callsites over to the shared
    constants, and added a small helper so TTFT/TTFM can attach an optional
    sanitized client.name tag from TurnContext.
    
    This should make follow-on telemetry work less ad hoc:
    - one canonical place for metric names
    - one canonical place for common metric tag keys/builders
    - less duplication between `codex-core` and `codex-otel`
  • chore(otel): rename OtelManager to SessionTelemetry (#13808)
    ## Summary
    This is a purely mechanical refactor of `OtelManager` ->
    `SessionTelemetry` to better convey what the struct is doing. No
    behavior change.
    
    ## Why
    
    `OtelManager` ended up sounding much broader than what this type
    actually does. It doesn't manage OTEL globally; it's the session-scoped
    telemetry surface for emitting log/trace events and recording metrics
    with consistent session metadata (`app_version`, `model`, `slug`,
    `originator`, etc.).
    
    `SessionTelemetry` is a more accurate name, and updating the call sites
    makes that boundary a lot easier to follow.
    
    ## Validation
    
    - `just fmt`
    - `cargo test -p codex-otel`
    - `cargo test -p codex-core`
  • chore(otel): reorganize codex-otel crate (#13800)
    ## Summary
    This is a structural cleanup of `codex-otel` to make the ownership
    boundaries a lot clearer.
    
    For example, previously it was quite confusing that `OtelManager` which
    emits log + trace event telemetry lived under
    `codex-rs/otel/src/traces/`. Also, there were two places that defined
    methods on OtelManager via `impl OtelManager` (`lib.rs` and
    `otel_manager.rs`).
    
    What changed:
    - move the `OtelProvider` implementation into `src/provider.rs`
    - move `OtelManager` and session-scoped event emission into
    `src/events/otel_manager.rs`
    - collapse the shared log/trace event helpers into
    `src/events/shared.rs`
    - pull target classification into `src/targets.rs`
    - move `traceparent_context_from_env()` into `src/trace_context.rs`
    - keep `src/otel_provider.rs` as a compatibility shim for existing
    imports
    - update the `codex-otel` README to reflect the new layout
    
    ## Why
    `lib.rs` and `otel_provider.rs` were doing too many different jobs at
    once: provider setup, export routing, trace-context helpers, and session
    event emission all lived together.
    
    This refactor separates those concerns without trying to change the
    behavior of the crate. The goal is to make future OTEL work easier to
    reason about and easier to review.
    
    ## Notes
    - no intended behavior change
    - `OtelManager` remains the session-scoped event emitter in this PR
    - the `otel_provider` shim keeps downstream churn low while the
    internals move around
    
    ## Validation
    - `just fmt`
    - `cargo test -p codex-otel`
    - `just fix -p codex-otel`
  • feat(otel, core): record turn TTFT and TTFM metrics in codex-core (#13630)
    ### Summary
    This adds turn-level latency metrics for the first model output and the
    first completed agent message.
    - `codex.turn.ttft.duration_ms` starts at turn start and records on the
    first output signal we see from the model. That includes normal
    assistant text, reasoning deltas, and non-text outputs like tool-call
    items.
    - `codex.turn.ttfm.duration_ms` also starts at turn start, but it
    records when the first agent message finishes streaming rather than when
    its first delta arrives.
    
    ### Implementation notes
    The timing is tracked in codex-core, not app-server, so the definition
    stays consistent across CLI, TUI, and app-server clients.
    
    I reused the existing turn lifecycle boundary that already drives
    `codex.turn.e2e_duration_ms`, stored the turn start timestamp in turn
    state, and record each metric once per turn.
    
    I also wired the new metric names into the OTEL runtime metrics summary
    so they show up in the same in-memory/debug snapshot path as the
    existing timing metrics.
  • feat(otel): safe tracing (#13626)
    ### Motivation
    Today config.toml has three different OTEL knobs under `[otel]`:
    - `exporter` controls where OTEL logs go
    - `trace_exporter` controls where OTEL traces go
    - `metrics_exporter` controls where metrics go
    
    Those often (pretty much always?) serve different purposes.
    
    For example, for OpenAI internal usage, the **log exporter** is already
    being used for IT/security telemetry, and that use case is intentionally
    content-rich: tool calls, arguments, outputs, MCP payloads, and in some
    cases user content are all useful there. `log_user_prompt` is a good
    example of that distinction. When it’s enabled, we include raw prompt
    text in OTEL logs, which is acceptable for the security use case.
    
    The **trace exporter** is a different story. The goal there is to give
    OpenAI engineers visibility into latency and request behavior when they
    run Codex locally, without sending sensitive prompt or tool data as
    trace event data. In other words, traces should help answer “what was
    slow?” or “where did time go?”, not “what did the user say?” or “what
    did the tool return?”
    
    The complication is that Rust’s `tracing` crate does not make a hard
    distinction between “logs” and “trace events.” It gives us one
    instrumentation API for logs and trace events (via `tracing::event!`),
    and subscribers decide what gets treated as logs, trace events, or both.
    
    Before this change, our OTEL trace layer was effectively attached to the
    general tracing stream, which meant turning on `trace_exporter` could
    pick up content-rich events that were originally written with logging
    (and the `log_exporter`) in mind. That made it too easy for sensitive
    data to end up in exported traces by accident.
    
    ### Concrete example
    In `otel_manager.rs`, this `tracing::event!` call would be exported in
    both logs AND traces (as a trace event).
    ```
        pub fn user_prompt(&self, items: &[UserInput]) {
            let prompt = items
                .iter()
                .flat_map(|item| match item {
                    UserInput::Text { text, .. } => Some(text.as_str()),
                    _ => None,
                })
                .collect::<String>();
    
            let prompt_to_log = if self.metadata.log_user_prompts {
                prompt.as_str()
            } else {
                "[REDACTED]"
            };
    
            tracing::event!(
                tracing::Level::INFO,
                event.name = "codex.user_prompt",
                event.timestamp = %timestamp(),
                // ...
                prompt = %prompt_to_log,
            );
        }
    ```
    
    Instead of `tracing::event!`, we should now be using `log_event!` and
    `trace_event!` instead to more clearly indicate which sink (logs vs.
    traces) that event should be exported to.
    
    ### What changed
    This PR makes the log and trace export distinct instead of treating them
    as two sinks for the same data.
    
    On the provider side, OTEL logs and traces now have separate
    routing/filtering policy. The log exporter keeps receiving the existing
    `codex_otel` events, while trace export is limited to spans and trace
    events.
    
    On the event side, `OtelManager` now emits two flavors of telemetry
    where needed:
    - a log-only event with the current rich payloads
    - a tracing-safe event with summaries only
    
    It also has a convenience `log_and_trace_event!` macro for emitting to
    both logs and traces when it's safe to do so, as well as log- and
    trace-specific fields.
    
    That means prompts, tool args, tool output, account email, MCP metadata,
    and similar content stay in the log lane, while traces get the pieces
    that are actually useful for performance work: durations, counts, sizes,
    status, token counts, tool origin, and normalized error classes.
    
    This preserves current IT/security logging behavior while making it safe
    to turn on trace export for employees.
    
    ### Full list of things removed from trace export
    - raw user prompt text from `codex.user_prompt`
    - raw tool arguments and output from `codex.tool_result`
    - MCP server metadata from `codex.tool_result` (mcp_server,
    mcp_server_origin)
    - account identity fields like `user.email` and `user.account_id` from
    trace-safe OTEL events
    - `host.name` from trace resources
    - generic `codex.tool_decision` events from traces
    - generic `codex.sse_event` events from traces
    - the full ToolCall debug payload from the `handle_tool_call` span
    
    What traces now keep instead is mostly:
    - spans
    - trace-safe OTEL events
    - counts, lengths, durations, status, token counts, and tool origin
    summaries
  • feat(core): persist trace_id for turns in RolloutItem::TurnContext (#13602)
    This PR adds a durable trace linkage for each turn by storing the active
    trace ID on the rollout TurnContext record stored in session rollout
    files.
    
    Before this change, we propagated trace context at runtime but didn’t
    persist a stable per-turn trace key in rollout history. That made
    after-the-fact debugging harder (for example, mapping a historical turn
    to the corresponding trace in datadog). This sets us up for much easier
    debugging in the future.
    
    ### What changed
    - Added an optional `trace_id` to TurnContextItem (rollout schema).
    - Added a small OTEL helper to read the current span trace ID.
    - Captured `trace_id` when creating `TurnContext` and included it in
    `to_turn_context_item()`.
    - Updated tests and fixtures that construct TurnContextItem so
    older/no-trace cases still work.
    
    ### Why this approach
    TurnContext is already the canonical durable per-turn metadata in
    rollout. This keeps ownership clean: trace linkage lives with other
    persisted turn metadata.
  • image-gen-core (#13290)
    Core tool-calling for image-gen, handles requesting and receiving logic
    for images using response API
  • feat(app-server): propagate app-server trace context into core (#13368)
    ### Summary
    Propagate trace context originating at app-server RPC method handlers ->
    codex core submission loop (so this includes spans such as `run_turn`!).
    This implements PR 2 of the app-server tracing rollout.
    
    This also removes the old lower-level env-based reparenting in core so
    explicit request/submission ancestry wins instead of being overridden by
    ambient `TRACEPARENT` state.
    
    ### What changed
    - Added `trace: Option<W3cTraceContext>` to codex_protocol::Submission
    - Taught `Codex::submit()` / `submit_with_id()` to automatically capture
    the current span context when constructing or forwarding a submission
    - Wrapped the core submission loop in a submission_dispatch span
    parented from Submission.trace
    - Warn on invalid submission trace carriers and ignore them cleanly
    - Removed the old env-based downstream reparenting path in core task
    execution
    - Stopped OTEL provider init from implicitly attaching env trace context
    process-wide
    - Updated mcp-server Submission call sites for the new field
    
    Added focused unit tests for:
    - capturing trace context into Submission
    - preferring `Submission.trace` when building the core dispatch span
    
    ### Why
    PR 1 gave us consistent inbound request spans in app-server, but that
    only covered the transport boundary. For long-running work like turns
    and reviews, the important missing piece was preserving ancestry after
    the request handler returns and core continues work on a different async
    path.
    
    This change makes that handoff explicit and keeps the parentage rules
    simple:
    - app-server request span sets the current context
    - `Submission.trace` snapshots that context
    - core restores it once, at the submission boundary
    - deeper core spans inherit naturally
    
    That also lets us stop relying on env-based reparenting for this path,
    which was too ambient and could override explicit ancestry.
  • feat(app-server): add tracing to all app-server APIs (#13285)
    ### Overview
    This PR adds the first piece of tracing for app-server JSON-RPC
    requests.
    
    There are two main changes:
    - JSON-RPC requests can now take an optional W3C trace context at the
    top level via a `trace` field (`traceparent` / `tracestate`).
    - app-server now creates a dedicated request span for every inbound
    JSON-RPC request in `MessageProcessor`, and uses the request-level trace
    context as the parent when present.
    
    For compatibility with existing flows, app-server still falls back to
    the TRACEPARENT env var when there is no request-level traceparent.
    
    This PR is intentionally scoped to the app-server boundary. In a
    followup, we'll actually propagate trace context through the async
    handoff into core execution spans like run_turn, which will make
    app-server traces much more useful.
    
    ### Spans
    A few details on the app-server span shape:
    - each inbound request gets its own server span
    - span/resource names are based on the JSON-RPC method (`initialize`,
    `thread/start`, `turn/start`, etc.)
    - spans record transport (stdio vs websocket), request id, connection
    id, and client name/version when available
    - `initialize` stores client metadata in session state so later requests
    on the same connection can reuse it
  • otel: add host.name resource attribute to logs/traces via gethostname (#12352)
    **PR Summary**
    
    This PR adds the OpenTelemetry `host.name` resource attribute to Codex
    OTEL exports so every OTEL log (and trace, via the shared resource)
    carries the machine hostname.
    
    **What changed**
    
    - Added `host.name` to the shared OTEL `Resource` in
    `/Users/michael.mcgrew/code/codex/codex-rs/otel/src/otel_provider.rs`
      - This applies to both:
        - OTEL logs (`SdkLoggerProvider`)
        - OTEL traces (`SdkTracerProvider`)
    - Hostname is now resolved via `gethostname::gethostname()`
    (best-effort)
      - Value is trimmed
      - Empty values are omitted (non-fatal)
    - Added focused unit tests for:
      - including `host.name` when present
      - omitting `host.name` when missing/empty
    
    **Why**
    
    - `host.name` is host/process metadata and belongs on the OTEL
    `resource`, not per-event attributes.
    - Attaching it in the shared resource is the smallest change that
    guarantees coverage across all exported OTEL logs/traces.
    
    **Scope / Non-goals**
    
    - No public API changes
    - No changes to metrics behavior (this PR only updates log/trace
    resource metadata)
    
    **Dependency updates**
    
    - Added `gethostname` as a workspace dependency and `codex-otel`
    dependency
    - `Cargo.lock` updated accordingly
    - `MODULE.bazel.lock` unchanged after refresh/check
    
    **Validation**
    
    - `just fmt`
    - `cargo test -p codex-otel`
    - `just bazel-lock-update`
    - `just bazel-lock-check`
  • feat: add service name to app-server (#12319)
    Add service name to the app-server so that the app can use it's own
    service name
    
    This is on thread level because later we might plan the app-server to
    become a singleton on the computer
  • Add MCP server context to otel tool_result logs (#12267)
    Summary
    - capture the origin for each configured MCP server and expose it via
    the connection manager
    - plumb MCP server name/origin into tool logging and emit
    codex.tool_result events with those fields
    - add unit coverage for origin parsing and extend OTEL tests to assert
    empty MCP fields for non-MCP tools
    - currently not logging full urls or url paths to prevent logging
    potentially sensitive data
    
    Testing
    - Not run (not requested)
  • add(core): safety check downgrade warning (#11964)
    Add per-turn notice when a request is downgraded to a fallback model due
    to cyber safety checks.
    
    **Changes**
    
    - codex-api: Emit a ServerModel event based on the openai-model response
    header and/or response payload (SSE + WebSocket), including when the
    model changes mid-stream.
    - core: When the server-reported model differs from the requested model,
    emit a single per-turn warning explaining the reroute to gpt-5.2 and
    directing users to Trusted
        Access verification and the cyber safety explainer.
    - app-server (v2): Surface these cyber model-routing warnings as
    synthetic userMessage items with text prefixed by Warning: (and document
    this behavior).
  • add sandbox policy and sandbox name to codex.tool.call metrics (#10711)
    This will give visibility into the comparative success rate of the
    Windows sandbox implementations compared to other platforms.
  • fix(auth): isolate chatgptAuthTokens concept to auth manager and app-server (#10423)
    So that the rest of the codebase (like TUI) don't need to be concerned
    whether ChatGPT auth was handled by Codex itself or passed in via
    app-server's external auth mode.
  • Include real OS info in metrics. (#10425)
    calculated a hashed user ID from either auth user id or API key
    Also correctly populates OS.
    
    These will make our metrics more useful and powerful for analysis.
  • Add websocket telemetry metrics and labels (#10316)
    Summary
    - expose websocket telemetry hooks through the responses client so
    request durations and event processing can be reported
    - record websocket request/event metrics and emit runtime telemetry
    events that the history UI now surfaces
    - improve tests to cover websocket telemetry reporting and guard runtime
    summary updates
    
    
    <img width="824" height="79" alt="Screenshot 2026-01-31 at 5 28 12 PM"
    src="https://github.com/user-attachments/assets/ea9a7965-d8b4-4e3c-a984-ef4fdc44c81d"
    />
  • feat: show runtime metrics in console (#10278)
    Summary of changes:
    
    - Adds a new feature flag: runtime_metrics
      - Declared in core/src/features.rs
      - Added to core/config.schema.json
      - Wired into OTEL init in core/src/otel_init.rs
    
    - Enables on-demand runtime metric snapshots in OTEL
      - Adds runtime_metrics: bool to otel/src/config.rs
      - Enables experimental custom reader features in otel/Cargo.toml
      - Adds snapshot/reset/summary APIs in:
        - otel/src/lib.rs
        - otel/src/metrics/client.rs
        - otel/src/metrics/config.rs
        - otel/src/metrics/error.rs
    
    - Defines metric names and a runtime summary builder
      - New files:
        - otel/src/metrics/names.rs
        - otel/src/metrics/runtime_metrics.rs
      - Summarizes totals for:
        - Tool calls
        - API requests
        - SSE/streaming events
    
    - Instruments metrics collection in OTEL manager
      - otel/src/traces/otel_manager.rs now records:
        - API call counts + durations
        - SSE event counts + durations (success/failure)
        - Tool call metrics now use shared constants
    
    - Surfaces runtime metrics in the TUI
      - Resets runtime metrics at turn start in tui/src/chatwidget.rs
    - Displays metrics in the final separator line in
    tui/src/history_cell.rs
    
    - Adds tests
      - New OTEL tests:
        - otel/tests/suite/snapshot.rs
        - otel/tests/suite/runtime_summary.rs
      - New TUI test:
    - final_message_separator_includes_runtime_metrics in
    tui/src/history_cell.rs
    
    Scope:
    - 19 files changed
    - ~652 insertions, 38 deletions
    
    
    <img width="922" height="169" alt="Screenshot 2026-01-30 at 4 11 34 PM"
    src="https://github.com/user-attachments/assets/1efd754d-a16d-4564-83a5-f4442fd2f998"
    />
  • feat: backfill timing metric (#10218)
    1. Add a metric to measure the backfill time
    2. Add a unit to the timing histogram
  • feat: sqlite 1 (#10004)
    Add a `.sqlite` database to be used to store rollout metatdata (and
    later logs)
    This PR is phase 1:
    * Add the database and the required infrastructure
    * Add a backfill of the database
    * Persist the newly created rollout both in files and in the DB
    * When we need to get metadata or a rollout, consider the `JSONL` as the
    source of truth but compare the results with the DB and show any errors
  • feat: add session source as otel metadata tag (#9720)
    Add session.source and user.account_id as global OTEL metric tags to
    identify client surface and user.
  • Act on reasoning-included per turn (#9402)
    - Reset reasoning-included flag each turn and update compaction test
  • Add text element metadata to types (#9235)
    Initial type tweaking PR to make the diff of
    https://github.com/openai/codex/pull/9116 smaller
    
    This should not change any behavior, just adds some fields to types
  • feat: metrics capabilities (#8318)
    Add metrics capabilities to Codex. The `README.md` is up to date.
    
    This will not be merged with the metrics before this PR of course:
    https://github.com/openai/codex/pull/8350
  • chore: unify conversation with thread name (#8830)
    Done and verified by Codex + refactor feature of RustRover
  • chore(deps): bump tracing-opentelemetry from 0.31.0 to 0.32.0 in /codex-rs (#8415)
    Bumps
    [tracing-opentelemetry](https://github.com/tokio-rs/tracing-opentelemetry)
    from 0.31.0 to 0.32.0.
    <details>
    <summary>Release notes</summary>
    <p><em>Sourced from <a
    href="https://github.com/tokio-rs/tracing-opentelemetry/releases">tracing-opentelemetry's
    releases</a>.</em></p>
    <blockquote>
    <h2>0.32.0</h2>
    <h3>Added</h3>
    <ul>
    <li>Add configuration for including <code>target</code> in spans (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/222">#222</a>)</li>
    </ul>
    <h3>Changed</h3>
    <ul>
    <li>OpenTelemetry context activation (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/202">#202</a>)
    <ul>
    <li>Trace ID and span ID can be obtained from <code>OtelData</code> via
    dedicated functions. Note that these
    will be available only if the context has already been built. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/233">#233</a>)</li>
    </ul>
    </li>
    <li>Correctly track entered and exited state for timings (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/212">#212</a>)</li>
    <li>Slightly improve error message on version mismatch (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/211">#211</a>)</li>
    <li>Remove Lazy for thread_local static (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/215">#215</a>)</li>
    <li>Update description of special fields and semantic conventions</li>
    </ul>
    <h3>Breaking Changes</h3>
    <ul>
    <li>The attributes <code>code.filepath</code>, <code>code.lineno</code>,
    and <code>code.namespace</code> have been renamed to
    <code>code.file.path</code>, and <code>code.line.number</code>, and
    <code>code.module.name</code>, to align with the opentelemetry
    semantic conventions for code. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/225">#225</a>)</li>
    <li>Upgrade from opentelemetry to 0.31.0. Refer to the upstream
    <a
    href="https://github.com/open-telemetry/opentelemetry-rust/blob/main/opentelemetry-sdk/CHANGELOG.md#0310">changelog</a>
    for more information. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/230">#230</a>)</li>
    <li>Hold onto <code>MetricsProvider</code> in <code>MetricsLayer</code>
    (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/224">#224</a>)</li>
    <li>The attribute <code>otel.status_message</code> was changed to
    <code>otel.status_description</code> to align with the
    opentelemetry semantic conventions for code. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/209">#209</a>)</li>
    <li>Remove the <code>metrics_gauge_unstable</code> feature.</li>
    </ul>
    </blockquote>
    </details>
    <details>
    <summary>Changelog</summary>
    <p><em>Sourced from <a
    href="https://github.com/tokio-rs/tracing-opentelemetry/blob/v0.1.x/CHANGELOG.md">tracing-opentelemetry's
    changelog</a>.</em></p>
    <blockquote>
    <h2><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/compare/v0.31.0...v0.32.0">0.32.0</a>
    - 2025-09-29</h2>
    <h3>Added</h3>
    <ul>
    <li>Add configuration for including <code>target</code> in spans (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/222">#222</a>)</li>
    </ul>
    <h3>Changed</h3>
    <ul>
    <li>OpenTelemetry context activation (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/202">#202</a>)
    <ul>
    <li>Trace ID and span ID can be obtained from <code>OtelData</code> via
    dedicated functions. Note that these
    will be available only if the context has already been built. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/233">#233</a>)</li>
    </ul>
    </li>
    <li>Correctly track entered and exited state for timings (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/212">#212</a>)</li>
    <li>Slightly improve error message on version mismatch (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/211">#211</a>)</li>
    <li>Remove Lazy for thread_local static (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/215">#215</a>)</li>
    <li>Update description of special fields and semantic conventions</li>
    </ul>
    <h3>Breaking Changes</h3>
    <ul>
    <li>The attributes <code>code.filepath</code>, <code>code.lineno</code>,
    and <code>code.namespace</code> have been renamed to
    <code>code.file.path</code>, and <code>code.line.number</code>, and
    <code>code.module.name</code>, to align with the opentelemetry
    semantic conventions for code. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/225">#225</a>)</li>
    <li>Upgrade from opentelemetry to 0.31.0. Refer to the upstream
    <a
    href="https://github.com/open-telemetry/opentelemetry-rust/blob/main/opentelemetry-sdk/CHANGELOG.md#0310">changelog</a>
    for more information. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/230">#230</a>)</li>
    <li>Hold onto <code>MetricsProvider</code> in <code>MetricsLayer</code>
    (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/224">#224</a>)</li>
    <li>The attribute <code>otel.status_message</code> was changed to
    <code>otel.status_description</code> to align with the
    opentelemetry semantic conventions for code. (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/pull/209">#209</a>)</li>
    <li>Remove the <code>metrics_gauge_unstable</code> feature.</li>
    </ul>
    </blockquote>
    </details>
    <details>
    <summary>Commits</summary>
    <ul>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/f663332dd81a9f37d4b6c61969596d6ff552202b"><code>f663332</code></a>
    chore: prepare release of 0.32.0</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/0154fa470b711c27d26d8bd3f2a7918b53203d75"><code>0154fa4</code></a>
    chore: fix docs link</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/d684c2ee368c8d87f7d409f44701117ac6032f9f"><code>d684c2e</code></a>
    chore: delete removed docs.rs feature</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/73a6baf71df28d7dd0b56e1131dc4e3177975f0f"><code>73a6baf</code></a>
    feat: make trace ID and span ID public on <code>OtelData</code> (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/233">#233</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/4ebae2c53792e76c71d47c0f651b8fb059094540"><code>4ebae2c</code></a>
    Upgrade to <code>opentelemetry</code> 0.31 (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/230">#230</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/4fdf56048d1e710a3fd2164a57ba8ce3b7bd10d4"><code>4fdf560</code></a>
    fix(layer)!: use otel semantic conventions for code (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/225">#225</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/612b5b2601e7db0c98efbb2fcde0a781593255c7"><code>612b5b2</code></a>
    chore: fix clippy lints (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/226">#226</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/c4fe96ac2a51bb1e60293aeb7346c3584bcdf4d3"><code>c4fe96a</code></a>
    feat: OpenTelemetry context activation (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/202">#202</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/764cd7365fd331ace160c7d539ed08761c16cd66"><code>764cd73</code></a>
    fix(metrics)!: hold onto <code>MetricsProvider</code> in
    <code>MetricsLayer</code> (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/224">#224</a>)</li>
    <li><a
    href="https://github.com/tokio-rs/tracing-opentelemetry/commit/fd0a58a7f48d5c6fe959dd9f856755893707694b"><code>fd0a58a</code></a>
    feat(layer): add configuration for including <code>target</code> in
    spans (<a
    href="https://redirect.github.com/tokio-rs/tracing-opentelemetry/issues/222">#222</a>)</li>
    <li>Additional commits viewable in <a
    href="https://github.com/tokio-rs/tracing-opentelemetry/compare/v0.31.0...v0.32.0">compare
    view</a></li>
    </ul>
    </details>
    <br />
    
    
    [![Dependabot compatibility
    score](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name=tracing-opentelemetry&package-manager=cargo&previous-version=0.31.0&new-version=0.32.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)
    
    Dependabot will resolve any conflicts with this PR as long as you don't
    alter it yourself. You can also trigger a rebase manually by commenting
    `@dependabot rebase`.
    
    [//]: # (dependabot-automerge-start)
    [//]: # (dependabot-automerge-end)
    
    ---
    
    <details>
    <summary>Dependabot commands and options</summary>
    <br />
    
    You can trigger Dependabot actions by commenting on this PR:
    - `@dependabot rebase` will rebase this PR
    - `@dependabot recreate` will recreate this PR, overwriting any edits
    that have been made to it
    - `@dependabot merge` will merge this PR after your CI passes on it
    - `@dependabot squash and merge` will squash and merge this PR after
    your CI passes on it
    - `@dependabot cancel merge` will cancel a previously requested merge
    and block automerging
    - `@dependabot reopen` will reopen this PR if it is closed
    - `@dependabot close` will close this PR and stop Dependabot recreating
    it. You can achieve the same result by closing it manually
    - `@dependabot show <dependency name> ignore conditions` will show all
    of the ignore conditions of the specified dependency
    - `@dependabot ignore this major version` will close this PR and stop
    Dependabot creating any more for this major version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this minor version` will close this PR and stop
    Dependabot creating any more for this minor version (unless you reopen
    the PR or upgrade to it yourself)
    - `@dependabot ignore this dependency` will close this PR and stop
    Dependabot creating any more for this dependency (unless you reopen the
    PR or upgrade to it yourself)
    
    
    </details>
    
    ---------
    
    Signed-off-by: dependabot[bot] <support@github.com>
    Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
    Co-authored-by: Anton Panasenko <apanasenko@openai.com>
  • Refresh on models etag mismatch (#8491)
    - Send models etag
    - Refresh models on 412
    - This wires `ModelsManager` to `ModelFamily` so we don't mutate it
    mid-turn
  • nit: trace span for regular task (#8053)
    Logs are too spammy
    
    ---------
    
    Co-authored-by: Anton Panasenko <apanasenko@openai.com>
  • Removed experimental "command risk assessment" feature (#7799)
    This experimental feature received lukewarm reception during internal
    testing. Removing from the code base.
  • fix: introduce AbsolutePathBuf and resolve relative paths in config.toml (#7796)
    This PR attempts to solve two problems by introducing a
    `AbsolutePathBuf` type with a special deserializer:
    
    - `AbsolutePathBuf` attempts to be a generally useful abstraction, as it
    ensures, by constructing, that it represents a value that is an
    absolute, normalized path, which is a stronger guarantee than an
    arbitrary `PathBuf`.
    - Values in `config.toml` that can be either an absolute or relative
    path should be resolved against the folder containing the `config.toml`
    in the relative path case. This PR makes this easy to support: the main
    cost is ensuring `AbsolutePathBufGuard` is used inside
    `deserialize_config_toml_with_base()`.
    
    While `AbsolutePathBufGuard` may seem slightly distasteful because it
    relies on thread-local storage, this seems much cleaner to me than using
    than my various experiments with
    https://docs.rs/serde/latest/serde/de/trait.DeserializeSeed.html.
    Further, since the `deserialize()` method from the `Deserialize` trait
    is not async, we do not really have to worry about the deserialization
    work being spread across multiple threads in a way that would interfere
    with `AbsolutePathBufGuard`.
    
    To start, this PR introduces the use of `AbsolutePathBuf` in
    `OtelTlsConfig`. Note how this simplifies `otel_provider.rs` because it
    no longer requires `settings.codex_home` to be threaded through.
    Furthermore, this sets us up better for a world where multiple
    `config.toml` files from different folders could be loaded and then
    merged together, as the absolutifying of the paths must be done against
    the correct parent folder.
  • fix: OTEL HTTP exporter panic and mTLS support (#7651)
    This fixes two issues with the OTEL HTTP exporter:
    
    1. **Runtime panic with async reqwest client**
    
    The `opentelemetry_sdk` `BatchLogProcessor` spawns a dedicated OS thread
    that uses `futures_executor::block_on()` rather than tokio's runtime.
    When the async reqwest client's timeout mechanism calls
    `tokio::time::sleep()`, it panics with "there is no reactor running,
    must be called from the context of a Tokio 1.x runtime".
    
    The fix is to use `reqwest::blocking::Client` instead, which doesn't
    depend on tokio for timeouts. However, the blocking client creates its
    own internal tokio runtime during construction, which would panic if
    built from within an async context. We wrap the construction in
    `tokio::task::block_in_place()` to handle this.
    
    2. **mTLS certificate handling**
    
    The HTTP client wasn't properly configured for mTLS, matching the fixes
    previously done for the model provider client:
    
    - Added `.tls_built_in_root_certs(false)` when using a custom CA
    certificate to ensure only our CA is trusted
    - Added `.https_only(true)` when using client identity
    - Added `rustls-tls` feature to ensure rustls is used (required for
    `Identity::from_pem()` to work correctly)
  • whitelist command prefix integration in core and tui (#7033)
    this PR enables TUI to approve commands and add their prefixes to an
    allowlist:
    <img width="708" height="605" alt="Screenshot 2025-11-21 at 4 18 07 PM"
    src="https://github.com/user-attachments/assets/56a19893-4553-4770-a881-becf79eeda32"
    />
    
    note: we only show the option to whitelist the command when 
    1) command is not multi-part (e.g `git add -A && git commit -m 'hello
    world'`)
    2) command is not already matched by an existing rule
  • Migrate model preset (#7542)
    - Introduce `openai_models` in `/core`
    - Move `PRESETS` under it
    - Move `ModelPreset`, `ModelUpgrade`, `ReasoningEffortPreset`,
    `ReasoningEffortPreset`, and `ReasoningEffortPreset` to `protocol`
    - Introduce `Op::ListModels` and `EventMsg::AvailableModels`
    
    Next steps:
    - migrate `app-server` and `tui` to use the introduced Operation
  • [codex][otel] support mtls configuration (#6228)
    fix for https://github.com/openai/codex/issues/6153
    
    supports mTLS configuration and includes TLS features in the library
    build to enable secure HTTPS connections with custom root certificates.
    
    grpc:
    https://docs.rs/tonic/0.13.1/src/tonic/transport/channel/endpoint.rs.html#63
    https:
    https://docs.rs/reqwest/0.12.23/src/reqwest/async_impl/client.rs.html#516