Convert opencode transcripts to otel (or agent) traces
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

Initial exp2span: parse opencode logs to OpenTelemetry spans with MCP semantics

rektide 85a1a137

+2378
+1542
Cargo.lock
··· 1 + # This file is automatically @generated by Cargo. 2 + # It is not intended for manual editing. 3 + version = 4 4 + 5 + [[package]] 6 + name = "aho-corasick" 7 + version = "1.1.4" 8 + source = "registry+https://github.com/rust-lang/crates.io-index" 9 + checksum = "ddd31a130427c27518df266943a5308ed92d4b226cc639f5a8f1002816174301" 10 + dependencies = [ 11 + "memchr", 12 + ] 13 + 14 + [[package]] 15 + name = "android_system_properties" 16 + version = "0.1.5" 17 + source = "registry+https://github.com/rust-lang/crates.io-index" 18 + checksum = "819e7219dbd41043ac279b19830f2efc897156490d7fd6ea916720117ee66311" 19 + dependencies = [ 20 + "libc", 21 + ] 22 + 23 + [[package]] 24 + name = "anyhow" 25 + version = "1.0.100" 26 + source = "registry+https://github.com/rust-lang/crates.io-index" 27 + checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" 28 + 29 + [[package]] 30 + name = "async-stream" 31 + version = "0.3.6" 32 + source = "registry+https://github.com/rust-lang/crates.io-index" 33 + checksum = "0b5a71a6f37880a80d1d7f19efd781e4b5de42c88f0722cc13bcb6cc2cfe8476" 34 + dependencies = [ 35 + "async-stream-impl", 36 + "futures-core", 37 + "pin-project-lite", 38 + ] 39 + 40 + [[package]] 41 + name = "async-stream-impl" 42 + version = "0.3.6" 43 + source = "registry+https://github.com/rust-lang/crates.io-index" 44 + checksum = "c7c24de15d275a1ecfd47a380fb4d5ec9bfe0933f309ed5e705b775596a3574d" 45 + dependencies = [ 46 + "proc-macro2", 47 + "quote", 48 + "syn", 49 + ] 50 + 51 + [[package]] 52 + name = "async-trait" 53 + version = "0.1.89" 54 + source = "registry+https://github.com/rust-lang/crates.io-index" 55 + checksum = "9035ad2d096bed7955a320ee7e2230574d28fd3c3a0f186cbea1ff3c7eed5dbb" 56 + dependencies = [ 57 + "proc-macro2", 58 + "quote", 59 + "syn", 60 + ] 61 + 62 + [[package]] 63 + name = "atomic-waker" 64 + version = "1.1.2" 65 + source = "registry+https://github.com/rust-lang/crates.io-index" 66 + checksum = "1505bd5d3d116872e7271a6d4e16d81d0c8570876c8de68093a09ac269d8aac0" 67 + 68 + [[package]] 69 + name = "autocfg" 70 + version = "1.5.0" 71 + source = "registry+https://github.com/rust-lang/crates.io-index" 72 + checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" 73 + 74 + [[package]] 75 + name = "axum" 76 + version = "0.7.9" 77 + source = "registry+https://github.com/rust-lang/crates.io-index" 78 + checksum = "edca88bc138befd0323b20752846e6587272d3b03b0343c8ea28a6f819e6e71f" 79 + dependencies = [ 80 + "async-trait", 81 + "axum-core", 82 + "bytes", 83 + "futures-util", 84 + "http", 85 + "http-body", 86 + "http-body-util", 87 + "itoa", 88 + "matchit", 89 + "memchr", 90 + "mime", 91 + "percent-encoding", 92 + "pin-project-lite", 93 + "rustversion", 94 + "serde", 95 + "sync_wrapper", 96 + "tower 0.5.3", 97 + "tower-layer", 98 + "tower-service", 99 + ] 100 + 101 + [[package]] 102 + name = "axum-core" 103 + version = "0.4.5" 104 + source = "registry+https://github.com/rust-lang/crates.io-index" 105 + checksum = "09f2bd6146b97ae3359fa0cc6d6b376d9539582c7b4220f041a33ec24c226199" 106 + dependencies = [ 107 + "async-trait", 108 + "bytes", 109 + "futures-util", 110 + "http", 111 + "http-body", 112 + "http-body-util", 113 + "mime", 114 + "pin-project-lite", 115 + "rustversion", 116 + "sync_wrapper", 117 + "tower-layer", 118 + "tower-service", 119 + ] 120 + 121 + [[package]] 122 + name = "base64" 123 + version = "0.22.1" 124 + source = "registry+https://github.com/rust-lang/crates.io-index" 125 + checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6" 126 + 127 + [[package]] 128 + name = "bitflags" 129 + version = "2.10.0" 130 + source = "registry+https://github.com/rust-lang/crates.io-index" 131 + checksum = "812e12b5285cc515a9c72a5c1d3b6d46a19dac5acfef5265968c166106e31dd3" 132 + 133 + [[package]] 134 + name = "bumpalo" 135 + version = "3.19.1" 136 + source = "registry+https://github.com/rust-lang/crates.io-index" 137 + checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" 138 + 139 + [[package]] 140 + name = "bytes" 141 + version = "1.11.0" 142 + source = "registry+https://github.com/rust-lang/crates.io-index" 143 + checksum = "b35204fbdc0b3f4446b89fc1ac2cf84a8a68971995d0bf2e925ec7cd960f9cb3" 144 + 145 + [[package]] 146 + name = "cc" 147 + version = "1.2.55" 148 + source = "registry+https://github.com/rust-lang/crates.io-index" 149 + checksum = "47b26a0954ae34af09b50f0de26458fa95369a0d478d8236d3f93082b219bd29" 150 + dependencies = [ 151 + "find-msvc-tools", 152 + "shlex", 153 + ] 154 + 155 + [[package]] 156 + name = "cfg-if" 157 + version = "1.0.4" 158 + source = "registry+https://github.com/rust-lang/crates.io-index" 159 + checksum = "9330f8b2ff13f34540b44e946ef35111825727b38d33286ef986142615121801" 160 + 161 + [[package]] 162 + name = "chrono" 163 + version = "0.4.43" 164 + source = "registry+https://github.com/rust-lang/crates.io-index" 165 + checksum = "fac4744fb15ae8337dc853fee7fb3f4e48c0fbaa23d0afe49c447b4fab126118" 166 + dependencies = [ 167 + "iana-time-zone", 168 + "js-sys", 169 + "num-traits", 170 + "serde", 171 + "wasm-bindgen", 172 + "windows-link", 173 + ] 174 + 175 + [[package]] 176 + name = "core-foundation-sys" 177 + version = "0.8.7" 178 + source = "registry+https://github.com/rust-lang/crates.io-index" 179 + checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" 180 + 181 + [[package]] 182 + name = "either" 183 + version = "1.15.0" 184 + source = "registry+https://github.com/rust-lang/crates.io-index" 185 + checksum = "48c757948c5ede0e46177b7add2e67155f70e33c07fea8284df6576da70b3719" 186 + 187 + [[package]] 188 + name = "equivalent" 189 + version = "1.0.2" 190 + source = "registry+https://github.com/rust-lang/crates.io-index" 191 + checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" 192 + 193 + [[package]] 194 + name = "errno" 195 + version = "0.3.14" 196 + source = "registry+https://github.com/rust-lang/crates.io-index" 197 + checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" 198 + dependencies = [ 199 + "libc", 200 + "windows-sys 0.61.2", 201 + ] 202 + 203 + [[package]] 204 + name = "exp2span" 205 + version = "0.1.0" 206 + dependencies = [ 207 + "anyhow", 208 + "chrono", 209 + "opentelemetry", 210 + "opentelemetry-otlp", 211 + "opentelemetry_sdk", 212 + "regex", 213 + "serde", 214 + "serde_json", 215 + "tokio", 216 + "tracing", 217 + "tracing-opentelemetry", 218 + "tracing-subscriber", 219 + ] 220 + 221 + [[package]] 222 + name = "find-msvc-tools" 223 + version = "0.1.9" 224 + source = "registry+https://github.com/rust-lang/crates.io-index" 225 + checksum = "5baebc0774151f905a1a2cc41989300b1e6fbb29aff0ceffa1064fdd3088d582" 226 + 227 + [[package]] 228 + name = "fnv" 229 + version = "1.0.7" 230 + source = "registry+https://github.com/rust-lang/crates.io-index" 231 + checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 232 + 233 + [[package]] 234 + name = "futures-channel" 235 + version = "0.3.31" 236 + source = "registry+https://github.com/rust-lang/crates.io-index" 237 + checksum = "2dff15bf788c671c1934e366d07e30c1814a8ef514e1af724a602e8a2fbe1b10" 238 + dependencies = [ 239 + "futures-core", 240 + ] 241 + 242 + [[package]] 243 + name = "futures-core" 244 + version = "0.3.31" 245 + source = "registry+https://github.com/rust-lang/crates.io-index" 246 + checksum = "05f29059c0c2090612e8d742178b0580d2dc940c837851ad723096f87af6663e" 247 + 248 + [[package]] 249 + name = "futures-executor" 250 + version = "0.3.31" 251 + source = "registry+https://github.com/rust-lang/crates.io-index" 252 + checksum = "1e28d1d997f585e54aebc3f97d39e72338912123a67330d723fdbb564d646c9f" 253 + dependencies = [ 254 + "futures-core", 255 + "futures-task", 256 + "futures-util", 257 + ] 258 + 259 + [[package]] 260 + name = "futures-macro" 261 + version = "0.3.31" 262 + source = "registry+https://github.com/rust-lang/crates.io-index" 263 + checksum = "162ee34ebcb7c64a8abebc059ce0fee27c2262618d7b60ed8faf72fef13c3650" 264 + dependencies = [ 265 + "proc-macro2", 266 + "quote", 267 + "syn", 268 + ] 269 + 270 + [[package]] 271 + name = "futures-sink" 272 + version = "0.3.31" 273 + source = "registry+https://github.com/rust-lang/crates.io-index" 274 + checksum = "e575fab7d1e0dcb8d0c7bcf9a63ee213816ab51902e6d244a95819acacf1d4f7" 275 + 276 + [[package]] 277 + name = "futures-task" 278 + version = "0.3.31" 279 + source = "registry+https://github.com/rust-lang/crates.io-index" 280 + checksum = "f90f7dce0722e95104fcb095585910c0977252f286e354b5e3bd38902cd99988" 281 + 282 + [[package]] 283 + name = "futures-util" 284 + version = "0.3.31" 285 + source = "registry+https://github.com/rust-lang/crates.io-index" 286 + checksum = "9fa08315bb612088cc391249efdc3bc77536f16c91f6cf495e6fbe85b20a4a81" 287 + dependencies = [ 288 + "futures-core", 289 + "futures-macro", 290 + "futures-sink", 291 + "futures-task", 292 + "pin-project-lite", 293 + "pin-utils", 294 + "slab", 295 + ] 296 + 297 + [[package]] 298 + name = "getrandom" 299 + version = "0.2.17" 300 + source = "registry+https://github.com/rust-lang/crates.io-index" 301 + checksum = "ff2abc00be7fca6ebc474524697ae276ad847ad0a6b3faa4bcb027e9a4614ad0" 302 + dependencies = [ 303 + "cfg-if", 304 + "libc", 305 + "wasi", 306 + ] 307 + 308 + [[package]] 309 + name = "glob" 310 + version = "0.3.3" 311 + source = "registry+https://github.com/rust-lang/crates.io-index" 312 + checksum = "0cc23270f6e1808e30a928bdc84dea0b9b4136a8bc82338574f23baf47bbd280" 313 + 314 + [[package]] 315 + name = "h2" 316 + version = "0.4.13" 317 + source = "registry+https://github.com/rust-lang/crates.io-index" 318 + checksum = "2f44da3a8150a6703ed5d34e164b875fd14c2cdab9af1252a9a1020bde2bdc54" 319 + dependencies = [ 320 + "atomic-waker", 321 + "bytes", 322 + "fnv", 323 + "futures-core", 324 + "futures-sink", 325 + "http", 326 + "indexmap 2.13.0", 327 + "slab", 328 + "tokio", 329 + "tokio-util", 330 + "tracing", 331 + ] 332 + 333 + [[package]] 334 + name = "hashbrown" 335 + version = "0.12.3" 336 + source = "registry+https://github.com/rust-lang/crates.io-index" 337 + checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" 338 + 339 + [[package]] 340 + name = "hashbrown" 341 + version = "0.16.1" 342 + source = "registry+https://github.com/rust-lang/crates.io-index" 343 + checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" 344 + 345 + [[package]] 346 + name = "http" 347 + version = "1.4.0" 348 + source = "registry+https://github.com/rust-lang/crates.io-index" 349 + checksum = "e3ba2a386d7f85a81f119ad7498ebe444d2e22c2af0b86b069416ace48b3311a" 350 + dependencies = [ 351 + "bytes", 352 + "itoa", 353 + ] 354 + 355 + [[package]] 356 + name = "http-body" 357 + version = "1.0.1" 358 + source = "registry+https://github.com/rust-lang/crates.io-index" 359 + checksum = "1efedce1fb8e6913f23e0c92de8e62cd5b772a67e7b3946df930a62566c93184" 360 + dependencies = [ 361 + "bytes", 362 + "http", 363 + ] 364 + 365 + [[package]] 366 + name = "http-body-util" 367 + version = "0.1.3" 368 + source = "registry+https://github.com/rust-lang/crates.io-index" 369 + checksum = "b021d93e26becf5dc7e1b75b1bed1fd93124b374ceb73f43d4d4eafec896a64a" 370 + dependencies = [ 371 + "bytes", 372 + "futures-core", 373 + "http", 374 + "http-body", 375 + "pin-project-lite", 376 + ] 377 + 378 + [[package]] 379 + name = "httparse" 380 + version = "1.10.1" 381 + source = "registry+https://github.com/rust-lang/crates.io-index" 382 + checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87" 383 + 384 + [[package]] 385 + name = "httpdate" 386 + version = "1.0.3" 387 + source = "registry+https://github.com/rust-lang/crates.io-index" 388 + checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" 389 + 390 + [[package]] 391 + name = "hyper" 392 + version = "1.8.1" 393 + source = "registry+https://github.com/rust-lang/crates.io-index" 394 + checksum = "2ab2d4f250c3d7b1c9fcdff1cece94ea4e2dfbec68614f7b87cb205f24ca9d11" 395 + dependencies = [ 396 + "atomic-waker", 397 + "bytes", 398 + "futures-channel", 399 + "futures-core", 400 + "h2", 401 + "http", 402 + "http-body", 403 + "httparse", 404 + "httpdate", 405 + "itoa", 406 + "pin-project-lite", 407 + "pin-utils", 408 + "smallvec", 409 + "tokio", 410 + "want", 411 + ] 412 + 413 + [[package]] 414 + name = "hyper-timeout" 415 + version = "0.5.2" 416 + source = "registry+https://github.com/rust-lang/crates.io-index" 417 + checksum = "2b90d566bffbce6a75bd8b09a05aa8c2cb1fabb6cb348f8840c9e4c90a0d83b0" 418 + dependencies = [ 419 + "hyper", 420 + "hyper-util", 421 + "pin-project-lite", 422 + "tokio", 423 + "tower-service", 424 + ] 425 + 426 + [[package]] 427 + name = "hyper-util" 428 + version = "0.1.19" 429 + source = "registry+https://github.com/rust-lang/crates.io-index" 430 + checksum = "727805d60e7938b76b826a6ef209eb70eaa1812794f9424d4a4e2d740662df5f" 431 + dependencies = [ 432 + "bytes", 433 + "futures-channel", 434 + "futures-core", 435 + "futures-util", 436 + "http", 437 + "http-body", 438 + "hyper", 439 + "libc", 440 + "pin-project-lite", 441 + "socket2 0.6.2", 442 + "tokio", 443 + "tower-service", 444 + "tracing", 445 + ] 446 + 447 + [[package]] 448 + name = "iana-time-zone" 449 + version = "0.1.65" 450 + source = "registry+https://github.com/rust-lang/crates.io-index" 451 + checksum = "e31bc9ad994ba00e440a8aa5c9ef0ec67d5cb5e5cb0cc7f8b744a35b389cc470" 452 + dependencies = [ 453 + "android_system_properties", 454 + "core-foundation-sys", 455 + "iana-time-zone-haiku", 456 + "js-sys", 457 + "log", 458 + "wasm-bindgen", 459 + "windows-core", 460 + ] 461 + 462 + [[package]] 463 + name = "iana-time-zone-haiku" 464 + version = "0.1.2" 465 + source = "registry+https://github.com/rust-lang/crates.io-index" 466 + checksum = "f31827a206f56af32e590ba56d5d2d085f558508192593743f16b2306495269f" 467 + dependencies = [ 468 + "cc", 469 + ] 470 + 471 + [[package]] 472 + name = "indexmap" 473 + version = "1.9.3" 474 + source = "registry+https://github.com/rust-lang/crates.io-index" 475 + checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" 476 + dependencies = [ 477 + "autocfg", 478 + "hashbrown 0.12.3", 479 + ] 480 + 481 + [[package]] 482 + name = "indexmap" 483 + version = "2.13.0" 484 + source = "registry+https://github.com/rust-lang/crates.io-index" 485 + checksum = "7714e70437a7dc3ac8eb7e6f8df75fd8eb422675fc7678aff7364301092b1017" 486 + dependencies = [ 487 + "equivalent", 488 + "hashbrown 0.16.1", 489 + ] 490 + 491 + [[package]] 492 + name = "itertools" 493 + version = "0.14.0" 494 + source = "registry+https://github.com/rust-lang/crates.io-index" 495 + checksum = "2b192c782037fadd9cfa75548310488aabdbf3d2da73885b31bd0abd03351285" 496 + dependencies = [ 497 + "either", 498 + ] 499 + 500 + [[package]] 501 + name = "itoa" 502 + version = "1.0.17" 503 + source = "registry+https://github.com/rust-lang/crates.io-index" 504 + checksum = "92ecc6618181def0457392ccd0ee51198e065e016d1d527a7ac1b6dc7c1f09d2" 505 + 506 + [[package]] 507 + name = "js-sys" 508 + version = "0.3.85" 509 + source = "registry+https://github.com/rust-lang/crates.io-index" 510 + checksum = "8c942ebf8e95485ca0d52d97da7c5a2c387d0e7f0ba4c35e93bfcaee045955b3" 511 + dependencies = [ 512 + "once_cell", 513 + "wasm-bindgen", 514 + ] 515 + 516 + [[package]] 517 + name = "lazy_static" 518 + version = "1.5.0" 519 + source = "registry+https://github.com/rust-lang/crates.io-index" 520 + checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" 521 + 522 + [[package]] 523 + name = "libc" 524 + version = "0.2.180" 525 + source = "registry+https://github.com/rust-lang/crates.io-index" 526 + checksum = "bcc35a38544a891a5f7c865aca548a982ccb3b8650a5b06d0fd33a10283c56fc" 527 + 528 + [[package]] 529 + name = "lock_api" 530 + version = "0.4.14" 531 + source = "registry+https://github.com/rust-lang/crates.io-index" 532 + checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" 533 + dependencies = [ 534 + "scopeguard", 535 + ] 536 + 537 + [[package]] 538 + name = "log" 539 + version = "0.4.29" 540 + source = "registry+https://github.com/rust-lang/crates.io-index" 541 + checksum = "5e5032e24019045c762d3c0f28f5b6b8bbf38563a65908389bf7978758920897" 542 + 543 + [[package]] 544 + name = "matchers" 545 + version = "0.2.0" 546 + source = "registry+https://github.com/rust-lang/crates.io-index" 547 + checksum = "d1525a2a28c7f4fa0fc98bb91ae755d1e2d1505079e05539e35bc876b5d65ae9" 548 + dependencies = [ 549 + "regex-automata", 550 + ] 551 + 552 + [[package]] 553 + name = "matchit" 554 + version = "0.7.3" 555 + source = "registry+https://github.com/rust-lang/crates.io-index" 556 + checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" 557 + 558 + [[package]] 559 + name = "memchr" 560 + version = "2.7.6" 561 + source = "registry+https://github.com/rust-lang/crates.io-index" 562 + checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" 563 + 564 + [[package]] 565 + name = "mime" 566 + version = "0.3.17" 567 + source = "registry+https://github.com/rust-lang/crates.io-index" 568 + checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" 569 + 570 + [[package]] 571 + name = "mio" 572 + version = "1.1.1" 573 + source = "registry+https://github.com/rust-lang/crates.io-index" 574 + checksum = "a69bcab0ad47271a0234d9422b131806bf3968021e5dc9328caf2d4cd58557fc" 575 + dependencies = [ 576 + "libc", 577 + "wasi", 578 + "windows-sys 0.61.2", 579 + ] 580 + 581 + [[package]] 582 + name = "nu-ansi-term" 583 + version = "0.50.3" 584 + source = "registry+https://github.com/rust-lang/crates.io-index" 585 + checksum = "7957b9740744892f114936ab4a57b3f487491bbeafaf8083688b16841a4240e5" 586 + dependencies = [ 587 + "windows-sys 0.61.2", 588 + ] 589 + 590 + [[package]] 591 + name = "num-traits" 592 + version = "0.2.19" 593 + source = "registry+https://github.com/rust-lang/crates.io-index" 594 + checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" 595 + dependencies = [ 596 + "autocfg", 597 + ] 598 + 599 + [[package]] 600 + name = "once_cell" 601 + version = "1.21.3" 602 + source = "registry+https://github.com/rust-lang/crates.io-index" 603 + checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" 604 + 605 + [[package]] 606 + name = "opentelemetry" 607 + version = "0.27.1" 608 + source = "registry+https://github.com/rust-lang/crates.io-index" 609 + checksum = "ab70038c28ed37b97d8ed414b6429d343a8bbf44c9f79ec854f3a643029ba6d7" 610 + dependencies = [ 611 + "futures-core", 612 + "futures-sink", 613 + "js-sys", 614 + "pin-project-lite", 615 + "thiserror", 616 + "tracing", 617 + ] 618 + 619 + [[package]] 620 + name = "opentelemetry-otlp" 621 + version = "0.27.0" 622 + source = "registry+https://github.com/rust-lang/crates.io-index" 623 + checksum = "91cf61a1868dacc576bf2b2a1c3e9ab150af7272909e80085c3173384fe11f76" 624 + dependencies = [ 625 + "async-trait", 626 + "futures-core", 627 + "http", 628 + "opentelemetry", 629 + "opentelemetry-proto", 630 + "opentelemetry_sdk", 631 + "prost", 632 + "thiserror", 633 + "tokio", 634 + "tonic", 635 + "tracing", 636 + ] 637 + 638 + [[package]] 639 + name = "opentelemetry-proto" 640 + version = "0.27.0" 641 + source = "registry+https://github.com/rust-lang/crates.io-index" 642 + checksum = "a6e05acbfada5ec79023c85368af14abd0b307c015e9064d249b2a950ef459a6" 643 + dependencies = [ 644 + "opentelemetry", 645 + "opentelemetry_sdk", 646 + "prost", 647 + "tonic", 648 + ] 649 + 650 + [[package]] 651 + name = "opentelemetry_sdk" 652 + version = "0.27.1" 653 + source = "registry+https://github.com/rust-lang/crates.io-index" 654 + checksum = "231e9d6ceef9b0b2546ddf52335785ce41252bc7474ee8ba05bfad277be13ab8" 655 + dependencies = [ 656 + "async-trait", 657 + "futures-channel", 658 + "futures-executor", 659 + "futures-util", 660 + "glob", 661 + "opentelemetry", 662 + "percent-encoding", 663 + "rand", 664 + "serde_json", 665 + "thiserror", 666 + "tokio", 667 + "tokio-stream", 668 + "tracing", 669 + ] 670 + 671 + [[package]] 672 + name = "parking_lot" 673 + version = "0.12.5" 674 + source = "registry+https://github.com/rust-lang/crates.io-index" 675 + checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" 676 + dependencies = [ 677 + "lock_api", 678 + "parking_lot_core", 679 + ] 680 + 681 + [[package]] 682 + name = "parking_lot_core" 683 + version = "0.9.12" 684 + source = "registry+https://github.com/rust-lang/crates.io-index" 685 + checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" 686 + dependencies = [ 687 + "cfg-if", 688 + "libc", 689 + "redox_syscall", 690 + "smallvec", 691 + "windows-link", 692 + ] 693 + 694 + [[package]] 695 + name = "percent-encoding" 696 + version = "2.3.2" 697 + source = "registry+https://github.com/rust-lang/crates.io-index" 698 + checksum = "9b4f627cb1b25917193a259e49bdad08f671f8d9708acfd5fe0a8c1455d87220" 699 + 700 + [[package]] 701 + name = "pin-project" 702 + version = "1.1.10" 703 + source = "registry+https://github.com/rust-lang/crates.io-index" 704 + checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" 705 + dependencies = [ 706 + "pin-project-internal", 707 + ] 708 + 709 + [[package]] 710 + name = "pin-project-internal" 711 + version = "1.1.10" 712 + source = "registry+https://github.com/rust-lang/crates.io-index" 713 + checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" 714 + dependencies = [ 715 + "proc-macro2", 716 + "quote", 717 + "syn", 718 + ] 719 + 720 + [[package]] 721 + name = "pin-project-lite" 722 + version = "0.2.16" 723 + source = "registry+https://github.com/rust-lang/crates.io-index" 724 + checksum = "3b3cff922bd51709b605d9ead9aa71031d81447142d828eb4a6eba76fe619f9b" 725 + 726 + [[package]] 727 + name = "pin-utils" 728 + version = "0.1.0" 729 + source = "registry+https://github.com/rust-lang/crates.io-index" 730 + checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" 731 + 732 + [[package]] 733 + name = "ppv-lite86" 734 + version = "0.2.21" 735 + source = "registry+https://github.com/rust-lang/crates.io-index" 736 + checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 737 + dependencies = [ 738 + "zerocopy", 739 + ] 740 + 741 + [[package]] 742 + name = "proc-macro2" 743 + version = "1.0.106" 744 + source = "registry+https://github.com/rust-lang/crates.io-index" 745 + checksum = "8fd00f0bb2e90d81d1044c2b32617f68fcb9fa3bb7640c23e9c748e53fb30934" 746 + dependencies = [ 747 + "unicode-ident", 748 + ] 749 + 750 + [[package]] 751 + name = "prost" 752 + version = "0.13.5" 753 + source = "registry+https://github.com/rust-lang/crates.io-index" 754 + checksum = "2796faa41db3ec313a31f7624d9286acf277b52de526150b7e69f3debf891ee5" 755 + dependencies = [ 756 + "bytes", 757 + "prost-derive", 758 + ] 759 + 760 + [[package]] 761 + name = "prost-derive" 762 + version = "0.13.5" 763 + source = "registry+https://github.com/rust-lang/crates.io-index" 764 + checksum = "8a56d757972c98b346a9b766e3f02746cde6dd1cd1d1d563472929fdd74bec4d" 765 + dependencies = [ 766 + "anyhow", 767 + "itertools", 768 + "proc-macro2", 769 + "quote", 770 + "syn", 771 + ] 772 + 773 + [[package]] 774 + name = "quote" 775 + version = "1.0.44" 776 + source = "registry+https://github.com/rust-lang/crates.io-index" 777 + checksum = "21b2ebcf727b7760c461f091f9f0f539b77b8e87f2fd88131e7f1b433b3cece4" 778 + dependencies = [ 779 + "proc-macro2", 780 + ] 781 + 782 + [[package]] 783 + name = "rand" 784 + version = "0.8.5" 785 + source = "registry+https://github.com/rust-lang/crates.io-index" 786 + checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" 787 + dependencies = [ 788 + "libc", 789 + "rand_chacha", 790 + "rand_core", 791 + ] 792 + 793 + [[package]] 794 + name = "rand_chacha" 795 + version = "0.3.1" 796 + source = "registry+https://github.com/rust-lang/crates.io-index" 797 + checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" 798 + dependencies = [ 799 + "ppv-lite86", 800 + "rand_core", 801 + ] 802 + 803 + [[package]] 804 + name = "rand_core" 805 + version = "0.6.4" 806 + source = "registry+https://github.com/rust-lang/crates.io-index" 807 + checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" 808 + dependencies = [ 809 + "getrandom", 810 + ] 811 + 812 + [[package]] 813 + name = "redox_syscall" 814 + version = "0.5.18" 815 + source = "registry+https://github.com/rust-lang/crates.io-index" 816 + checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" 817 + dependencies = [ 818 + "bitflags", 819 + ] 820 + 821 + [[package]] 822 + name = "regex" 823 + version = "1.12.2" 824 + source = "registry+https://github.com/rust-lang/crates.io-index" 825 + checksum = "843bc0191f75f3e22651ae5f1e72939ab2f72a4bc30fa80a066bd66edefc24d4" 826 + dependencies = [ 827 + "aho-corasick", 828 + "memchr", 829 + "regex-automata", 830 + "regex-syntax", 831 + ] 832 + 833 + [[package]] 834 + name = "regex-automata" 835 + version = "0.4.13" 836 + source = "registry+https://github.com/rust-lang/crates.io-index" 837 + checksum = "5276caf25ac86c8d810222b3dbb938e512c55c6831a10f3e6ed1c93b84041f1c" 838 + dependencies = [ 839 + "aho-corasick", 840 + "memchr", 841 + "regex-syntax", 842 + ] 843 + 844 + [[package]] 845 + name = "regex-syntax" 846 + version = "0.8.8" 847 + source = "registry+https://github.com/rust-lang/crates.io-index" 848 + checksum = "7a2d987857b319362043e95f5353c0535c1f58eec5336fdfcf626430af7def58" 849 + 850 + [[package]] 851 + name = "rustversion" 852 + version = "1.0.22" 853 + source = "registry+https://github.com/rust-lang/crates.io-index" 854 + checksum = "b39cdef0fa800fc44525c84ccb54a029961a8215f9619753635a9c0d2538d46d" 855 + 856 + [[package]] 857 + name = "scopeguard" 858 + version = "1.2.0" 859 + source = "registry+https://github.com/rust-lang/crates.io-index" 860 + checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 861 + 862 + [[package]] 863 + name = "serde" 864 + version = "1.0.228" 865 + source = "registry+https://github.com/rust-lang/crates.io-index" 866 + checksum = "9a8e94ea7f378bd32cbbd37198a4a91436180c5bb472411e48b5ec2e2124ae9e" 867 + dependencies = [ 868 + "serde_core", 869 + "serde_derive", 870 + ] 871 + 872 + [[package]] 873 + name = "serde_core" 874 + version = "1.0.228" 875 + source = "registry+https://github.com/rust-lang/crates.io-index" 876 + checksum = "41d385c7d4ca58e59fc732af25c3983b67ac852c1a25000afe1175de458b67ad" 877 + dependencies = [ 878 + "serde_derive", 879 + ] 880 + 881 + [[package]] 882 + name = "serde_derive" 883 + version = "1.0.228" 884 + source = "registry+https://github.com/rust-lang/crates.io-index" 885 + checksum = "d540f220d3187173da220f885ab66608367b6574e925011a9353e4badda91d79" 886 + dependencies = [ 887 + "proc-macro2", 888 + "quote", 889 + "syn", 890 + ] 891 + 892 + [[package]] 893 + name = "serde_json" 894 + version = "1.0.149" 895 + source = "registry+https://github.com/rust-lang/crates.io-index" 896 + checksum = "83fc039473c5595ace860d8c4fafa220ff474b3fc6bfdb4293327f1a37e94d86" 897 + dependencies = [ 898 + "itoa", 899 + "memchr", 900 + "serde", 901 + "serde_core", 902 + "zmij", 903 + ] 904 + 905 + [[package]] 906 + name = "sharded-slab" 907 + version = "0.1.7" 908 + source = "registry+https://github.com/rust-lang/crates.io-index" 909 + checksum = "f40ca3c46823713e0d4209592e8d6e826aa57e928f09752619fc696c499637f6" 910 + dependencies = [ 911 + "lazy_static", 912 + ] 913 + 914 + [[package]] 915 + name = "shlex" 916 + version = "1.3.0" 917 + source = "registry+https://github.com/rust-lang/crates.io-index" 918 + checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" 919 + 920 + [[package]] 921 + name = "signal-hook-registry" 922 + version = "1.4.8" 923 + source = "registry+https://github.com/rust-lang/crates.io-index" 924 + checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" 925 + dependencies = [ 926 + "errno", 927 + "libc", 928 + ] 929 + 930 + [[package]] 931 + name = "slab" 932 + version = "0.4.12" 933 + source = "registry+https://github.com/rust-lang/crates.io-index" 934 + checksum = "0c790de23124f9ab44544d7ac05d60440adc586479ce501c1d6d7da3cd8c9cf5" 935 + 936 + [[package]] 937 + name = "smallvec" 938 + version = "1.15.1" 939 + source = "registry+https://github.com/rust-lang/crates.io-index" 940 + checksum = "67b1b7a3b5fe4f1376887184045fcf45c69e92af734b7aaddc05fb777b6fbd03" 941 + 942 + [[package]] 943 + name = "socket2" 944 + version = "0.5.10" 945 + source = "registry+https://github.com/rust-lang/crates.io-index" 946 + checksum = "e22376abed350d73dd1cd119b57ffccad95b4e585a7cda43e286245ce23c0678" 947 + dependencies = [ 948 + "libc", 949 + "windows-sys 0.52.0", 950 + ] 951 + 952 + [[package]] 953 + name = "socket2" 954 + version = "0.6.2" 955 + source = "registry+https://github.com/rust-lang/crates.io-index" 956 + checksum = "86f4aa3ad99f2088c990dfa82d367e19cb29268ed67c574d10d0a4bfe71f07e0" 957 + dependencies = [ 958 + "libc", 959 + "windows-sys 0.60.2", 960 + ] 961 + 962 + [[package]] 963 + name = "syn" 964 + version = "2.0.114" 965 + source = "registry+https://github.com/rust-lang/crates.io-index" 966 + checksum = "d4d107df263a3013ef9b1879b0df87d706ff80f65a86ea879bd9c31f9b307c2a" 967 + dependencies = [ 968 + "proc-macro2", 969 + "quote", 970 + "unicode-ident", 971 + ] 972 + 973 + [[package]] 974 + name = "sync_wrapper" 975 + version = "1.0.2" 976 + source = "registry+https://github.com/rust-lang/crates.io-index" 977 + checksum = "0bf256ce5efdfa370213c1dabab5935a12e49f2c58d15e9eac2870d3b4f27263" 978 + 979 + [[package]] 980 + name = "thiserror" 981 + version = "1.0.69" 982 + source = "registry+https://github.com/rust-lang/crates.io-index" 983 + checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52" 984 + dependencies = [ 985 + "thiserror-impl", 986 + ] 987 + 988 + [[package]] 989 + name = "thiserror-impl" 990 + version = "1.0.69" 991 + source = "registry+https://github.com/rust-lang/crates.io-index" 992 + checksum = "4fee6c4efc90059e10f81e6d42c60a18f76588c3d74cb83a0b242a2b6c7504c1" 993 + dependencies = [ 994 + "proc-macro2", 995 + "quote", 996 + "syn", 997 + ] 998 + 999 + [[package]] 1000 + name = "thread_local" 1001 + version = "1.1.9" 1002 + source = "registry+https://github.com/rust-lang/crates.io-index" 1003 + checksum = "f60246a4944f24f6e018aa17cdeffb7818b76356965d03b07d6a9886e8962185" 1004 + dependencies = [ 1005 + "cfg-if", 1006 + ] 1007 + 1008 + [[package]] 1009 + name = "tokio" 1010 + version = "1.49.0" 1011 + source = "registry+https://github.com/rust-lang/crates.io-index" 1012 + checksum = "72a2903cd7736441aac9df9d7688bd0ce48edccaadf181c3b90be801e81d3d86" 1013 + dependencies = [ 1014 + "bytes", 1015 + "libc", 1016 + "mio", 1017 + "parking_lot", 1018 + "pin-project-lite", 1019 + "signal-hook-registry", 1020 + "socket2 0.6.2", 1021 + "tokio-macros", 1022 + "windows-sys 0.61.2", 1023 + ] 1024 + 1025 + [[package]] 1026 + name = "tokio-macros" 1027 + version = "2.6.0" 1028 + source = "registry+https://github.com/rust-lang/crates.io-index" 1029 + checksum = "af407857209536a95c8e56f8231ef2c2e2aff839b22e07a1ffcbc617e9db9fa5" 1030 + dependencies = [ 1031 + "proc-macro2", 1032 + "quote", 1033 + "syn", 1034 + ] 1035 + 1036 + [[package]] 1037 + name = "tokio-stream" 1038 + version = "0.1.18" 1039 + source = "registry+https://github.com/rust-lang/crates.io-index" 1040 + checksum = "32da49809aab5c3bc678af03902d4ccddea2a87d028d86392a4b1560c6906c70" 1041 + dependencies = [ 1042 + "futures-core", 1043 + "pin-project-lite", 1044 + "tokio", 1045 + ] 1046 + 1047 + [[package]] 1048 + name = "tokio-util" 1049 + version = "0.7.18" 1050 + source = "registry+https://github.com/rust-lang/crates.io-index" 1051 + checksum = "9ae9cec805b01e8fc3fd2fe289f89149a9b66dd16786abd8b19cfa7b48cb0098" 1052 + dependencies = [ 1053 + "bytes", 1054 + "futures-core", 1055 + "futures-sink", 1056 + "pin-project-lite", 1057 + "tokio", 1058 + ] 1059 + 1060 + [[package]] 1061 + name = "tonic" 1062 + version = "0.12.3" 1063 + source = "registry+https://github.com/rust-lang/crates.io-index" 1064 + checksum = "877c5b330756d856ffcc4553ab34a5684481ade925ecc54bcd1bf02b1d0d4d52" 1065 + dependencies = [ 1066 + "async-stream", 1067 + "async-trait", 1068 + "axum", 1069 + "base64", 1070 + "bytes", 1071 + "h2", 1072 + "http", 1073 + "http-body", 1074 + "http-body-util", 1075 + "hyper", 1076 + "hyper-timeout", 1077 + "hyper-util", 1078 + "percent-encoding", 1079 + "pin-project", 1080 + "prost", 1081 + "socket2 0.5.10", 1082 + "tokio", 1083 + "tokio-stream", 1084 + "tower 0.4.13", 1085 + "tower-layer", 1086 + "tower-service", 1087 + "tracing", 1088 + ] 1089 + 1090 + [[package]] 1091 + name = "tower" 1092 + version = "0.4.13" 1093 + source = "registry+https://github.com/rust-lang/crates.io-index" 1094 + checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" 1095 + dependencies = [ 1096 + "futures-core", 1097 + "futures-util", 1098 + "indexmap 1.9.3", 1099 + "pin-project", 1100 + "pin-project-lite", 1101 + "rand", 1102 + "slab", 1103 + "tokio", 1104 + "tokio-util", 1105 + "tower-layer", 1106 + "tower-service", 1107 + "tracing", 1108 + ] 1109 + 1110 + [[package]] 1111 + name = "tower" 1112 + version = "0.5.3" 1113 + source = "registry+https://github.com/rust-lang/crates.io-index" 1114 + checksum = "ebe5ef63511595f1344e2d5cfa636d973292adc0eec1f0ad45fae9f0851ab1d4" 1115 + dependencies = [ 1116 + "futures-core", 1117 + "futures-util", 1118 + "pin-project-lite", 1119 + "sync_wrapper", 1120 + "tower-layer", 1121 + "tower-service", 1122 + ] 1123 + 1124 + [[package]] 1125 + name = "tower-layer" 1126 + version = "0.3.3" 1127 + source = "registry+https://github.com/rust-lang/crates.io-index" 1128 + checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 1129 + 1130 + [[package]] 1131 + name = "tower-service" 1132 + version = "0.3.3" 1133 + source = "registry+https://github.com/rust-lang/crates.io-index" 1134 + checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 1135 + 1136 + [[package]] 1137 + name = "tracing" 1138 + version = "0.1.44" 1139 + source = "registry+https://github.com/rust-lang/crates.io-index" 1140 + checksum = "63e71662fa4b2a2c3a26f570f037eb95bb1f85397f3cd8076caed2f026a6d100" 1141 + dependencies = [ 1142 + "pin-project-lite", 1143 + "tracing-attributes", 1144 + "tracing-core", 1145 + ] 1146 + 1147 + [[package]] 1148 + name = "tracing-attributes" 1149 + version = "0.1.31" 1150 + source = "registry+https://github.com/rust-lang/crates.io-index" 1151 + checksum = "7490cfa5ec963746568740651ac6781f701c9c5ea257c58e057f3ba8cf69e8da" 1152 + dependencies = [ 1153 + "proc-macro2", 1154 + "quote", 1155 + "syn", 1156 + ] 1157 + 1158 + [[package]] 1159 + name = "tracing-core" 1160 + version = "0.1.36" 1161 + source = "registry+https://github.com/rust-lang/crates.io-index" 1162 + checksum = "db97caf9d906fbde555dd62fa95ddba9eecfd14cb388e4f491a66d74cd5fb79a" 1163 + dependencies = [ 1164 + "once_cell", 1165 + "valuable", 1166 + ] 1167 + 1168 + [[package]] 1169 + name = "tracing-log" 1170 + version = "0.2.0" 1171 + source = "registry+https://github.com/rust-lang/crates.io-index" 1172 + checksum = "ee855f1f400bd0e5c02d150ae5de3840039a3f54b025156404e34c23c03f47c3" 1173 + dependencies = [ 1174 + "log", 1175 + "once_cell", 1176 + "tracing-core", 1177 + ] 1178 + 1179 + [[package]] 1180 + name = "tracing-opentelemetry" 1181 + version = "0.28.0" 1182 + source = "registry+https://github.com/rust-lang/crates.io-index" 1183 + checksum = "97a971f6058498b5c0f1affa23e7ea202057a7301dbff68e968b2d578bcbd053" 1184 + dependencies = [ 1185 + "js-sys", 1186 + "once_cell", 1187 + "opentelemetry", 1188 + "opentelemetry_sdk", 1189 + "smallvec", 1190 + "tracing", 1191 + "tracing-core", 1192 + "tracing-log", 1193 + "tracing-subscriber", 1194 + "web-time", 1195 + ] 1196 + 1197 + [[package]] 1198 + name = "tracing-subscriber" 1199 + version = "0.3.22" 1200 + source = "registry+https://github.com/rust-lang/crates.io-index" 1201 + checksum = "2f30143827ddab0d256fd843b7a66d164e9f271cfa0dde49142c5ca0ca291f1e" 1202 + dependencies = [ 1203 + "matchers", 1204 + "nu-ansi-term", 1205 + "once_cell", 1206 + "regex-automata", 1207 + "sharded-slab", 1208 + "smallvec", 1209 + "thread_local", 1210 + "tracing", 1211 + "tracing-core", 1212 + "tracing-log", 1213 + ] 1214 + 1215 + [[package]] 1216 + name = "try-lock" 1217 + version = "0.2.5" 1218 + source = "registry+https://github.com/rust-lang/crates.io-index" 1219 + checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" 1220 + 1221 + [[package]] 1222 + name = "unicode-ident" 1223 + version = "1.0.22" 1224 + source = "registry+https://github.com/rust-lang/crates.io-index" 1225 + checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" 1226 + 1227 + [[package]] 1228 + name = "valuable" 1229 + version = "0.1.1" 1230 + source = "registry+https://github.com/rust-lang/crates.io-index" 1231 + checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" 1232 + 1233 + [[package]] 1234 + name = "want" 1235 + version = "0.3.1" 1236 + source = "registry+https://github.com/rust-lang/crates.io-index" 1237 + checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" 1238 + dependencies = [ 1239 + "try-lock", 1240 + ] 1241 + 1242 + [[package]] 1243 + name = "wasi" 1244 + version = "0.11.1+wasi-snapshot-preview1" 1245 + source = "registry+https://github.com/rust-lang/crates.io-index" 1246 + checksum = "ccf3ec651a847eb01de73ccad15eb7d99f80485de043efb2f370cd654f4ea44b" 1247 + 1248 + [[package]] 1249 + name = "wasm-bindgen" 1250 + version = "0.2.108" 1251 + source = "registry+https://github.com/rust-lang/crates.io-index" 1252 + checksum = "64024a30ec1e37399cf85a7ffefebdb72205ca1c972291c51512360d90bd8566" 1253 + dependencies = [ 1254 + "cfg-if", 1255 + "once_cell", 1256 + "rustversion", 1257 + "wasm-bindgen-macro", 1258 + "wasm-bindgen-shared", 1259 + ] 1260 + 1261 + [[package]] 1262 + name = "wasm-bindgen-macro" 1263 + version = "0.2.108" 1264 + source = "registry+https://github.com/rust-lang/crates.io-index" 1265 + checksum = "008b239d9c740232e71bd39e8ef6429d27097518b6b30bdf9086833bd5b6d608" 1266 + dependencies = [ 1267 + "quote", 1268 + "wasm-bindgen-macro-support", 1269 + ] 1270 + 1271 + [[package]] 1272 + name = "wasm-bindgen-macro-support" 1273 + version = "0.2.108" 1274 + source = "registry+https://github.com/rust-lang/crates.io-index" 1275 + checksum = "5256bae2d58f54820e6490f9839c49780dff84c65aeab9e772f15d5f0e913a55" 1276 + dependencies = [ 1277 + "bumpalo", 1278 + "proc-macro2", 1279 + "quote", 1280 + "syn", 1281 + "wasm-bindgen-shared", 1282 + ] 1283 + 1284 + [[package]] 1285 + name = "wasm-bindgen-shared" 1286 + version = "0.2.108" 1287 + source = "registry+https://github.com/rust-lang/crates.io-index" 1288 + checksum = "1f01b580c9ac74c8d8f0c0e4afb04eeef2acf145458e52c03845ee9cd23e3d12" 1289 + dependencies = [ 1290 + "unicode-ident", 1291 + ] 1292 + 1293 + [[package]] 1294 + name = "web-time" 1295 + version = "1.1.0" 1296 + source = "registry+https://github.com/rust-lang/crates.io-index" 1297 + checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 1298 + dependencies = [ 1299 + "js-sys", 1300 + "wasm-bindgen", 1301 + ] 1302 + 1303 + [[package]] 1304 + name = "windows-core" 1305 + version = "0.62.2" 1306 + source = "registry+https://github.com/rust-lang/crates.io-index" 1307 + checksum = "b8e83a14d34d0623b51dce9581199302a221863196a1dde71a7663a4c2be9deb" 1308 + dependencies = [ 1309 + "windows-implement", 1310 + "windows-interface", 1311 + "windows-link", 1312 + "windows-result", 1313 + "windows-strings", 1314 + ] 1315 + 1316 + [[package]] 1317 + name = "windows-implement" 1318 + version = "0.60.2" 1319 + source = "registry+https://github.com/rust-lang/crates.io-index" 1320 + checksum = "053e2e040ab57b9dc951b72c264860db7eb3b0200ba345b4e4c3b14f67855ddf" 1321 + dependencies = [ 1322 + "proc-macro2", 1323 + "quote", 1324 + "syn", 1325 + ] 1326 + 1327 + [[package]] 1328 + name = "windows-interface" 1329 + version = "0.59.3" 1330 + source = "registry+https://github.com/rust-lang/crates.io-index" 1331 + checksum = "3f316c4a2570ba26bbec722032c4099d8c8bc095efccdc15688708623367e358" 1332 + dependencies = [ 1333 + "proc-macro2", 1334 + "quote", 1335 + "syn", 1336 + ] 1337 + 1338 + [[package]] 1339 + name = "windows-link" 1340 + version = "0.2.1" 1341 + source = "registry+https://github.com/rust-lang/crates.io-index" 1342 + checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" 1343 + 1344 + [[package]] 1345 + name = "windows-result" 1346 + version = "0.4.1" 1347 + source = "registry+https://github.com/rust-lang/crates.io-index" 1348 + checksum = "7781fa89eaf60850ac3d2da7af8e5242a5ea78d1a11c49bf2910bb5a73853eb5" 1349 + dependencies = [ 1350 + "windows-link", 1351 + ] 1352 + 1353 + [[package]] 1354 + name = "windows-strings" 1355 + version = "0.5.1" 1356 + source = "registry+https://github.com/rust-lang/crates.io-index" 1357 + checksum = "7837d08f69c77cf6b07689544538e017c1bfcf57e34b4c0ff58e6c2cd3b37091" 1358 + dependencies = [ 1359 + "windows-link", 1360 + ] 1361 + 1362 + [[package]] 1363 + name = "windows-sys" 1364 + version = "0.52.0" 1365 + source = "registry+https://github.com/rust-lang/crates.io-index" 1366 + checksum = "282be5f36a8ce781fad8c8ae18fa3f9beff57ec1b52cb3de0789201425d9a33d" 1367 + dependencies = [ 1368 + "windows-targets 0.52.6", 1369 + ] 1370 + 1371 + [[package]] 1372 + name = "windows-sys" 1373 + version = "0.60.2" 1374 + source = "registry+https://github.com/rust-lang/crates.io-index" 1375 + checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb" 1376 + dependencies = [ 1377 + "windows-targets 0.53.5", 1378 + ] 1379 + 1380 + [[package]] 1381 + name = "windows-sys" 1382 + version = "0.61.2" 1383 + source = "registry+https://github.com/rust-lang/crates.io-index" 1384 + checksum = "ae137229bcbd6cdf0f7b80a31df61766145077ddf49416a728b02cb3921ff3fc" 1385 + dependencies = [ 1386 + "windows-link", 1387 + ] 1388 + 1389 + [[package]] 1390 + name = "windows-targets" 1391 + version = "0.52.6" 1392 + source = "registry+https://github.com/rust-lang/crates.io-index" 1393 + checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 1394 + dependencies = [ 1395 + "windows_aarch64_gnullvm 0.52.6", 1396 + "windows_aarch64_msvc 0.52.6", 1397 + "windows_i686_gnu 0.52.6", 1398 + "windows_i686_gnullvm 0.52.6", 1399 + "windows_i686_msvc 0.52.6", 1400 + "windows_x86_64_gnu 0.52.6", 1401 + "windows_x86_64_gnullvm 0.52.6", 1402 + "windows_x86_64_msvc 0.52.6", 1403 + ] 1404 + 1405 + [[package]] 1406 + name = "windows-targets" 1407 + version = "0.53.5" 1408 + source = "registry+https://github.com/rust-lang/crates.io-index" 1409 + checksum = "4945f9f551b88e0d65f3db0bc25c33b8acea4d9e41163edf90dcd0b19f9069f3" 1410 + dependencies = [ 1411 + "windows-link", 1412 + "windows_aarch64_gnullvm 0.53.1", 1413 + "windows_aarch64_msvc 0.53.1", 1414 + "windows_i686_gnu 0.53.1", 1415 + "windows_i686_gnullvm 0.53.1", 1416 + "windows_i686_msvc 0.53.1", 1417 + "windows_x86_64_gnu 0.53.1", 1418 + "windows_x86_64_gnullvm 0.53.1", 1419 + "windows_x86_64_msvc 0.53.1", 1420 + ] 1421 + 1422 + [[package]] 1423 + name = "windows_aarch64_gnullvm" 1424 + version = "0.52.6" 1425 + source = "registry+https://github.com/rust-lang/crates.io-index" 1426 + checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 1427 + 1428 + [[package]] 1429 + name = "windows_aarch64_gnullvm" 1430 + version = "0.53.1" 1431 + source = "registry+https://github.com/rust-lang/crates.io-index" 1432 + checksum = "a9d8416fa8b42f5c947f8482c43e7d89e73a173cead56d044f6a56104a6d1b53" 1433 + 1434 + [[package]] 1435 + name = "windows_aarch64_msvc" 1436 + version = "0.52.6" 1437 + source = "registry+https://github.com/rust-lang/crates.io-index" 1438 + checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 1439 + 1440 + [[package]] 1441 + name = "windows_aarch64_msvc" 1442 + version = "0.53.1" 1443 + source = "registry+https://github.com/rust-lang/crates.io-index" 1444 + checksum = "b9d782e804c2f632e395708e99a94275910eb9100b2114651e04744e9b125006" 1445 + 1446 + [[package]] 1447 + name = "windows_i686_gnu" 1448 + version = "0.52.6" 1449 + source = "registry+https://github.com/rust-lang/crates.io-index" 1450 + checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 1451 + 1452 + [[package]] 1453 + name = "windows_i686_gnu" 1454 + version = "0.53.1" 1455 + source = "registry+https://github.com/rust-lang/crates.io-index" 1456 + checksum = "960e6da069d81e09becb0ca57a65220ddff016ff2d6af6a223cf372a506593a3" 1457 + 1458 + [[package]] 1459 + name = "windows_i686_gnullvm" 1460 + version = "0.52.6" 1461 + source = "registry+https://github.com/rust-lang/crates.io-index" 1462 + checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 1463 + 1464 + [[package]] 1465 + name = "windows_i686_gnullvm" 1466 + version = "0.53.1" 1467 + source = "registry+https://github.com/rust-lang/crates.io-index" 1468 + checksum = "fa7359d10048f68ab8b09fa71c3daccfb0e9b559aed648a8f95469c27057180c" 1469 + 1470 + [[package]] 1471 + name = "windows_i686_msvc" 1472 + version = "0.52.6" 1473 + source = "registry+https://github.com/rust-lang/crates.io-index" 1474 + checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 1475 + 1476 + [[package]] 1477 + name = "windows_i686_msvc" 1478 + version = "0.53.1" 1479 + source = "registry+https://github.com/rust-lang/crates.io-index" 1480 + checksum = "1e7ac75179f18232fe9c285163565a57ef8d3c89254a30685b57d83a38d326c2" 1481 + 1482 + [[package]] 1483 + name = "windows_x86_64_gnu" 1484 + version = "0.52.6" 1485 + source = "registry+https://github.com/rust-lang/crates.io-index" 1486 + checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 1487 + 1488 + [[package]] 1489 + name = "windows_x86_64_gnu" 1490 + version = "0.53.1" 1491 + source = "registry+https://github.com/rust-lang/crates.io-index" 1492 + checksum = "9c3842cdd74a865a8066ab39c8a7a473c0778a3f29370b5fd6b4b9aa7df4a499" 1493 + 1494 + [[package]] 1495 + name = "windows_x86_64_gnullvm" 1496 + version = "0.52.6" 1497 + source = "registry+https://github.com/rust-lang/crates.io-index" 1498 + checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 1499 + 1500 + [[package]] 1501 + name = "windows_x86_64_gnullvm" 1502 + version = "0.53.1" 1503 + source = "registry+https://github.com/rust-lang/crates.io-index" 1504 + checksum = "0ffa179e2d07eee8ad8f57493436566c7cc30ac536a3379fdf008f47f6bb7ae1" 1505 + 1506 + [[package]] 1507 + name = "windows_x86_64_msvc" 1508 + version = "0.52.6" 1509 + source = "registry+https://github.com/rust-lang/crates.io-index" 1510 + checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 1511 + 1512 + [[package]] 1513 + name = "windows_x86_64_msvc" 1514 + version = "0.53.1" 1515 + source = "registry+https://github.com/rust-lang/crates.io-index" 1516 + checksum = "d6bbff5f0aada427a1e5a6da5f1f98158182f26556f345ac9e04d36d0ebed650" 1517 + 1518 + [[package]] 1519 + name = "zerocopy" 1520 + version = "0.8.37" 1521 + source = "registry+https://github.com/rust-lang/crates.io-index" 1522 + checksum = "7456cf00f0685ad319c5b1693f291a650eaf345e941d082fc4e03df8a03996ac" 1523 + dependencies = [ 1524 + "zerocopy-derive", 1525 + ] 1526 + 1527 + [[package]] 1528 + name = "zerocopy-derive" 1529 + version = "0.8.37" 1530 + source = "registry+https://github.com/rust-lang/crates.io-index" 1531 + checksum = "1328722bbf2115db7e19d69ebcc15e795719e2d66b60827c6a69a117365e37a0" 1532 + dependencies = [ 1533 + "proc-macro2", 1534 + "quote", 1535 + "syn", 1536 + ] 1537 + 1538 + [[package]] 1539 + name = "zmij" 1540 + version = "1.0.18" 1541 + source = "registry+https://github.com/rust-lang/crates.io-index" 1542 + checksum = "1966f8ac2c1f76987d69a74d0e0f929241c10e78136434e3be70ff7f58f64214"
+18
Cargo.toml
··· 1 + [package] 2 + name = "exp2span" 3 + version = "0.1.0" 4 + edition = "2024" 5 + 6 + [dependencies] 7 + opentelemetry = "0.27" 8 + opentelemetry_sdk = { version = "0.27", features = ["rt-tokio"] } 9 + opentelemetry-otlp = { version = "0.27", features = ["tokio", "trace"] } 10 + tracing = "0.1" 11 + tracing-subscriber = { version = "0.3", features = ["env-filter"] } 12 + tracing-opentelemetry = "0.28" 13 + tokio = { version = "1", features = ["full"] } 14 + serde = { version = "1.0", features = ["derive"] } 15 + serde_json = "1.0" 16 + regex = "1.11" 17 + chrono = { version = "0.4", features = ["serde"] } 18 + anyhow = "1.0"
+61
README.md
··· 1 + # exp2span 2 + 3 + Converts opencode logs to OpenTelemetry traces using MCP semantic conventions. 4 + 5 + ## Usage 6 + 7 + ```bash 8 + cargo run -- --path <log-file> 9 + ``` 10 + 11 + ## MCP Semantic Conventions Found 12 + 13 + The OpenTelemetry semantic conventions repository has recent additions for **Model Context Protocol (MCP)** instrumentation: 14 + 15 + - **Commit**: `c8400846 MCP semantic conventions (#2083)` 16 + - **Status**: Development 17 + - **File**: `.test-agent/sem/docs/gen-ai/mcp.md` 18 + 19 + ### Key Attributes 20 + 21 + #### Client Spans 22 + - `mcp.session.id` - Session identifier 23 + - `mcp.method.name` - Request/notification method (e.g., `tools/call`, `initialize`) 24 + - `mcp.protocol.version` - MCP version (e.g., `2025-06-18`) 25 + - `gen_ai.operation.name` - Operation type (e.g., `execute_tool`) 26 + - `gen_ai.tool.name` - Tool name 27 + - `jsonrpc.protocol.version` - JSON-RPC version (default: `2.0`) 28 + - `network.transport` - Transport protocol (`tcp`, `quic`, `pipe`) 29 + - `network.protocol.name` - OSI application layer (e.g., `http`, `websocket`) 30 + 31 + #### Metrics 32 + - `mcp.client.operation.duration` - Histogram of operation durations 33 + - `mcp.server.operation.duration` - Server-side operation duration 34 + 35 + ### Well-Known MCP Methods 36 + 37 + Common methods from the specification: 38 + - `tools/call` - Execute a tool 39 + - `tools/list` - List available tools 40 + - `initialize` - Initialize MCP client 41 + - `resources/list` - List available resources 42 + - `resources/read` - Read a resource 43 + 44 + ## Implementation 45 + 46 + The parser extracts: 47 + - Session ID from header metadata 48 + - Assistant/User messages with timestamps 49 + - Tool usage information (when available) 50 + - Thinking sections for context analysis 51 + 52 + Each assistant message is converted to an OpenTelemetry span with appropriate MCP attributes. 53 + 54 + ## Dependencies 55 + 56 + - `opentelemetry` - Core tracing API 57 + - `opentelemetry_sdk` - SDK implementation 58 + - `opentelemetry-otlp` - OTLP exporter 59 + - `regex` - Log parsing 60 + - `chrono` - Timestamp handling 61 + - `serde_json` - JSON parsing
+457
doc/PLAN-enhancements.md
··· 1 + # exp2span Enhancement Plan 2 + 3 + **Status:** Planning 4 + **Created:** 2025-02-01 5 + **Priority:** TBD 6 + 7 + --- 8 + 9 + ## Overview 10 + 11 + This document outlines potential improvements to `exp2span`, organized by category and priority. The goal is to transform it from a basic prototype into a production-ready CLI tool following Rust CLI best practices. 12 + 13 + ## Current exp2span State 14 + 15 + **What we have:** 16 + - Simple `main.rs` with basic argument parsing (`std::env::args`) 17 + - Single binary that takes a file path 18 + - Parses opencode markdown logs 19 + - Creates OpenTelemetry spans (currently in-memory) 20 + - Basic error handling with anyhow 21 + 22 + --- 23 + 24 + ## Potential Improvements by Category 25 + 26 + ### 1. CLI Structure & Clap v4 🎯 High Priority 27 + 28 + ```rust 29 + // Proposed CLI structure 30 + exp2span export <file> # Export to spans 31 + exp2span validate <file> # Validate log format 32 + exp2span info <file> # Show log metadata 33 + exp2span watch <file> # Watch and export changes 34 + 35 + # Global options 36 + --config <path> # Config file 37 + --output {json,yaml,table,otel} # Output format 38 + --verbose # Logging level 39 + --quiet # Suppress output 40 + 41 + # Export options 42 + --otel-endpoint <url> # OTLP endpoint URL 43 + --otel-headers <key=value> # OTLP auth headers 44 + --batch-size <n> # Process N entries at once 45 + --dry-run # Don't actually export 46 + ``` 47 + 48 + **Benefits:** 49 + - Professional CLI feel 50 + - Easy to extend with new commands 51 + - Shell completions out of the box 52 + - Consistent help/usage messages 53 + 54 + --- 55 + 56 + ### 2. Output Formatting 🎯 High Priority 57 + 58 + **What we could add:** 59 + 60 + ```rust 61 + // Multiple output formats 62 + export --output json # Pretty-printed JSON 63 + export --output json-lines # JSON Lines (NDJSON) for streaming 64 + export --output yaml # YAML format 65 + export --output table # Human-readable table 66 + export --output otlp # Send directly to OTLP endpoint 67 + export --output file # Write to trace file (protobuf) 68 + 69 + // Output controls 70 + --no-color # Disable colors 71 + --compact # Compact JSON (no indentation) 72 + --include-content # Include full message content 73 + --include-thinking # Include thinking blocks 74 + --filter role=assistant # Filter by role 75 + --filter tool-name=* # Filter by tool calls 76 + ``` 77 + 78 + **Example outputs:** 79 + - **JSON**: `{ "span": { "name": "tools/call", "attributes": {...} }` 80 + - **Table**: `| ID | Tool | Model | Duration |` 81 + - **OTLP**: Direct streaming to Jaeger/Tempo/collector 82 + 83 + --- 84 + 85 + ### 3. Configuration Management 🟡 Medium Priority 86 + 87 + ```toml 88 + # ~/.config/exp2span/config.toml or .exp2span.toml 89 + [otel] 90 + endpoint = "http://localhost:4318" 91 + headers = { "Authorization" = "Bearer ${OTEL_TOKEN}" } 92 + batch_size = 100 93 + timeout_seconds = 30 94 + 95 + [output] 96 + format = "json" 97 + include_thinking = false 98 + compact = false 99 + 100 + [parser] 101 + strict_mode = false 102 + max_file_size_mb = 100 103 + ``` 104 + 105 + **Environment variables:** 106 + ```bash 107 + EXP2SPAN_OTEL_ENDPOINT=http://localhost:4318 108 + EXP2SPAN_OTEL_HEADERS=Authorization=Bearer xyz 109 + EXP2SPAN_OUTPUT_FORMAT=json 110 + EXP2SPAN_CONFIG=/path/to/config.toml 111 + ``` 112 + 113 + **Configuration precedence:** CLI args → ENV vars → Config file → Defaults 114 + 115 + --- 116 + 117 + ### 4. Error Handling & UX 🎯 High Priority 118 + 119 + **Current issues:** 120 + - Generic error messages 121 + - No helpful suggestions 122 + - No exit code differentiation 123 + 124 + **Improvements:** 125 + ```rust 126 + // Better error messages 127 + Error: Failed to parse log file 128 + 129 + Caused by: Invalid timestamp format at line 42 130 + File: /path/to/ex.md:42 131 + 132 + Suggestion: Check that timestamps follow format: "1/30/2026, 11:39:56 AM" 133 + 134 + // Exit codes 135 + 0 - Success 136 + 1 - General error 137 + 2 - File not found / invalid path 138 + 3 - Parse error in input file 139 + 4 - Configuration error 140 + 5 - Network error (OTLP export failed) 141 + 142 + // Confirmations 143 + export --force # Skip confirmation 144 + export --dry-run # Show what would be exported 145 + ``` 146 + 147 + --- 148 + 149 + ### 5. Performance & Large Files 🟡 Medium Priority 150 + 151 + ```rust 152 + // Batch processing 153 + export --batch-size 500 # Process 500 entries at once 154 + 155 + // Streaming mode 156 + export --stream # Stream output as we parse (don't wait) 157 + export --stream-interval 1s # Flush output every 1 second 158 + 159 + // Parallel processing 160 + export --parallel-jobs 4 # Use 4 worker threads 161 + 162 + // Memory-efficient mode 163 + export --memory-limit 1GB # Use at most 1GB RAM 164 + 165 + // Progress indication 166 + export --progress # Show progress bar 167 + ``` 168 + 169 + **Use cases:** 170 + - Large log files (100MB+) 171 + - Real-time log processing 172 + - Low-memory environments 173 + 174 + --- 175 + 176 + ### 6. OTLP Export (Real OpenTelemetry) 🟡 Medium Priority 177 + 178 + **Current limitation:** 179 + - We create spans in-memory but don't actually export them anywhere 180 + - Just prints "Created span: X with Y attributes" 181 + 182 + **Improvements:** 183 + ```rust 184 + // Direct OTLP export 185 + exp2span export ex.md --otel-endpoint http://localhost:4318 186 + 187 + // Configurable exporters 188 + --otel-protocol {grpc,http} # OTLP protocol 189 + --otel-insecure # Skip TLS verification 190 + --otel-headers Authorization=Bearer $TOKEN 191 + --otel-service-name exp2span # Service name for traces 192 + 193 + // Export to file 194 + --output-file traces.json # Save spans to file 195 + --output-file traces.otlp # Binary protobuf format 196 + ``` 197 + 198 + **Why this matters:** 199 + - Actually sends traces to Jaeger, Tempo, Zipkin, etc. 200 + - Production-ready observability 201 + - No need to pipe to other tools 202 + 203 + --- 204 + 205 + ### 7. File Watching & Real-time Mode 🟢 Low Priority 206 + 207 + ```rust 208 + // Watch mode 209 + exp2span watch ex.md 210 + 211 + // Behaviors 212 + - Monitor file for changes (using notify crate) 213 + - Incrementally export new entries 214 + - Debounce rapid changes 215 + - Show "Watching..." indicator 216 + - Ctrl+C to stop gracefully 217 + 218 + // Use cases 219 + - Development: Watch log file while assistant runs 220 + - Testing: See traces appear in real-time in Jaeger 221 + - Debugging: Immediate feedback on log parsing 222 + ``` 223 + 224 + --- 225 + 226 + ### 8. Validation & Diagnostics 🟡 Medium Priority 227 + 228 + ```rust 229 + // Validate command 230 + exp2span validate ex.md 231 + 232 + # Output 233 + ✓ Header parsing: OK 234 + ✓ Session ID: ses_3f14c1a87ffec6pfnoFXP5dBp 235 + ✓ Messages: 67 assistant entries 236 + ✓ Timestamps: All valid 237 + ✗ Tool detection: 5 tool calls without tool names 238 + Line 142, 289, 445, 612, 778 239 + 240 + // Info command 241 + exp2span info ex.md 242 + 243 + # Output 244 + Session ID: ses_3f14c1a87ffec6pfnoFXP5dBp 245 + Created: 1/30/2026, 11:39:56 AM 246 + Updated: 2/1/2026, 1:57:51 AM 247 + Total messages: 67 248 + Assistant: 67 249 + User: 13 250 + Tools called: 12 251 + Models: glm-4.7 (67) 252 + Duration: 83.4s total 253 + 254 + // Debug mode 255 + exp2span --debug export ex.md 256 + # Shows detailed parsing progress, attribute values, etc. 257 + ``` 258 + 259 + --- 260 + 261 + ### 9. Testing Infrastructure 🟢 Low Priority 262 + 263 + ```rust 264 + // Integration tests 265 + tests/ 266 + ├── cli/ 267 + │ ├── export.rs 268 + │ ├── validate.rs 269 + │ └── watch.rs 270 + ├── parser/ 271 + │ └── log_parser.rs 272 + └── fixtures/ 273 + ├── simple.md 274 + ├── complex.md 275 + └── malformed.md 276 + 277 + // Snapshot tests 278 + - Capture stdout/stderr for various commands 279 + - Verify error messages 280 + - Test different output formats 281 + 282 + // Benchmarks 283 + - Parse performance for different file sizes 284 + - Export speed to different backends 285 + - Memory usage during processing 286 + ``` 287 + 288 + --- 289 + 290 + ### 10. Shell Integration 🟢 Low Priority 291 + 292 + ```bash 293 + # Generated completions 294 + exp2span completion bash # Generate bash completions 295 + exp2span completion zsh # Generate zsh completions 296 + exp2span completion fish # Generate fish completions 297 + 298 + # Shell functions 299 + exp2span-completion() { 300 + # Dynamic completions for file paths, formats, etc. 301 + } 302 + 303 + # Alias for common patterns 304 + alias exp2span-export='exp2span export --output json-lines' 305 + ``` 306 + 307 + --- 308 + 309 + ## Implementation Phases 310 + 311 + ### Phase 1: Essential CLI Structure (This Iteration) 312 + 313 + **Must do:** 314 + - [ ] Add clap v4 with derive API 315 + - [ ] Implement `export`, `validate`, `info` subcommands 316 + - [ ] Add `--output` flag (json, yaml, table) 317 + - [ ] Add `--verbose` and `--quiet` flags 318 + - [ ] Better error messages with suggestions 319 + - [ ] Proper exit codes 320 + 321 + **Estimated effort:** 1-2 days 322 + 323 + **Success criteria:** 324 + - Help text is clear and professional 325 + - All commands work end-to-end 326 + - Error messages are actionable 327 + 328 + --- 329 + 330 + ### Phase 2: Core Features (Next Iteration) 331 + 332 + **Should do:** 333 + - [ ] Configuration file support (TOML) 334 + - [ ] Environment variable support 335 + - [ ] JSON Lines output for streaming 336 + - [ ] Progress bar for large files 337 + - [ ] Basic OTLP export to collector 338 + - [ ] Validation command with detailed output 339 + 340 + **Estimated effort:** 2-3 days 341 + 342 + **Success criteria:** 343 + - Can run with config file 344 + - Can stream output for piping 345 + - Actually exports to OTLP collector 346 + - Validation catches common issues 347 + 348 + --- 349 + 350 + ### Phase 3: Advanced Features (Future) 351 + 352 + **Nice to have:** 353 + - [ ] File watching mode 354 + - [ ] Batch/parallel processing 355 + - [ ] Full configuration schema validation 356 + - [ ] Shell completion generation 357 + - [ ] Comprehensive test suite 358 + - [ ] Benchmark suite 359 + - [ ] Update checking 360 + 361 + **Estimated effort:** 3-5 days (spread over multiple iterations) 362 + 363 + **Success criteria:** 364 + - Can watch files in real-time 365 + - Tests cover >80% of code paths 366 + - Completions work in bash/zsh/fish 367 + - Performance benchmarks established 368 + 369 + --- 370 + 371 + ## Open Questions 372 + 373 + ### Priority Discussion 374 + 375 + 1. **Output format priorities** - Should we focus on JSON/JSONL first, or implement table/yaml too? 376 + - **Option A:** JSON only (simpler, faster) 377 + - **Option B:** JSON + JSONL (most useful for scripting) 378 + - **Option C:** All formats (more work, more flexible) 379 + 380 + 2. **OTLP export** - Is this critical for your use case, or is stdout sufficient for now? 381 + - **Option A:** Export to stdout only (current behavior, just formatted better) 382 + - **Option B:** Export to stdout + OTLP endpoint (hybrid approach) 383 + - **Option C:** Full OTLP support (multiple protocols, auth, etc.) 384 + 385 + 3. **Configuration** - Do you need config files, or are CLI args enough? 386 + - **Option A:** CLI args only (simpler, no hidden state) 387 + - **Option B:** CLI + ENV (good for CI/CD) 388 + - **Option C:** CLI + ENV + config files (most flexible) 389 + 390 + 4. **Large files** - Are you processing files larger than ~10MB? If not, streaming/parallelism may not be needed yet. 391 + - **Assessment needed:** Test with representative files to see if performance is an issue 392 + 393 + 5. **Real-time** - Do you need file watching, or is one-time export sufficient? 394 + - **Use case:** Development vs production workflows 395 + - **Impact:** Affects whether we invest in file watching infrastructure 396 + 397 + --- 398 + 399 + ## Dependencies to Add 400 + 401 + For **Phase 1**: 402 + ```toml 403 + clap = { version = "4", features = ["derive", "env"] } 404 + colored = "*" 405 + thiserror = "*" 406 + ``` 407 + 408 + For **Phase 2**: 409 + ```toml 410 + directories = "*" # Config file locations 411 + serde = { version = "1", features = ["derive"] } 412 + toml = "*" 413 + indicatif = "*" # Progress bars 414 + opentelemetry-otlp = "*" # Real OTLP export 415 + ``` 416 + 417 + For **Phase 3**: 418 + ```toml 419 + notify = "*" # File watching 420 + assert_cmd = "*" # CLI testing 421 + insta = "*" # Snapshot testing 422 + criterion = "*" # Benchmarking 423 + clap_complete = "*" 424 + clap_mangen = "*" 425 + ``` 426 + 427 + --- 428 + 429 + ## Success Metrics 430 + 431 + ### Phase 1 Success 432 + - [ ] Help output is professional and consistent 433 + - [ ] Error messages include file:line references 434 + - [ ] Exit codes follow conventions 435 + - [ ] At least 3 different output formats work 436 + 437 + ### Phase 2 Success 438 + - [ ] Config files override defaults correctly 439 + - [ ] Environment variables work 440 + - [ ] Can export 1000+ entry log in <5 seconds 441 + - [ ] OTLP export succeeds with local collector 442 + 443 + ### Phase 3 Success 444 + - [ ] File watching detects changes within 500ms 445 + - [ ] Test coverage >70% 446 + - [ ] Benchmarks establish baseline performance 447 + - [ ] Shell completions auto-complete options 448 + 449 + --- 450 + 451 + ## Next Steps 452 + 453 + 1. **Review and prioritize** - Go through "Open Questions" and discuss priorities 454 + 2. **Start Phase 1** - Begin with clap v4 integration 455 + 3. **Iterate quickly** - Ship Phase 1 before starting Phase 2 456 + 4. **Gather feedback** - Test with real opencode logs 457 + 5. **Adjust plan** - Update based on actual usage patterns
+1
ex.md
··· 1 + ../req-gov/doc/transcript/trace2.md
+299
src/main.rs
··· 1 + use anyhow::Result; 2 + use chrono::{DateTime, Utc}; 3 + use opentelemetry::trace::{Span, SpanKind, Tracer, TracerProvider as TracerProviderTrait}; 4 + use opentelemetry::{trace::TraceError, KeyValue}; 5 + use regex::Regex; 6 + use serde::Deserialize; 7 + use std::fs; 8 + 9 + #[derive(Debug, Clone, Deserialize)] 10 + pub struct OpenCodeLog { 11 + session_id: String, 12 + created: String, 13 + updated: String, 14 + messages: Vec<LogMessage>, 15 + } 16 + 17 + #[derive(Debug, Clone, Deserialize)] 18 + pub struct LogMessage { 19 + #[serde(rename = "type")] 20 + msg_type: String, 21 + role: String, 22 + model: Option<String>, 23 + timestamp: Option<DateTime<Utc>>, 24 + content: String, 25 + thinking: Option<String>, 26 + tools_used: Option<Vec<ToolUsage>>, 27 + } 28 + 29 + #[derive(Debug, Clone, Deserialize)] 30 + pub struct ToolUsage { 31 + name: String, 32 + method: String, 33 + arguments: serde_json::Value, 34 + result: Option<serde_json::Value>, 35 + duration_ms: Option<u64>, 36 + } 37 + 38 + #[derive(Debug, Clone)] 39 + pub struct ParsedLogEntry { 40 + session_id: String, 41 + role: String, 42 + model: Option<String>, 43 + timestamp: DateTime<Utc>, 44 + tool_name: Option<String>, 45 + mcp_method: Option<String>, 46 + content: String, 47 + thinking: Option<String>, 48 + duration_ms: Option<u64>, 49 + } 50 + 51 + pub struct LogParser { 52 + header_regex: Regex, 53 + assistant_regex: Regex, 54 + user_regex: Regex, 55 + tool_regex: Regex, 56 + } 57 + 58 + impl LogParser { 59 + pub fn new() -> Self { 60 + Self { 61 + header_regex: Regex::new( 62 + r"\*\*Session ID:\*\* (.+?)\n\*\*Created:\*\* (.+?)\n\*\*Updated:\*\* (.+?)\n", 63 + ) 64 + .unwrap(), 65 + assistant_regex: Regex::new(r"## \s*Assistant \s*\(([^)]+)\)\s*").unwrap(), 66 + user_regex: Regex::new(r"## \s*User").unwrap(), 67 + tool_regex: Regex::new(r"Tool:\s+(\w+)").unwrap(), 68 + } 69 + } 70 + 71 + pub fn parse_file(&self, path: &str) -> Result<OpenCodeLog> { 72 + let content = fs::read_to_string(path)?; 73 + self.parse_content(&content) 74 + } 75 + 76 + pub fn parse_content(&self, content: &str) -> Result<OpenCodeLog> { 77 + let mut session_id = String::new(); 78 + let mut created = String::new(); 79 + let mut updated = String::new(); 80 + 81 + if let Some(caps) = self.header_regex.captures(content) { 82 + session_id = caps[1].to_string(); 83 + created = caps[2].to_string(); 84 + updated = caps[3].to_string(); 85 + } 86 + 87 + let mut messages = Vec::new(); 88 + let lines: Vec<&str> = content.lines().collect(); 89 + let mut i = 0; 90 + 91 + while i < lines.len() { 92 + let line = lines[i]; 93 + 94 + if let Some(caps) = self.assistant_regex.captures(line) { 95 + let mut message = LogMessage { 96 + msg_type: "assistant".to_string(), 97 + role: "assistant".to_string(), 98 + model: Some( 99 + caps[1] 100 + .split("·") 101 + .next() 102 + .unwrap_or("unknown") 103 + .trim() 104 + .to_string(), 105 + ), 106 + timestamp: None, 107 + content: String::new(), 108 + thinking: None, 109 + tools_used: None, 110 + }; 111 + 112 + i += 1; 113 + let mut in_thinking = false; 114 + let mut thinking_content = String::new(); 115 + 116 + while i < lines.len() { 117 + let line = lines[i]; 118 + 119 + if line.starts_with("## ") { 120 + break; 121 + } 122 + 123 + if line == "_Thinking:_" { 124 + in_thinking = true; 125 + i += 1; 126 + continue; 127 + } 128 + 129 + if in_thinking && line == "Done!" { 130 + in_thinking = false; 131 + i += 1; 132 + continue; 133 + } 134 + 135 + if in_thinking { 136 + thinking_content.push_str(line); 137 + thinking_content.push('\n'); 138 + } else { 139 + message.content.push_str(line); 140 + message.content.push('\n'); 141 + } 142 + 143 + i += 1; 144 + } 145 + 146 + if !thinking_content.is_empty() { 147 + message.thinking = Some(thinking_content.trim().to_string()); 148 + } 149 + 150 + message.content = message.content.trim().to_string(); 151 + messages.push(message); 152 + continue; 153 + } 154 + 155 + i += 1; 156 + } 157 + 158 + Ok(OpenCodeLog { 159 + session_id, 160 + created, 161 + updated, 162 + messages, 163 + }) 164 + } 165 + 166 + pub fn parse_entries(&self, log: &OpenCodeLog) -> Vec<ParsedLogEntry> { 167 + let mut entries = Vec::new(); 168 + 169 + for msg in &log.messages { 170 + let mut tool_name = None; 171 + let mut mcp_method = None; 172 + 173 + if let Some(tool_caps) = self.tool_regex.captures(&msg.content) { 174 + tool_name = Some(tool_caps[1].to_string()); 175 + } 176 + 177 + if let Some(tools) = &msg.tools_used { 178 + if let Some(tool) = tools.first() { 179 + mcp_method = Some(tool.method.clone()); 180 + } 181 + } 182 + 183 + entries.push(ParsedLogEntry { 184 + session_id: log.session_id.clone(), 185 + role: msg.role.clone(), 186 + model: msg.model.clone(), 187 + timestamp: msg.timestamp.unwrap_or_else(|| Utc::now()), 188 + tool_name, 189 + mcp_method, 190 + content: msg.content.clone(), 191 + thinking: msg.thinking.clone(), 192 + duration_ms: msg 193 + .tools_used 194 + .as_ref() 195 + .and_then(|t| t.first().and_then(|u| u.duration_ms)), 196 + }); 197 + } 198 + 199 + entries 200 + } 201 + } 202 + 203 + pub struct OtelExporter { 204 + tracer: opentelemetry_sdk::trace::Tracer, 205 + } 206 + 207 + impl OtelExporter { 208 + pub fn new(service_name: &str) -> Result<Self, TraceError> { 209 + use opentelemetry_sdk::trace::TracerProvider; 210 + use opentelemetry_sdk::Resource; 211 + 212 + let resource = Resource::new(vec![ 213 + KeyValue::new("service.name", service_name.to_string()), 214 + KeyValue::new("service.version", env!("CARGO_PKG_VERSION")), 215 + KeyValue::new("mcp.protocol.version", "2025-06-18"), 216 + ]); 217 + 218 + let provider = TracerProvider::builder().with_resource(resource).build(); 219 + 220 + let tracer = provider.tracer("exp2span"); 221 + 222 + Ok(Self { tracer }) 223 + } 224 + 225 + pub fn export_log(&self, entry: &ParsedLogEntry) { 226 + use opentelemetry::trace::SpanBuilder; 227 + 228 + let mut attributes = vec![ 229 + KeyValue::new("mcp.session.id", entry.session_id.clone()), 230 + KeyValue::new("network.transport", "tcp"), 231 + KeyValue::new("jsonrpc.protocol.version", "2.0"), 232 + ]; 233 + 234 + if let Some(model) = &entry.model { 235 + attributes.push(KeyValue::new("gen_ai.model.name", model.clone())); 236 + } 237 + 238 + let mut tool_name_str = None; 239 + if let Some(tool_name) = &entry.tool_name { 240 + tool_name_str = Some(tool_name.clone()); 241 + attributes.push(KeyValue::new("gen_ai.tool.name", tool_name.clone())); 242 + } 243 + 244 + if let Some(mcp_method) = &entry.mcp_method { 245 + attributes.push(KeyValue::new("mcp.method.name", mcp_method.clone())); 246 + attributes.push(KeyValue::new("gen_ai.operation.name", "execute_tool")); 247 + } 248 + 249 + if let Some(thinking) = &entry.thinking { 250 + attributes.push(KeyValue::new("opencode.thinking", thinking.clone())); 251 + } 252 + 253 + let span_name = if let Some(tool_name) = &tool_name_str { 254 + format!("tools/call {}", tool_name) 255 + } else { 256 + format!("{} session", entry.role) 257 + }; 258 + 259 + let attr_count = attributes.len(); 260 + 261 + let mut builder = SpanBuilder::from_name(span_name.clone()); 262 + builder.span_kind = Some(SpanKind::Client); 263 + builder.attributes = Some(attributes); 264 + 265 + let mut span = self.tracer.build(builder); 266 + span.end(); 267 + 268 + println!("Created span: {} with {} attributes", span_name, attr_count); 269 + } 270 + 271 + pub fn export_log_file(&self, parser: &LogParser, path: &str) -> Result<()> { 272 + let log = parser.parse_file(path)?; 273 + let entries = parser.parse_entries(&log); 274 + 275 + for entry in &entries { 276 + self.export_log(entry); 277 + } 278 + 279 + Ok(()) 280 + } 281 + } 282 + 283 + fn main() -> Result<()> { 284 + let args: Vec<String> = std::env::args().collect(); 285 + 286 + if args.len() < 2 { 287 + eprintln!("Usage: {} <log-file>", args[0]); 288 + std::process::exit(1); 289 + } 290 + 291 + let log_path = &args[1]; 292 + 293 + let parser = LogParser::new(); 294 + let exporter = OtelExporter::new("exp2span")?; 295 + 296 + exporter.export_log_file(&parser, log_path)?; 297 + 298 + Ok(()) 299 + }