Compare commits

...

2 Commits

Author SHA1 Message Date
pakrym-oai
aabc9cca88 feedback: add trace context to logs and events uploaded to Sentry
Adds trace context (trace_id, span_id) to Sentry events and log items when uploading feedback. Ensures that both main event and logs are correlated via the same trace_id. Logs are now uploaded in a separate envelope when include_logs is true. Removes unnecessary import.
2025-10-27 08:17:29 -07:00
pakrym-oai
0d4d31f5d2 Upload logs 2025-10-26 09:29:35 -07:00
4 changed files with 437 additions and 202 deletions

432
codex-rs/Cargo.lock generated
View File

@@ -12,6 +12,158 @@ dependencies = [
"regex",
]
[[package]]
name = "actix-codec"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f7b0a21988c1bf877cf4759ef5ddaac04c1c9fe808c9142ecb78ba97d97a28a"
dependencies = [
"bitflags 2.10.0",
"bytes",
"futures-core",
"futures-sink",
"memchr",
"pin-project-lite",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "actix-http"
version = "3.11.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7926860314cbe2fb5d1f13731e387ab43bd32bca224e82e6e2db85de0a3dba49"
dependencies = [
"actix-codec",
"actix-rt",
"actix-service",
"actix-utils",
"base64",
"bitflags 2.10.0",
"bytes",
"bytestring",
"derive_more 2.0.1",
"encoding_rs",
"foldhash",
"futures-core",
"http 0.2.12",
"httparse",
"httpdate",
"itoa",
"language-tags",
"local-channel",
"mime",
"percent-encoding",
"pin-project-lite",
"rand 0.9.2",
"sha1",
"smallvec",
"tokio",
"tokio-util",
"tracing",
]
[[package]]
name = "actix-router"
version = "0.5.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13d324164c51f63867b57e73ba5936ea151b8a41a1d23d1031eeb9f70d0236f8"
dependencies = [
"bytestring",
"cfg-if",
"http 0.2.12",
"regex-lite",
"serde",
"tracing",
]
[[package]]
name = "actix-rt"
version = "2.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "92589714878ca59a7626ea19734f0e07a6a875197eec751bb5d3f99e64998c63"
dependencies = [
"futures-core",
"tokio",
]
[[package]]
name = "actix-server"
version = "2.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a65064ea4a457eaf07f2fba30b4c695bf43b721790e9530d26cb6f9019ff7502"
dependencies = [
"actix-rt",
"actix-service",
"actix-utils",
"futures-core",
"futures-util",
"mio",
"socket2 0.5.10",
"tokio",
"tracing",
]
[[package]]
name = "actix-service"
version = "2.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9e46f36bf0e5af44bdc4bdb36fbbd421aa98c79a9bce724e1edeb3894e10dc7f"
dependencies = [
"futures-core",
"pin-project-lite",
]
[[package]]
name = "actix-utils"
version = "3.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88a1dcdff1466e3c2488e1cb5c36a71822750ad43839937f85d2f4d9f8b705d8"
dependencies = [
"local-waker",
"pin-project-lite",
]
[[package]]
name = "actix-web"
version = "4.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a597b77b5c6d6a1e1097fddde329a83665e25c5437c696a3a9a4aa514a614dea"
dependencies = [
"actix-codec",
"actix-http",
"actix-router",
"actix-rt",
"actix-server",
"actix-service",
"actix-utils",
"bytes",
"bytestring",
"cfg-if",
"derive_more 2.0.1",
"encoding_rs",
"foldhash",
"futures-core",
"futures-util",
"impl-more",
"itoa",
"language-tags",
"log",
"mime",
"once_cell",
"pin-project-lite",
"regex-lite",
"serde",
"serde_json",
"serde_urlencoded",
"smallvec",
"socket2 0.5.10",
"time",
"tracing",
"url",
]
[[package]]
name = "addr2line"
version = "0.24.2"
@@ -494,7 +646,7 @@ dependencies = [
"axum-core",
"bytes",
"futures-util",
"http",
"http 1.3.1",
"http-body",
"http-body-util",
"hyper",
@@ -522,7 +674,7 @@ checksum = "68464cd0412f486726fb3373129ef5d2993f90c34bc2bc1c1e9943b2f4fc7ca6"
dependencies = [
"bytes",
"futures-core",
"http",
"http 1.3.1",
"http-body",
"http-body-util",
"mime",
@@ -554,6 +706,12 @@ version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
[[package]]
name = "base64ct"
version = "1.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "55248b47b0caf0546f7988906588779981c43bb1bc9d0c44087278f80cdb44ba"
[[package]]
name = "basic-toml"
version = "0.1.10"
@@ -592,9 +750,9 @@ checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
[[package]]
name = "bitflags"
version = "2.9.1"
version = "2.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b8e56985ec62d17e9c1001dc89c88ecd7dc08e47eba5ec7c29c7b5eeecde967"
checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3"
[[package]]
name = "block-buffer"
@@ -668,6 +826,15 @@ version = "1.10.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a"
[[package]]
name = "bytestring"
version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "113b4343b5f6617e7ad401ced8de3cc8b012e73a594347c307b90db3e9271289"
dependencies = [
"bytes",
]
[[package]]
name = "cassowary"
version = "0.3.0"
@@ -1076,7 +1243,7 @@ dependencies = [
"escargot",
"eventsource-stream",
"futures",
"http",
"http 1.3.1",
"indexmap 2.10.0",
"landlock",
"libc",
@@ -1178,6 +1345,10 @@ dependencies = [
"codex-protocol",
"pretty_assertions",
"sentry",
"sentry-tracing",
"serde",
"serde_json",
"tracing",
"tracing-subscriber",
]
@@ -1704,7 +1875,7 @@ version = "0.28.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"crossterm_winapi",
"futures-core",
"mio",
@@ -1904,6 +2075,16 @@ dependencies = [
"serde_json",
]
[[package]]
name = "der"
version = "0.7.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb"
dependencies = [
"pem-rfc7468",
"zeroize",
]
[[package]]
name = "deranged"
version = "0.5.4"
@@ -2048,7 +2229,7 @@ version = "0.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"objc2",
]
@@ -2672,7 +2853,7 @@ dependencies = [
"fnv",
"futures-core",
"futures-sink",
"http",
"http 1.3.1",
"indexmap 2.10.0",
"slab",
"tokio",
@@ -2773,6 +2954,17 @@ dependencies = [
"windows-link 0.1.3",
]
[[package]]
name = "http"
version = "0.2.12"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "601cbb57e577e2f5ef5be8e7b83f0f63994f25aa94d673e54a92d5c516d101f1"
dependencies = [
"bytes",
"fnv",
"itoa",
]
[[package]]
name = "http"
version = "1.3.1"
@@ -2791,7 +2983,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184"
dependencies = [
"bytes",
"http",
"http 1.3.1",
]
[[package]]
@@ -2802,7 +2994,7 @@ checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a"
dependencies = [
"bytes",
"futures-core",
"http",
"http 1.3.1",
"http-body",
"pin-project-lite",
]
@@ -2839,7 +3031,7 @@ dependencies = [
"futures-channel",
"futures-core",
"h2",
"http",
"http 1.3.1",
"http-body",
"httparse",
"httpdate",
@@ -2857,7 +3049,7 @@ version = "0.27.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e3c93eb611681b207e1fe55d5a71ecf91572ec8a6705cdb6857f7d8d5242cf58"
dependencies = [
"http",
"http 1.3.1",
"hyper",
"hyper-util",
"rustls",
@@ -2909,7 +3101,7 @@ dependencies = [
"futures-channel",
"futures-core",
"futures-util",
"http",
"http 1.3.1",
"http-body",
"hyper",
"ipnet",
@@ -3138,6 +3330,12 @@ dependencies = [
"zune-jpeg",
]
[[package]]
name = "impl-more"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e8a5a9a0ff0086c7a148acb942baaabeadf9504d10400b5a05645853729b9cd2"
[[package]]
name = "indenter"
version = "0.3.3"
@@ -3178,7 +3376,7 @@ version = "0.11.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f37dccff2791ab604f9babef0ba14fbe0be30bd368dc541e2b08d07c8aa908f3"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"inotify-sys",
"libc",
]
@@ -3241,7 +3439,7 @@ version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"libc",
]
@@ -3454,6 +3652,12 @@ dependencies = [
"thiserror 2.0.16",
]
[[package]]
name = "language-tags"
version = "0.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388"
[[package]]
name = "lazy_static"
version = "1.5.0"
@@ -3487,7 +3691,7 @@ version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4488594b9328dee448adb906d8b126d9b7deb7cf5c22161ee591610bb1be83c0"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"libc",
]
@@ -3497,7 +3701,7 @@ version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "761e49ec5fd8a5a463f9b84e877c373d888935b71c6be78f3767fe2ae6bed18e"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"libc",
]
@@ -3519,6 +3723,23 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
[[package]]
name = "local-channel"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6cbc85e69b8df4b8bb8b89ec634e7189099cea8927a276b7384ce5488e53ec8"
dependencies = [
"futures-core",
"futures-sink",
"local-waker",
]
[[package]]
name = "local-waker"
version = "0.1.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d873d7c67ce09b42110d801813efbc9364414e356be9935700d368351657487"
[[package]]
name = "lock_api"
version = "0.4.13"
@@ -3765,7 +3986,7 @@ version = "0.28.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"cfg_aliases 0.1.1",
"libc",
@@ -3777,7 +3998,7 @@ version = "0.29.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"cfg_aliases 0.2.1",
"libc",
@@ -3790,7 +4011,7 @@ version = "0.30.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "74523f3a35e05aba87a1d978330aef40f67b0304ac79c1c00b294c9830543db6"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"cfg_aliases 0.2.1",
"libc",
@@ -3818,7 +4039,7 @@ version = "8.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d3d07927151ff8575b7087f245456e549fea62edf0ec4e565a5ee50c8402bc3"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"fsevent-sys",
"inotify",
"kqueue",
@@ -3962,7 +4183,7 @@ dependencies = [
"base64",
"chrono",
"getrandom 0.2.16",
"http",
"http 1.3.1",
"rand 0.8.5",
"reqwest",
"serde",
@@ -3988,7 +4209,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"objc2",
"objc2-core-graphics",
"objc2-foundation",
@@ -4000,7 +4221,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"dispatch2",
"objc2",
]
@@ -4011,7 +4232,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"dispatch2",
"objc2",
"objc2-core-foundation",
@@ -4030,7 +4251,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"objc2",
"objc2-core-foundation",
]
@@ -4041,7 +4262,7 @@ version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"objc2",
"objc2-core-foundation",
]
@@ -4073,7 +4294,7 @@ version = "0.10.73"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8505734d46c8ab1e19a1dce3aef597ad87dcb4c37e7188231769bd6bd51cebf8"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"foreign-types",
"libc",
@@ -4155,7 +4376,7 @@ checksum = "50f6639e842a97dbea8886e3439710ae463120091e2e064518ba8e716e6ac36d"
dependencies = [
"async-trait",
"bytes",
"http",
"http 1.3.1",
"opentelemetry",
"reqwest",
]
@@ -4166,7 +4387,7 @@ version = "0.30.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dbee664a43e07615731afc539ca60c6d9f1a9425e25ca09c57bc36c87c55852b"
dependencies = [
"http",
"http 1.3.1",
"opentelemetry",
"opentelemetry-http",
"opentelemetry-proto",
@@ -4312,6 +4533,15 @@ version = "0.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "df94ce210e5bc13cb6651479fa48d14f601d9858cfe0467f43ae157023b938d3"
[[package]]
name = "pem-rfc7468"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "88b39c9bfcfc231068454382784bb460aae594343fb030d46e9f50a645418412"
dependencies = [
"base64ct",
]
[[package]]
name = "percent-encoding"
version = "2.3.1"
@@ -4405,7 +4635,7 @@ version = "0.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "97baced388464909d42d89643fe4361939af9b7ce7a31ee32a168f832a70f2a0"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"crc32fast",
"fdeflate",
"flate2",
@@ -4594,7 +4824,7 @@ version = "0.10.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "76979bea66e7875e7509c4ec5300112b316af87fa7a252ca91c448b32dfe3993"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"getopts",
"memchr",
"pulldown-cmark-escape",
@@ -4775,7 +5005,7 @@ name = "ratatui"
version = "0.29.0"
source = "git+https://github.com/nornagon/ratatui?branch=nornagon-v0.29.0-patch#9b2ad1298408c45918ee9f8241a6f95498cdbed2"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cassowary",
"compact_str",
"crossterm",
@@ -4805,7 +5035,7 @@ version = "0.5.15"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8af0dde094006011e6a740d4879319439489813bd0bcdc7d821beaeeff48ec"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
]
[[package]]
@@ -4904,7 +5134,7 @@ dependencies = [
"futures-core",
"futures-util",
"h2",
"http",
"http 1.3.1",
"http-body",
"http-body-util",
"hyper",
@@ -4964,7 +5194,7 @@ dependencies = [
"bytes",
"chrono",
"futures",
"http",
"http 1.3.1",
"http-body",
"http-body-util",
"oauth2",
@@ -5034,7 +5264,7 @@ version = "0.38.44"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fdb5bc1ae2baa591800df16c9ca78619bf65c0488b41b96ccec5d11220d8c154"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"errno",
"libc",
"linux-raw-sys 0.4.15",
@@ -5047,7 +5277,7 @@ version = "1.0.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "11181fbabf243db407ef8df94a6ce0b2f9a733bd8be4ad02b4eda9602296cac8"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"errno",
"libc",
"linux-raw-sys 0.9.4",
@@ -5080,6 +5310,15 @@ dependencies = [
"security-framework 3.5.1",
]
[[package]]
name = "rustls-pemfile"
version = "2.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dce314e5fee3f39953d46bb63bb8a46d40c2f8fb7cc5a3b6cab2bde9721d6e50"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "rustls-pki-types"
version = "1.12.0"
@@ -5113,7 +5352,7 @@ version = "14.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7803e8936da37efd9b6d4478277f4b2b9bb5cdb37a113e8d63222e58da647e63"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"cfg-if",
"clipboard-win",
"fd-lock",
@@ -5312,7 +5551,7 @@ version = "2.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "897b2245f0b511c87893af39b033e5ca9cce68824c4d7e7630b5a1d339658d02"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"core-foundation 0.9.4",
"core-foundation-sys",
"libc",
@@ -5325,7 +5564,7 @@ version = "3.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b3297343eaf830f66ede390ea39da1d462b6b0c1b000f420d0a83f898bbbe6ef"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"core-foundation 0.10.1",
"core-foundation-sys",
"libc",
@@ -5350,13 +5589,14 @@ checksum = "d767eb0aabc880b29956c35734170f26ed551a859dbd361d140cdbeca61ab1e2"
[[package]]
name = "sentry"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5484316556650182f03b43d4c746ce0e3e48074a21e2f51244b648b6542e1066"
checksum = "48b85e25e8a1fc13928885e8bf13abe8a09e15c46993aed05d6405f7755d6e20"
dependencies = [
"httpdate",
"native-tls",
"reqwest",
"sentry-actix",
"sentry-backtrace",
"sentry-contexts",
"sentry-core",
@@ -5368,22 +5608,34 @@ dependencies = [
]
[[package]]
name = "sentry-backtrace"
version = "0.34.0"
name = "sentry-actix"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "40aa225bb41e2ec9d7c90886834367f560efc1af028f1c5478a6cce6a59c463a"
checksum = "cc694e6ffc8d5d7fdb2a33923b0358f6ad41c0b428ced034b349b9e2b08260bc"
dependencies = [
"actix-http",
"actix-web",
"bytes",
"futures-util",
"sentry-core",
]
[[package]]
name = "sentry-backtrace"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f3253a495ab536f6de1746a58d5d7824b77d75e08e1a4b8ca6fb356839077ae0"
dependencies = [
"backtrace",
"once_cell",
"regex",
"sentry-core",
]
[[package]]
name = "sentry-contexts"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a8dd746da3d16cb8c39751619cefd4fcdbd6df9610f3310fd646b55f6e39910"
checksum = "027f81a728836e66b88c07666a10f5ed5a35e2695b04eb7aa0fcbed93f814900"
dependencies = [
"hostname",
"libc",
@@ -5395,33 +5647,32 @@ dependencies = [
[[package]]
name = "sentry-core"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "161283cfe8e99c8f6f236a402b9ccf726b201f365988b5bb637ebca0abbd4a30"
checksum = "d3b6729c8e71ac968edbe9bf2dd4109c162e552b52bacd2b07e24ede1aba84a5"
dependencies = [
"once_cell",
"rand 0.8.5",
"rand 0.9.2",
"sentry-types",
"serde",
"serde_json",
"url",
]
[[package]]
name = "sentry-debug-images"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8fc6b25e945fcaa5e97c43faee0267eebda9f18d4b09a251775d8fef1086238a"
checksum = "dc85b59c1dfb19912bfba1af73a592e2e5548cae241a79ecb805afab3333d04c"
dependencies = [
"findshlibs",
"once_cell",
"sentry-core",
]
[[package]]
name = "sentry-panic"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc74f229c7186dd971a9491ffcbe7883544aa064d1589bd30b83fb856cd22d63"
checksum = "1ac0471f04f8f97af0c17eeca2c516e23faa1c0271a55bc64371d9ce488c2d40"
dependencies = [
"sentry-backtrace",
"sentry-core",
@@ -5429,10 +5680,11 @@ dependencies = [
[[package]]
name = "sentry-tracing"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cd3c5faf2103cd01eeda779ea439b68c4ee15adcdb16600836e97feafab362ec"
checksum = "428f780866a613142dcc81b7f8551ae4d1c056f4df22b6d7ddd9154a9974eb03"
dependencies = [
"bitflags 2.10.0",
"sentry-backtrace",
"sentry-core",
"tracing-core",
@@ -5441,16 +5693,16 @@ dependencies = [
[[package]]
name = "sentry-types"
version = "0.34.0"
version = "0.45.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5d68cdf6bc41b8ff3ae2a9c4671e97426dcdd154cc1d4b6b72813f285d6b163f"
checksum = "2c19d1d1967b55659c358886d0f1aa3076488d445f84c7d727d384c675adaec1"
dependencies = [
"debugid",
"hex",
"rand 0.8.5",
"rand 0.9.2",
"serde",
"serde_json",
"thiserror 1.0.69",
"thiserror 2.0.16",
"time",
"url",
"uuid",
@@ -6024,7 +6276,7 @@ version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3c879d448e9d986b661742763247d3693ed13609438cf3d006f51f5368a5ba6b"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"core-foundation 0.9.4",
"system-configuration-sys",
]
@@ -6439,7 +6691,7 @@ dependencies = [
"base64",
"bytes",
"h2",
"http",
"http 1.3.1",
"http-body",
"http-body-util",
"hyper",
@@ -6482,10 +6734,10 @@ version = "0.6.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "adc82fd73de2a9722ac5da747f12383d2bfdb93591ee6c58486e0097890f05f2"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
"bytes",
"futures-util",
"http",
"http 1.3.1",
"http-body",
"iri-string",
"pin-project-lite",
@@ -6770,15 +7022,32 @@ checksum = "8ecb6da28b8a351d773b68d5825ac39017e680750f980f3a1a85cd8dd28a47c1"
[[package]]
name = "ureq"
version = "2.12.1"
version = "3.1.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "02d1a66277ed75f640d608235660df48c8e3c19f3b4edb6a263315626cc3c01d"
checksum = "99ba1025f18a4a3fc3e9b48c868e9beb4f24f4b4b1a325bada26bd4119f46537"
dependencies = [
"base64",
"der",
"log",
"native-tls",
"once_cell",
"url",
"percent-encoding",
"rustls-pemfile",
"rustls-pki-types",
"ureq-proto",
"utf-8",
"webpki-root-certs",
]
[[package]]
name = "ureq-proto"
version = "0.5.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b4531c118335662134346048ddb0e54cc86bd7e81866757873055f0e38f5d2"
dependencies = [
"base64",
"http 1.3.1",
"httparse",
"log",
]
[[package]]
@@ -6799,6 +7068,12 @@ version = "2.1.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "daf8dba3b7eb870caf1ddeed7bc9d2a049f3cfdfae7cb521b087cc33ae4c49da"
[[package]]
name = "utf-8"
version = "0.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "09cc8ee72d2a9becf2f2febe0205bbed8fc6615b7cb429ad062dc7b7ddd036a9"
[[package]]
name = "utf8_iter"
version = "1.0.4"
@@ -7025,6 +7300,15 @@ dependencies = [
"web-sys",
]
[[package]]
name = "webpki-root-certs"
version = "1.0.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05d651ec480de84b762e7be71e6efa7461699c19d9e2c272c8d93455f567786e"
dependencies = [
"rustls-pki-types",
]
[[package]]
name = "webpki-roots"
version = "1.0.2"
@@ -7538,7 +7822,7 @@ dependencies = [
"base64",
"deadpool",
"futures",
"http",
"http 1.3.1",
"http-body-util",
"hyper",
"hyper-util",
@@ -7557,7 +7841,7 @@ version = "0.39.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1"
dependencies = [
"bitflags 2.9.1",
"bitflags 2.10.0",
]
[[package]]

View File

@@ -6,8 +6,13 @@ version.workspace = true
[dependencies]
anyhow = { workspace = true }
codex-protocol = { workspace = true }
sentry = { version = "0.34" }
sentry = { version = "0.45" }
sentry-tracing = { version = "0.45", features = ["logs"] }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true }
tracing = { workspace = true }
tracing-subscriber = { workspace = true }
[dev-dependencies]
pretty_assertions = { workspace = true }

View File

@@ -1,6 +1,5 @@
use std::collections::VecDeque;
use std::fs;
use std::io::Write;
use std::io::{self};
use std::path::PathBuf;
use std::sync::Arc;
@@ -10,9 +9,20 @@ use std::time::Duration;
use anyhow::Result;
use anyhow::anyhow;
use codex_protocol::ConversationId;
use tracing_subscriber::fmt::writer::MakeWriter;
use sentry::protocol::ItemContainer;
use sentry::protocol::Log;
use sentry::protocol::SpanId;
use sentry::protocol::TraceContext;
use sentry::protocol::TraceId;
use sentry_tracing::log_from_event;
use tracing::Event;
use tracing::Subscriber;
const DEFAULT_MAX_BYTES: usize = 4 * 1024 * 1024; // 4 MiB
use tracing_subscriber::Layer;
use tracing_subscriber::layer::Context;
use tracing_subscriber::registry::LookupSpan;
const DEFAULT_MAX_MESSAGES: usize = 300;
const SENTRY_DSN: &str =
"https://ae32ed50620d7a7792c1ce5df38b3e3e@o33249.ingest.us.sentry.io/4510195390611458";
const UPLOAD_TIMEOUT_SECS: u64 = 10;
@@ -30,28 +40,28 @@ impl Default for CodexFeedback {
impl CodexFeedback {
pub fn new() -> Self {
Self::with_capacity(DEFAULT_MAX_BYTES)
Self::with_capacity(DEFAULT_MAX_MESSAGES)
}
pub(crate) fn with_capacity(max_bytes: usize) -> Self {
pub(crate) fn with_capacity(max_messages: usize) -> Self {
Self {
inner: Arc::new(FeedbackInner::new(max_bytes)),
inner: Arc::new(FeedbackInner::new(max_messages)),
}
}
pub fn make_writer(&self) -> FeedbackMakeWriter {
FeedbackMakeWriter {
pub fn make_layer(&self) -> FeedbackLayer {
FeedbackLayer {
inner: self.inner.clone(),
}
}
pub fn snapshot(&self, session_id: Option<ConversationId>) -> CodexLogSnapshot {
let bytes = {
let guard = self.inner.ring.lock().expect("mutex poisoned");
guard.snapshot_bytes()
let logs = {
let guard = self.inner.messages.lock().expect("mutex poisoned");
guard.clone()
};
CodexLogSnapshot {
bytes,
logs,
thread_id: session_id
.map(|id| id.to_string())
.unwrap_or("no-active-thread-".to_string() + &ConversationId::new().to_string()),
@@ -60,116 +70,59 @@ impl CodexFeedback {
}
struct FeedbackInner {
ring: Mutex<RingBuffer>,
messages: Mutex<VecDeque<Log>>,
}
impl FeedbackInner {
fn new(max_bytes: usize) -> Self {
fn new(max_messages: usize) -> Self {
Self {
ring: Mutex::new(RingBuffer::new(max_bytes)),
messages: Mutex::new(VecDeque::with_capacity(max_messages)),
}
}
fn add_message(&self, message: Log) {
let mut guard = self.messages.lock().expect("mutex poisoned");
guard.push_back(message);
}
}
#[derive(Clone)]
pub struct FeedbackMakeWriter {
pub struct FeedbackLayer {
inner: Arc<FeedbackInner>,
}
impl<'a> MakeWriter<'a> for FeedbackMakeWriter {
type Writer = FeedbackWriter;
fn make_writer(&'a self) -> Self::Writer {
FeedbackWriter {
inner: self.inner.clone(),
}
}
}
pub struct FeedbackWriter {
inner: Arc<FeedbackInner>,
}
impl Write for FeedbackWriter {
fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
let mut guard = self.inner.ring.lock().map_err(|_| io::ErrorKind::Other)?;
guard.push_bytes(buf);
Ok(buf.len())
}
fn flush(&mut self) -> io::Result<()> {
Ok(())
}
}
struct RingBuffer {
max: usize,
buf: VecDeque<u8>,
}
impl RingBuffer {
fn new(capacity: usize) -> Self {
Self {
max: capacity,
buf: VecDeque::with_capacity(capacity),
}
}
fn len(&self) -> usize {
self.buf.len()
}
fn push_bytes(&mut self, data: &[u8]) {
if data.is_empty() {
return;
}
// If the incoming chunk is larger than capacity, keep only the trailing bytes.
if data.len() >= self.max {
self.buf.clear();
let start = data.len() - self.max;
self.buf.extend(data[start..].iter().copied());
return;
}
// Evict from the front if we would exceed capacity.
let needed = self.len() + data.len();
if needed > self.max {
let to_drop = needed - self.max;
for _ in 0..to_drop {
let _ = self.buf.pop_front();
}
}
self.buf.extend(data.iter().copied());
}
fn snapshot_bytes(&self) -> Vec<u8> {
self.buf.iter().copied().collect()
impl<S> Layer<S> for FeedbackLayer
where
S: Subscriber + for<'a> LookupSpan<'a>,
{
fn on_event(&self, event: &Event, ctx: Context<'_, S>) {
let log = log_from_event(event, Some(&ctx));
self.inner.add_message(log);
}
}
pub struct CodexLogSnapshot {
bytes: Vec<u8>,
logs: VecDeque<Log>,
pub thread_id: String,
}
impl CodexLogSnapshot {
pub(crate) fn as_bytes(&self) -> &[u8] {
&self.bytes
}
pub fn save_to_temp_file(&self) -> io::Result<PathBuf> {
let dir = std::env::temp_dir();
let filename = format!("codex-feedback-{}.log", self.thread_id);
let path = dir.join(filename);
fs::write(&path, self.as_bytes())?;
let messages_text = self
.logs
.iter()
.filter_map(|message| serde_json::to_string(&message).ok())
.collect::<Vec<String>>()
.join("\n");
fs::write(&path, messages_text)?;
Ok(path)
}
/// Upload feedback to Sentry with optional attachments.
pub fn upload_feedback(
&self,
&mut self,
classification: &str,
reason: Option<&str>,
cli_version: &str,
@@ -212,7 +165,6 @@ impl CodexLogSnapshot {
_ => Level::Info,
};
let mut envelope = Envelope::new();
let title = format!(
"[{}]: Codex session {}",
display_classification(classification),
@@ -225,6 +177,7 @@ impl CodexLogSnapshot {
tags,
..Default::default()
};
if let Some(r) = reason {
use sentry::protocol::Exception;
use sentry::protocol::Values;
@@ -235,15 +188,22 @@ impl CodexLogSnapshot {
..Default::default()
}]);
}
envelope.add_item(EnvelopeItem::Event(event));
if include_logs {
envelope.add_item(EnvelopeItem::Attachment(Attachment {
buffer: self.bytes.clone(),
filename: String::from("codex-logs.log"),
content_type: Some("text/plain".to_string()),
ty: None,
}));
let trace_id = TraceId::default();
let trace_context = TraceContext {
span_id: SpanId::default(),
trace_id,
..Default::default()
};
let mut envelope = Envelope::new();
event.contexts.insert(
"trace".to_string(),
sentry::protocol::Context::Trace(Box::new(trace_context)),
);
for log in self.logs.iter_mut() {
log.trace_id = Some(trace_id);
}
if let Some((path, data)) = rollout_path.and_then(|p| fs::read(p).ok().map(|d| (p, d))) {
@@ -261,6 +221,15 @@ impl CodexLogSnapshot {
}
client.send_envelope(envelope);
if include_logs {
let mut log_envelope = Envelope::new();
log_envelope.add_item(EnvelopeItem::ItemContainer(ItemContainer::Logs(
self.logs.iter().cloned().collect(),
)));
client.send_envelope(log_envelope);
}
client.flush(Some(Duration::from_secs(UPLOAD_TIMEOUT_SECS)));
Ok(())
}
@@ -274,21 +243,3 @@ fn display_classification(classification: &str) -> String {
_ => "Other".to_string(),
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn ring_buffer_drops_front_when_full() {
let fb = CodexFeedback::with_capacity(8);
{
let mut w = fb.make_writer().make_writer();
w.write_all(b"abcdefgh").unwrap();
w.write_all(b"ij").unwrap();
}
let snap = fb.snapshot(None);
// Capacity 8: after writing 10 bytes, we should keep the last 8.
pretty_assertions::assert_eq!(std::str::from_utf8(snap.as_bytes()).unwrap(), "cdefghij");
}
}

View File

@@ -214,13 +214,8 @@ pub async fn run_main(
.with_filter(env_filter());
let feedback = codex_feedback::CodexFeedback::new();
let targets = Targets::new().with_default(tracing::Level::TRACE);
let feedback_layer = tracing_subscriber::fmt::layer()
.with_writer(feedback.make_writer())
.with_ansi(false)
.with_target(false)
.with_filter(targets);
let feedback_layer = feedback.make_layer();
if cli.oss {
codex_ollama::ensure_oss_ready(&config)