From e0490b6458d913cd45c40837eba392accb97c912 Mon Sep 17 00:00:00 2001 From: Alexander Koz Date: Wed, 27 Mar 2024 20:49:56 +0400 Subject: [PATCH] add tracing --- .github/workflows/dev-build.yml | 2 +- Cargo.lock | 443 +++++++++++++++++++++++++- support/device/Cargo.toml | 2 + support/device/src/device/command.rs | 2 +- support/device/src/device/methods.rs | 1 + support/device/src/device/mod.rs | 2 +- support/device/src/install.rs | 3 + support/device/src/interface/mod.rs | 1 + support/device/src/lib.rs | 6 + support/device/src/mount/linux.rs | 5 + support/device/src/mount/mac.rs | 8 + support/device/src/mount/methods.rs | 11 + support/device/src/mount/mod.rs | 4 +- support/device/src/mount/win.rs | 8 +- support/device/src/run.rs | 2 + support/device/src/send.rs | 2 + support/device/src/serial/async.rs | 1 + support/device/src/serial/blocking.rs | 1 + support/device/src/serial/discover.rs | 12 +- support/device/src/serial/methods.rs | 10 +- support/device/src/serial/mod.rs | 9 +- support/device/src/usb/discover.rs | 8 + support/device/src/usb/io.rs | 5 + support/device/src/usb/mod.rs | 67 +++- support/tool2/Cargo.toml | 15 + support/tool2/src/cli.rs | 2 + support/tool2/src/main.rs | 86 ++++- 27 files changed, 689 insertions(+), 29 deletions(-) diff --git a/.github/workflows/dev-build.yml b/.github/workflows/dev-build.yml index d4b6c865..def2bc66 100644 --- a/.github/workflows/dev-build.yml +++ b/.github/workflows/dev-build.yml @@ -83,7 +83,7 @@ jobs: - name: pdtool run: | - cargo build -p=playdate-tool2 --bins + cargo build -p=playdate-tool2 --bins -features=tracing - name: Upload diff --git a/Cargo.lock b/Cargo.lock index 4af3310f..0dbb1adb 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -131,6 +131,39 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "96d30a06541fbafbc7f82ed10c06164cfbd2c401138f6addd8404629c4b16711" +[[package]] +name = "async-stream" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd56dd203fef61ac097dd65721a419ddccb106b2d2b70ba60a6b529f03961a51" +dependencies = [ + "async-stream-impl", + "futures-core", + "pin-project-lite", +] + +[[package]] +name = "async-stream-impl" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16e62a023e7c117e27523144c5d2459f4397fcc3cab0085af8e2224f643a0193" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "async-trait" +version = "0.1.79" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a507401cad91ec6a857ed5513a2073c82a9b9048762b885bb98655b306964681" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -143,6 +176,51 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f1fdabc7756949593fe60f30ec81974b613357de856987752631dea1e3394c80" +[[package]] +name = "axum" +version = "0.6.20" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b829e4e32b91e643de6eafe82b1d90675f5874230191a4ffbc1b336dec4d6bf" +dependencies = [ + "async-trait", + "axum-core", + "bitflags 1.3.2", + "bytes", + "futures-util", + "http", + "http-body", + "hyper", + "itoa", + "matchit", + "memchr", + "mime", + "percent-encoding", + "pin-project-lite", + "rustversion", + "serde", + "sync_wrapper", + "tower", + "tower-layer", + "tower-service", +] + +[[package]] +name = "axum-core" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "759fa577a247914fd3f7f76d62972792636412fbfd634cd452f6a385a74d2d2c" +dependencies = [ + "async-trait", + "bytes", + "futures-util", + "http", + "http-body", + "mime", + "rustversion", + "tower-layer", + "tower-service", +] + [[package]] name = "backtrace" version = "0.3.71" @@ -341,7 +419,7 @@ dependencies = [ "humantime", "ignore", "im-rc", - "indexmap", + "indexmap 2.2.6", "itertools 0.12.1", "jobserver", "lazycell", @@ -651,6 +729,43 @@ dependencies = [ "memchr", ] +[[package]] +name = "console-api" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fd326812b3fd01da5bb1af7d340d0d555fd3d4b641e7f1dfcf5962a902952787" +dependencies = [ + "futures-core", + "prost", + "prost-types", + "tonic", + "tracing-core", +] + +[[package]] +name = "console-subscriber" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7481d4c57092cd1c19dd541b92bdce883de840df30aa5d03fd48a3935c01842e" +dependencies = [ + "console-api", + "crossbeam-channel", + "crossbeam-utils", + "futures-task", + "hdrhistogram", + "humantime", + "prost-types", + "serde", + "serde_json", + "thread_local", + "tokio", + "tokio-stream", + "tonic", + "tracing", + "tracing-core", + "tracing-subscriber", +] + [[package]] name = "const-hex" version = "1.11.3" @@ -1089,6 +1204,12 @@ dependencies = [ "miniz_oxide", ] +[[package]] +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + [[package]] name = "form_urlencoded" version = "1.2.1" @@ -1573,7 +1694,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7ddf80e16f3c19ac06ce415a38b8591993d3f73aede049cb561becb5b3a8e242" dependencies = [ "gix-hash", - "hashbrown", + "hashbrown 0.14.3", "parking_lot 0.12.1", ] @@ -2033,6 +2154,31 @@ dependencies = [ "subtle", ] +[[package]] +name = "h2" +version = "0.3.25" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4fbd2820c5e49886948654ab546d0688ff24530286bdcf8fca3cefb16d4618eb" +dependencies = [ + "bytes", + "fnv", + "futures-core", + "futures-sink", + "futures-util", + "http", + "indexmap 2.2.6", + "slab", + "tokio", + "tokio-util", + "tracing", +] + +[[package]] +name = "hashbrown" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" + [[package]] name = "hashbrown" version = "0.14.3" @@ -2049,7 +2195,20 @@ version = "0.8.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e8094feaf31ff591f651a2664fb9cfd92bba7a60ce3197265e9482ebe753c8f7" dependencies = [ - "hashbrown", + "hashbrown 0.14.3", +] + +[[package]] +name = "hdrhistogram" +version = "7.5.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "765c9198f173dd59ce26ff9f95ef0aafd0a0fe01fb9d72841bc5066a4c06511d" +dependencies = [ + "base64", + "byteorder", + "flate2", + "nom", + "num-traits", ] [[package]] @@ -2131,6 +2290,17 @@ dependencies = [ "syn 1.0.109", ] +[[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-auth" version = "0.1.9" @@ -2140,12 +2310,71 @@ dependencies = [ "memchr", ] +[[package]] +name = "http-body" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ceab25649e9960c0311ea418d17bee82c0dcec1bd053b5f9a66e265a693bed2" +dependencies = [ + "bytes", + "http", + "pin-project-lite", +] + +[[package]] +name = "httparse" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d897f394bad6a705d5f4104762e116a75639e470d80901eed05a860a95cb1904" + +[[package]] +name = "httpdate" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9" + [[package]] name = "humantime" version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "hyper" +version = "0.14.28" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" +dependencies = [ + "bytes", + "futures-channel", + "futures-core", + "futures-util", + "h2", + "http", + "http-body", + "httparse", + "httpdate", + "itoa", + "pin-project-lite", + "socket2", + "tokio", + "tower-service", + "tracing", + "want", +] + +[[package]] +name = "hyper-timeout" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bbb958482e8c7be4bc3cf272a766a2b0bf1a6755e7a6ae777f017a31d11b13b1" +dependencies = [ + "hyper", + "pin-project-lite", + "tokio", + "tokio-io-timeout", +] + [[package]] name = "idna" version = "0.5.0" @@ -2186,6 +2415,16 @@ dependencies = [ "version_check", ] +[[package]] +name = "indexmap" +version = "1.9.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd070e393353796e801d209ad339e89596eb4c8d430d18ede6a1cced8fafbd99" +dependencies = [ + "autocfg", + "hashbrown 0.12.3", +] + [[package]] name = "indexmap" version = "2.2.6" @@ -2193,7 +2432,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "168fb715dda47215e360912c096649d23d58bf392ac62f73919e831745e40f26" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.14.3", ] [[package]] @@ -2573,6 +2812,12 @@ dependencies = [ "regex-automata 0.1.10", ] +[[package]] +name = "matchit" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" + [[package]] name = "maybe-async" version = "0.2.10" @@ -2639,6 +2884,12 @@ dependencies = [ "syn 2.0.55", ] +[[package]] +name = "mime" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a" + [[package]] name = "minimal-lexical" version = "0.2.1" @@ -3109,6 +3360,26 @@ dependencies = [ "siphasher", ] +[[package]] +name = "pin-project" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bf43b791c5b9e34c3d182969b4abb522f9343702850a2e57f460d00d09b4b3" +dependencies = [ + "pin-project-internal", +] + +[[package]] +name = "pin-project-internal" +version = "1.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f38a4412a78282e09a2cf38d195ea5420d15ba0602cb375210efbc877243965" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.55", +] + [[package]] name = "pin-project-lite" version = "0.2.13" @@ -3245,6 +3516,7 @@ dependencies = [ "thiserror", "tokio", "tokio-serial", + "tracing", "udev", "usb-ids", "windows", @@ -3352,6 +3624,7 @@ name = "playdate-tool2" version = "0.2.0" dependencies = [ "clap", + "console-subscriber", "env_logger", "futures", "futures-lite", @@ -3362,6 +3635,8 @@ dependencies = [ "serde_json", "thiserror", "tokio", + "tracing", + "tracing-subscriber", ] [[package]] @@ -3384,7 +3659,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d9d34169e64b3c7a80c8621a48adaf44e0cf62c78a9b25dd9dd35f1881a17cf9" dependencies = [ "base64", - "indexmap", + "indexmap 2.2.6", "line-wrap", "quick-xml", "serde", @@ -3471,6 +3746,38 @@ dependencies = [ "unarray", ] +[[package]] +name = "prost" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "146c289cda302b98a28d40c8b3b90498d6e526dd24ac2ecea73e4e491685b94a" +dependencies = [ + "bytes", + "prost-derive", +] + +[[package]] +name = "prost-derive" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "efb6c9a1dd1def8e2124d17e83a20af56f1570d6c2d2bd9e266ccb768df3840e" +dependencies = [ + "anyhow", + "itertools 0.11.0", + "proc-macro2", + "quote", + "syn 2.0.55", +] + +[[package]] +name = "prost-types" +version = "0.12.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "193898f59edcf43c26227dcd4c8427f00d99d61e95dcde58dabd49fa291d470e" +dependencies = [ + "prost", +] + [[package]] name = "quick-xml" version = "0.31.0" @@ -3681,6 +3988,12 @@ dependencies = [ "windows-sys 0.52.0", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.17" @@ -4100,6 +4413,12 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "sync_wrapper" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" + [[package]] name = "tar" version = "0.4.40" @@ -4254,9 +4573,20 @@ dependencies = [ "signal-hook-registry", "socket2", "tokio-macros", + "tracing", "windows-sys 0.48.0", ] +[[package]] +name = "tokio-io-timeout" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "30b74022ada614a1b4834de765f9bb43877f910cc8ce4be40e89042c9223a8bf" +dependencies = [ + "pin-project-lite", + "tokio", +] + [[package]] name = "tokio-macros" version = "2.2.0" @@ -4281,6 +4611,31 @@ dependencies = [ "tokio", ] +[[package]] +name = "tokio-stream" +version = "0.1.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "267ac89e0bec6e691e5813911606935d77c476ff49024f98abcea3e7b15e37af" +dependencies = [ + "futures-core", + "pin-project-lite", + "tokio", +] + +[[package]] +name = "tokio-util" +version = "0.7.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5419f34732d9eb6ee4c3578b7989078579b7f039cbbb9ca2c4da015749371e15" +dependencies = [ + "bytes", + "futures-core", + "futures-sink", + "pin-project-lite", + "tokio", + "tracing", +] + [[package]] name = "toml" version = "0.8.12" @@ -4308,7 +4663,7 @@ version = "0.21.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6a8534fd7f78b5405e860340ad6575217ce99f38d4d5c8f2442cb5ecb50090e1" dependencies = [ - "indexmap", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", @@ -4321,13 +4676,72 @@ version = "0.22.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e40bb779c5187258fd7aad0eb68cb8706a0a81fa712fbea808ab43c4b8374c4" dependencies = [ - "indexmap", + "indexmap 2.2.6", "serde", "serde_spanned", "toml_datetime", "winnow 0.6.5", ] +[[package]] +name = "tonic" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d560933a0de61cf715926b9cac824d4c883c2c43142f787595e48280c40a1d0e" +dependencies = [ + "async-stream", + "async-trait", + "axum", + "base64", + "bytes", + "h2", + "http", + "http-body", + "hyper", + "hyper-timeout", + "percent-encoding", + "pin-project", + "prost", + "tokio", + "tokio-stream", + "tower", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower" +version = "0.4.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b8fa9be0de6cf49e536ce1851f987bd21a43b771b09473c3549a6c853db37c1c" +dependencies = [ + "futures-core", + "futures-util", + "indexmap 1.9.3", + "pin-project", + "pin-project-lite", + "rand", + "slab", + "tokio", + "tokio-util", + "tower-layer", + "tower-service", + "tracing", +] + +[[package]] +name = "tower-layer" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c20c8dbed6283a09604c3e69b4b7eeb54e298b8a600d4d5ecb5ad39de609f1d0" + +[[package]] +name = "tower-service" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6bc1c9ce2b5135ac7f93c72918fc37feb872bdc6a5533a8b85eb4b86bfdae52" + [[package]] name = "tracing" version = "0.1.40" @@ -4395,6 +4809,12 @@ version = "0.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c8da954976b3cfd8a4d73b3ebb573e4b0f4c92326e5c1366a1c7b11e1eb11745" +[[package]] +name = "try-lock" +version = "0.2.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" + [[package]] name = "typenum" version = "1.17.0" @@ -4546,6 +4966,15 @@ dependencies = [ "winapi-util", ] +[[package]] +name = "want" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bfa7760aed19e106de2c7c0b581b509f2f25d3dacaf737cb82ac61bc6d760b0e" +dependencies = [ + "try-lock", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" diff --git a/support/device/Cargo.toml b/support/device/Cargo.toml index 8a986a10..10267b59 100644 --- a/support/device/Cargo.toml +++ b/support/device/Cargo.toml @@ -26,6 +26,8 @@ usb-ids = { version = "1.2024.2" } serialport = { version = "4.3", features = ["usbportinfo-interface"] } tokio-serial = { version = "5.4", optional = true } +tracing = { version = "0.1", optional = true } + # mb. read mount-points: # rustix = "0.38" diff --git a/support/device/src/device/command.rs b/support/device/src/device/command.rs index 4e189f99..af4d19b4 100644 --- a/support/device/src/device/command.rs +++ b/support/device/src/device/command.rs @@ -143,7 +143,7 @@ impl Command { line } - pub fn with_break_to(&self, mut writer: W) -> std::io::Result<()> { writeln!(writer, "{self}") } + pub fn with_break_to(&self, mut writer: W) -> std::io::Result<()> { writeln!(writer, "\n{self}\n") } } diff --git a/support/device/src/device/methods.rs b/support/device/src/device/methods.rs index 228ece09..de985f9f 100644 --- a/support/device/src/device/methods.rs +++ b/support/device/src/device/methods.rs @@ -15,6 +15,7 @@ pub async fn wait_mode_data(dev: Device) -> Result { wait_mode_change(de // TODO: make timeout configurable +#[cfg_attr(feature = "tracing", tracing::instrument(skip(dev), fields(dev = dev.info().serial_number())))] pub async fn wait_mode_change(mut dev: Device, to: Mode) -> Result { const ITER: u64 = 40; // ms const RETRIES: u8 = 130; // ≈5 sec diff --git a/support/device/src/device/mod.rs b/support/device/src/device/mod.rs index 260221e0..f3c4589d 100644 --- a/support/device/src/device/mod.rs +++ b/support/device/src/device/mod.rs @@ -72,7 +72,7 @@ impl std::fmt::Display for Device { impl std::fmt::Debug for Device { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("Device") - .field("info", &self.info) + .field("sn", &self.info.serial_number()) .field("mode", &self.mode) .field("open", &self.is_open()) .field("ready", &self.is_ready()) diff --git a/support/device/src/install.rs b/support/device/src/install.rs index f4956df2..c8d4043d 100644 --- a/support/device/src/install.rs +++ b/support/device/src/install.rs @@ -58,6 +58,7 @@ impl MountedDevicePath { /// Install package on the device. /// /// `path` is a host filesystem path to pdx. +#[cfg_attr(feature = "tracing", tracing::instrument(skip(drive)))] pub async fn install<'dev>(drive: &'dev MountedDevice, path: &Path, force: bool) @@ -146,6 +147,7 @@ pub async fn install<'dev>(drive: &'dev MountedDevice, /// 1. Mount if needed /// 1. Wait for FS to become available /// 1. Install package +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn mount_and_install(query: Query, path: &Path, force: bool) @@ -170,6 +172,7 @@ pub async fn mount_and_install(query: Query, /// Validate path - pdz or pdx-dir. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn validate_host_package(path: &Path) -> Result<()> { use std::io::{Error, ErrorKind}; diff --git a/support/device/src/interface/mod.rs b/support/device/src/interface/mod.rs index d7adf174..696eb1dd 100644 --- a/support/device/src/interface/mod.rs +++ b/support/device/src/interface/mod.rs @@ -79,6 +79,7 @@ mod ext { where T: tokio::io::AsyncWriteExt, Self: Unpin { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] async fn send_cmd(&mut self, cmd: crate::device::command::Command) -> Result { let cmd = cmd.with_break(); let bytes = cmd.as_bytes(); diff --git a/support/device/src/lib.rs b/support/device/src/lib.rs index b2af1801..ffd00847 100644 --- a/support/device/src/lib.rs +++ b/support/device/src/lib.rs @@ -3,8 +3,14 @@ #![feature(error_generic_member_access)] #![feature(exit_status_error)] #![feature(associated_type_defaults)] +#![cfg_attr(feature = "tracing", allow(unused_braces))] #[macro_use] +#[cfg(feature = "tracing")] +extern crate tracing; + +#[macro_use] +#[cfg(not(feature = "tracing"))] extern crate log; pub extern crate serialport; diff --git a/support/device/src/mount/linux.rs b/support/device/src/mount/linux.rs index 9cd869f0..3ecb2aa2 100644 --- a/support/device/src/mount/linux.rs +++ b/support/device/src/mount/linux.rs @@ -16,6 +16,7 @@ use crate::error::Error; use crate::device::Device; +#[derive(Debug, Clone)] pub struct Volume { /// FS mount point. path: PathBuf, @@ -58,6 +59,7 @@ mod unmount { impl Unmount for Volume { + #[cfg_attr(feature = "tracing", tracing::instrument())] fn unmount_blocking(&self) -> Result<(), Error> { use std::process::Command; @@ -101,6 +103,7 @@ mod unmount { #[cfg(feature = "tokio")] impl UnmountAsync for Volume { + #[cfg_attr(feature = "tracing", tracing::instrument())] async fn unmount(&self) -> Result<(), Error> { use tokio::process::Command; use futures_lite::future::ready; @@ -210,6 +213,7 @@ mod unmount { } +#[cfg_attr(feature = "tracing", tracing::instrument(fields(dev = dev.as_ref().serial_number())))] pub async fn volume_for(dev: Info) -> Result where Info: AsRef { let sysfs = dev.as_ref().sysfs_path(); @@ -246,6 +250,7 @@ pub async fn volume_for(dev: Info) -> Result } +#[cfg_attr(feature = "tracing", tracing::instrument(skip(devs)))] pub async fn volumes_for_map(devs: I) -> Result>, Error> where I: IntoIterator { let mounts = lfs_core::read_mountinfo()?; diff --git a/support/device/src/mount/mac.rs b/support/device/src/mount/mac.rs index 864deb24..eac44727 100644 --- a/support/device/src/mount/mac.rs +++ b/support/device/src/mount/mac.rs @@ -14,6 +14,7 @@ use crate::error::Error; pub const VENDOR_ID_ENC: &str = const_hex::const_encode::<2, true>(&crate::VENDOR_ID.to_be_bytes()).as_str(); +#[derive(Debug, Clone)] pub struct Volume { path: PathBuf, } @@ -39,6 +40,7 @@ mod unmount { impl Unmount for Volume { + #[cfg_attr(feature = "tracing", tracing::instrument())] fn unmount_blocking(&self) -> Result<(), Error> { cmd(self).status()? .exit_ok() @@ -49,6 +51,7 @@ mod unmount { #[cfg(feature = "tokio")] impl UnmountAsync for Volume { + #[cfg_attr(feature = "tracing", tracing::instrument())] async fn unmount(&self) -> Result<(), Error> { tokio::process::Command::from(cmd(self)).status() .await? @@ -76,6 +79,7 @@ pub struct SpusbInfo } +#[cfg_attr(feature = "tracing", tracing::instrument(fields(dev = dev.as_ref().serial_number())))] pub async fn volume_for(dev: Info) -> Result where Info: AsRef { if let Some(sn) = dev.as_ref().serial_number() { @@ -91,6 +95,7 @@ pub async fn volume_for(dev: Info) -> Result .map(Volume::from) } +#[cfg_attr(feature = "tracing", tracing::instrument(skip(devs)))] pub async fn volumes_for_map(devs: I) -> Result>, Error> where I: IntoIterator { let mut devs = devs.into_iter() @@ -127,6 +132,7 @@ pub async fn volumes_for_map(devs: I) -> Result( devs: I) -> Result>, &'i Device)>, Error> @@ -146,6 +152,7 @@ pub fn volumes_for<'i, I: 'i>( /// Call `system_profiler -json SPUSBDataType` +#[cfg_attr(feature = "tracing", tracing::instrument(skip(filter)))] fn spusb(filter: F) -> Result>>>, Error> where F: FnMut(&DeviceInfo) -> bool { @@ -198,6 +205,7 @@ fn spusb(filter: F) /// Calls `diskutil info -plist {partition.volume_uuid}` +#[cfg_attr(feature = "tracing", tracing::instrument(skip(par), fields(par.name = par.name.as_str())))] async fn mount_point_for_partition(par: MediaPartitionInfo) -> Result { use std::process::Command; diff --git a/support/device/src/mount/methods.rs b/support/device/src/mount/methods.rs index 10425199..13a26caa 100644 --- a/support/device/src/mount/methods.rs +++ b/support/device/src/mount/methods.rs @@ -20,6 +20,7 @@ use crate::interface::{self, AsyncSend}; type Result = std::result::Result; // TODO: make timeout configurable +#[cfg_attr(feature = "tracing", tracing::instrument(fields(dev = mount.info().serial_number(), mount = mount.handle.volume().path().as_ref().display().to_string())))] pub async fn wait_fs_available(mount: &MountedDevice) -> Result { const ITER: u64 = 120; // ms const RETRIES: u8 = 255; // ≈30 sec @@ -77,6 +78,7 @@ pub async fn wait_fs_available(mount: &MountedDevice) -> Result { } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn mount(query: Query) -> Result>> { match query.value { Some(QueryValue::Path(port)) => { @@ -96,6 +98,7 @@ pub async fn mount(query: Query) -> Result Result>> { let fut = mount(query).await?.flat_map(move |res| { async move { @@ -114,6 +117,7 @@ pub async fn mount_and(query: Query, wait: bool) -> Result) -> Result>>> { let devices = usb::discover::devices_with(sn)?; let mounting = devices.map(mount_dev); @@ -131,6 +135,7 @@ pub async fn mount_by_sn_mb(sn: Option) -> Result>( port: S) -> Result>>> { @@ -201,6 +206,7 @@ pub async fn mount_by_port_name>( } +#[cfg_attr(feature = "tracing", tracing::instrument(fields(dev = dev.info().serial_number())))] fn mount_dev(mut dev: Device) -> Result>> { dev.info().serial_number().map(|s| debug!("mounting {s}")); let fut = match dev.mode_cached() { @@ -225,6 +231,7 @@ fn mount_dev(mut dev: Device) -> Result Result { const ITER: u64 = 100; // ms const RETRIES: u8 = 100; // ≈10 sec @@ -266,6 +273,7 @@ async fn wait_mount_point(dev: Device) -> Result { } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn unmount(query: Query) -> Result>> { match query.value { Some(QueryValue::Path(path)) => { @@ -281,6 +289,7 @@ pub async fn unmount(query: Query) -> Result Result>> { let stream = Unordered::new(); unmount(query).await? @@ -300,6 +309,7 @@ pub async fn unmount_and_wait(query: Query) -> Result Result>> { let results = if wait { unmount_and_wait(query).await?.left_stream() @@ -313,6 +323,7 @@ pub async fn unmount_and(query: Query, wait: bool) -> Result) -> Result>> { let devs = devices_storage()?.filter(move |dev| { sn.as_ref() diff --git a/support/device/src/mount/mod.rs b/support/device/src/mount/mod.rs index 3e5d0d19..dfc398ca 100644 --- a/support/device/src/mount/mod.rs +++ b/support/device/src/mount/mod.rs @@ -97,12 +97,14 @@ pub struct MountedDevice { } impl Unmount for MountedDevice { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self), fields(dev = self.info().serial_number(), mount = self.handle.volume().path().as_ref().display().to_string())))] fn unmount_blocking(&self) -> Result<(), Error> { ::unmount_blocking(&self.handle.volume) } } impl UnmountAsync for MountedDevice where volume::Volume: UnmountAsync { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self), fields(dev = self.info().serial_number(), mount = self.handle.volume().path().as_ref().display().to_string())))] fn unmount(&self) -> impl std::future::Future> { ::unmount(&self.handle.volume) } @@ -145,7 +147,7 @@ impl MountHandle { impl Drop for MountHandle { fn drop(&mut self) { if self.unmount_on_drop { - debug!("Unmounting {}", self.volume); + trace!("Unmounting {} by drop", self.volume); let _ = self.volume .unmount_blocking() .map_err(|err| { diff --git a/support/device/src/mount/win.rs b/support/device/src/mount/win.rs index 9de23806..61f7fba9 100644 --- a/support/device/src/mount/win.rs +++ b/support/device/src/mount/win.rs @@ -19,6 +19,7 @@ use crate::usb::mode::{DeviceMode, Mode}; use crate::device::Device; +#[derive(Debug, Clone)] pub struct Volume { letter: char, disk_number: u32, @@ -138,6 +139,7 @@ mod unmount { } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn volume_for(dev: &Device) -> Result { if !matches!(dev.info().mode(), Mode::Storage) { return Err(Error::not_found()); @@ -147,6 +149,7 @@ pub async fn volume_for(dev: &Device) -> Result { .ok_or_else(|| Error::not_found()) } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn volumes_for(devs: &[Device]) -> impl Iterator { enumerate_volumes().filter_map(|vol| { devs.into_iter() @@ -156,6 +159,7 @@ pub fn volumes_for(devs: &[Device]) -> impl Iterator { } +#[cfg_attr(feature = "tracing", tracing::instrument(skip(devs)))] pub async fn volumes_for_map(devs: I) -> Result>, Error> where I: IntoIterator { let mut devs: Vec<_> = devs.into_iter().collect(); @@ -178,6 +182,7 @@ pub async fn volumes_for_map(devs: I) -> Result impl Iterator { const LETTERS: &'static str = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; let mask = unsafe { GetLogicalDrives() }; @@ -243,6 +248,7 @@ fn enumerate_volumes() -> impl Iterator { } +#[cfg_attr(feature = "tracing", tracing::instrument())] fn file_handle(letter: char) -> Result { use windows::Win32::Storage::FileSystem::{FILE_SHARE_READ, FILE_SHARE_WRITE, OPEN_EXISTING, FILE_FLAGS_AND_ATTRIBUTES}; @@ -269,7 +275,7 @@ struct FileHandle(pub HANDLE, Pin); impl Drop for FileHandle { fn drop(&mut self) { - trace!("closing file handle {:?}", self.0); + trace!("closing file handle {:?} by drop", self.0); unsafe { windows::Win32::Foundation::CloseHandle(self.0) }.map_err(|err| error!("{err}")) .ok(); } diff --git a/support/device/src/run.rs b/support/device/src/run.rs index c1773282..7dd85cfa 100644 --- a/support/device/src/run.rs +++ b/support/device/src/run.rs @@ -16,6 +16,7 @@ use crate::{install, device, usb, interface}; type Result = std::result::Result; +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn run_on_device(query: Query, pdx: PathBuf, no_install: bool, @@ -75,6 +76,7 @@ pub async fn run_on_device(query: Query, } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn run_with_sim(pdx: PathBuf, sdk: Option) -> Result<(), Error> { let sdk = sdk.map_or_else(|| Sdk::try_new(), Sdk::try_new_exact)?; diff --git a/support/device/src/send.rs b/support/device/src/send.rs index 148b9df4..778078d3 100644 --- a/support/device/src/send.rs +++ b/support/device/src/send.rs @@ -13,6 +13,7 @@ type Result = std::result::Result; /// Fails if can't map specified port to device in case of query is a port name/path. /// Use [[send_to_interfaces]] instead if device mapping not needed. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn send_to_devs(query: Query, cmd: Command, read: bool) @@ -50,6 +51,7 @@ pub async fn send_to_devs(query: Query, } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn send_to_interfaces(query: Query, cmd: Command) -> Result>> { diff --git a/support/device/src/serial/async.rs b/support/device/src/serial/async.rs index 9a2cb0b0..3626be54 100644 --- a/support/device/src/serial/async.rs +++ b/support/device/src/serial/async.rs @@ -14,6 +14,7 @@ use super::Interface; impl crate::interface::r#async::Out for Interface { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] async fn send_cmd(&self, cmd: crate::device::command::Command) -> Result { trace!("sending `{cmd}` to {}", self.info.port_name); if let Some(ref port) = self.port { diff --git a/support/device/src/serial/blocking.rs b/support/device/src/serial/blocking.rs index 63db2224..0e707953 100644 --- a/support/device/src/serial/blocking.rs +++ b/support/device/src/serial/blocking.rs @@ -5,6 +5,7 @@ use super::Interface; impl crate::interface::blocking::Out for Interface { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] fn send_cmd(&self, cmd: crate::device::command::Command) -> Result { trace!("sending `{cmd}` to {}", self.info.port_name); if let Some(ref port) = self.port { diff --git a/support/device/src/serial/discover.rs b/support/device/src/serial/discover.rs index 7eefa52a..2763f199 100644 --- a/support/device/src/serial/discover.rs +++ b/support/device/src/serial/discover.rs @@ -1,4 +1,5 @@ use std::borrow::Cow; +use std::fmt::Debug; use serialport::{SerialPortInfo, SerialPortType, available_ports}; @@ -8,6 +9,7 @@ use crate::{VENDOR_ID, PRODUCT_ID_DATA}; /// Enumerate all serial ports on the system for Playdate devices. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn ports() -> Result, Error> { let iter = available_ports()?.into_iter().filter(|port| { match port.port_type { @@ -22,8 +24,9 @@ pub fn ports() -> Result, Error> { /// Search exact one serial port for device with same serial number. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn port(sn: &SN) -> Result - where SN: PartialEq { + where SN: PartialEq + Debug { let port = ports()?.find(move |port| { match port.port_type { SerialPortType::UsbPort(ref info) => { @@ -38,8 +41,9 @@ pub fn port(sn: &SN) -> Result /// Search serial ports for device with same serial number, /// or __any__ Playdate- serial port if `sn` is `None`. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn ports_with(sn: Option) -> Result, Error> - where SN: PartialEq { + where SN: PartialEq + Debug { let ports = ports()?.filter(move |port| { match port.port_type { SerialPortType::UsbPort(ref info) => { @@ -67,8 +71,9 @@ pub fn ports_with(sn: Option) -> Result(sn: Option) -> Result, Error> - where SN: PartialEq { + where SN: PartialEq + Debug { let ports: Vec<_> = ports()?.collect(); let devs: Vec<_> = crate::usb::discover::devices_data()?.collect(); @@ -102,6 +107,7 @@ pub fn ports_with_or_single(sn: Option) -> Result Result + '_, Error> { diff --git a/support/device/src/serial/methods.rs b/support/device/src/serial/methods.rs index 9c0ec04c..a6e5deec 100644 --- a/support/device/src/serial/methods.rs +++ b/support/device/src/serial/methods.rs @@ -10,6 +10,7 @@ type Result = std::result::Result; /// Create `Device` with serial interface by given `port` name/path. +#[cfg_attr(feature = "tracing", tracing::instrument(fields(port = port.as_ref())))] pub async fn dev_with_port>(port: S) -> Result { use serialport::SerialPort; @@ -35,6 +36,7 @@ pub async fn dev_with_port>(port: S) -> Result { } +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn unknown_serial_port_info(port_name: Cow<'_, str>) -> serialport::SerialPortInfo { let unknown = serialport::SerialPortType::Unknown; serialport::SerialPortInfo { port_name: port_name.to_string(), @@ -44,6 +46,7 @@ pub fn unknown_serial_port_info(port_name: Cow<'_, str>) -> serialport::SerialPo /// Open given `interface` and read to stdout infinitely. #[cfg(feature = "tokio-serial")] +#[cfg_attr(feature = "tracing", tracing::instrument(skip(interface), fields(interface.port_name = interface.info().port_name)))] pub async fn redirect_interface_to_stdout(interface: &super::Interface) -> Result<(), Error> { let mut out = tokio::io::stdout(); let mut port = interface.port @@ -57,6 +60,7 @@ pub async fn redirect_interface_to_stdout(interface: &super::Interface) -> Resul /// Open given `port` and read to stdout infinitely. #[cfg(feature = "tokio-serial")] +#[cfg_attr(feature = "tracing", tracing::instrument(fields(port.name = serialport::SerialPort::name(port.as_ref()))))] pub async fn redirect_port_to_stdout(port: &mut super::Port) -> Result<(), Error> { let mut out = tokio::io::stdout(); tokio::io::copy(port, &mut out).await @@ -67,15 +71,17 @@ pub async fn redirect_port_to_stdout(port: &mut super::Port) -> Result<(), Error /// Open port by given `port` name/path and read to stdout infinitely. #[cfg(feature = "tokio-serial")] +#[cfg_attr(feature = "tracing", tracing::instrument())] pub async fn redirect_to_stdout(port: S) -> Result<(), Error> - where S: for<'a> Into> { + where S: for<'a> Into> + std::fmt::Debug { let mut port = super::open(port)?; redirect_port_to_stdout(&mut port).await } /// Open port by given `port` name/path and read to stdout infinitely. +#[cfg_attr(feature = "tracing", tracing::instrument())] pub fn redirect_to_stdout_blocking(port: S) -> Result<(), Error> - where S: for<'a> Into> { + where S: for<'a> Into> + std::fmt::Debug { let mut port = super::open(port)?; #[cfg(feature = "tokio-serial")] diff --git a/support/device/src/serial/mod.rs b/support/device/src/serial/mod.rs index dd148d53..dfbb4927 100644 --- a/support/device/src/serial/mod.rs +++ b/support/device/src/serial/mod.rs @@ -24,8 +24,10 @@ pub struct Interface { impl Interface { + #[cfg_attr(feature = "tracing", tracing::instrument)] pub fn new(info: serialport::SerialPortInfo) -> Self { Self { info, port: None } } + #[cfg_attr(feature = "tracing", tracing::instrument)] pub fn new_with(port: Port, name: Option) -> Self { use serialport::{SerialPort, SerialPortType, SerialPortInfo}; @@ -41,8 +43,10 @@ impl Interface { pub fn info(&self) -> &serialport::SerialPortInfo { &self.info } pub fn is_open(&self) -> bool { self.port.is_some() } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self), fields(self.port_name = self.info().port_name)))] pub fn set_port(&mut self, port: Port) { self.port = Some(RefCell::new(port)); } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self), fields(self.port_name = self.info().port_name)))] pub fn open(&mut self) -> Result<(), Error> { if self.port.is_some() { Ok(()) @@ -54,11 +58,14 @@ impl Interface { } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self), fields(self.port_name = self.info().port_name)))] pub fn close(&mut self) { self.port.take(); } } -pub fn open<'a>(port_name: impl Into>) -> Result { +#[cfg_attr(feature = "tracing", tracing::instrument)] +pub fn open<'a, S: Into>>(port_name: S) -> Result + where S: std::fmt::Debug { let builder = port_builder(port_name); #[cfg(not(feature = "tokio-serial"))] diff --git a/support/device/src/usb/discover.rs b/support/device/src/usb/discover.rs index 790b43d6..5c28a956 100644 --- a/support/device/src/usb/discover.rs +++ b/support/device/src/usb/discover.rs @@ -13,22 +13,26 @@ use super::Device; /// Enumerate all Playdate- devices. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn devices() -> Result, Error> { Ok(nusb::list_devices()?.filter(|d| d.vendor_id() == VENDOR_ID) .map(|info| Device::new(info))) } /// Search Playdate- devices that in data (serial/modem/telnet) mode. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn devices_data() -> Result, Error> { devices().map(|iter| iter.filter(|d| d.info.product_id() == PRODUCT_ID_DATA)) } /// Search Playdate- devices that in storage (data-disk) mode. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn devices_storage() -> Result, Error> { devices().map(|iter| iter.filter(|d| d.info.product_id() == PRODUCT_ID_STORAGE)) } /// Search exact one device with same serial number. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn device(sn: &Sn) -> Result { devices()?.find(|d| d.info.serial_number().filter(|s| sn.eq(s)).is_some()) .ok_or_else(|| Error::not_found()) @@ -36,6 +40,7 @@ pub fn device(sn: &Sn) -> Result { /// Search devices with same serial number, /// or __any__ Playdate- device if `sn` is `None`. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn devices_with(sn: Option) -> Result, Error> { Ok(devices()?.filter(move |dev| { if let Some(sn) = sn.as_ref() { @@ -48,6 +53,7 @@ pub fn devices_with(sn: Option) -> Result, Erro /// Search devices with same serial number in data mode, /// or __any__ Playdate- device if `sn` is `None`. +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn devices_data_with(sn: Option) -> Result, Error> { Ok(devices_data()?.filter(move |dev| { if let Some(sn) = sn.as_ref() { @@ -60,6 +66,7 @@ pub fn devices_data_with(sn: Option) -> Result, #[cfg(feature = "futures")] +#[cfg_attr(feature = "tracing", tracing::instrument)] pub async fn devices_data_for(query: query::DeviceQuery) -> Result, Error> { use query::DeviceQueryValue as Query; use serial::dev_with_port; @@ -123,6 +130,7 @@ pub async fn devices_data_for(query: query::DeviceQuery) -> Result, #[cfg(feature = "futures")] +#[cfg_attr(feature = "tracing", tracing::instrument(skip(f)))] pub async fn for_each_data_interface(query: query::DeviceQuery, mut f: F) -> Result, Error> diff --git a/support/device/src/usb/io.rs b/support/device/src/usb/io.rs index 66626ba0..dee31828 100644 --- a/support/device/src/usb/io.rs +++ b/support/device/src/usb/io.rs @@ -15,6 +15,7 @@ use crate::usb::mode::Mode; use crate::usb::BULK_IN; +#[cfg_attr(feature = "tracing", tracing::instrument(skip(interface)))] pub fn read_interface(interface: &Interface, buf_size: usize, bufs: usize) @@ -40,6 +41,7 @@ pub fn read_interface(interface: &Interface, Ok(stream) } +#[cfg_attr(feature = "tracing", tracing::instrument(skip(interface, map)))] pub fn read_while_map(interface: &Interface, buf_size: usize, buffers: usize, @@ -80,6 +82,7 @@ pub fn read_while_map(interface: &Interface, } +#[cfg_attr(feature = "tracing", tracing::instrument)] pub fn read_once(device: DeviceInfo) -> Result<(String, Interface), Error> { let mode = device.mode(); if !matches!(mode, Mode::Data) { @@ -110,6 +113,7 @@ pub fn read_once(device: DeviceInfo) -> Result<(String, Interface), Error> { } +#[cfg_attr(feature = "tracing", tracing::instrument)] pub async fn redirect_to_stdout(device: &mut Device) -> Result<(), Error> { let mode = device.mode(); if !matches!(mode, Mode::Data) { @@ -122,6 +126,7 @@ pub async fn redirect_to_stdout(device: &mut Device) -> Result<(), Error> { Ok(()) } +#[cfg_attr(feature = "tracing", tracing::instrument)] pub async fn redirect_interface_to_stdout(interface: &mut crate::interface::Interface) -> Result<(), Error> { match interface { crate::interface::Interface::Usb(interface) => { diff --git a/support/device/src/usb/mod.rs b/support/device/src/usb/mod.rs index e0086ad2..e1f149fe 100644 --- a/support/device/src/usb/mod.rs +++ b/support/device/src/usb/mod.rs @@ -26,6 +26,7 @@ pub mod io; const BULK_IN: u8 = 0x81; const BULK_OUT: u8 = 0x01; +const INTERRUPT_IN: u8 = 0x82; pub trait HaveDataInterface { @@ -34,7 +35,9 @@ pub trait HaveDataInterface { } impl HaveDataInterface for DeviceInfo { + #[cfg_attr(feature = "tracing", tracing::instrument)] fn data_interface(&self) -> Option<&InterfaceInfo> { self.interfaces().find(|i| i.class() == 0xA | 2) } + #[cfg_attr(feature = "tracing", tracing::instrument)] fn have_data_interface(&self) -> bool { self.data_interface().is_some() } } @@ -44,7 +47,9 @@ pub trait MassStorageInterface { } impl MassStorageInterface for DeviceInfo { + #[cfg_attr(feature = "tracing", tracing::instrument)] fn storage_interface(&self) -> Option<&InterfaceInfo> { self.interfaces().find(|i| i.class() == 8) } + #[cfg_attr(feature = "tracing", tracing::instrument)] fn have_storage_interface(&self) -> bool { self.storage_interface().is_some() } } @@ -55,6 +60,7 @@ impl Device { /// 1. [if changed] Update state of `this`, drop all pending transfers if needed /// to prevent future errors when send to unexisting interface. /// 1. Return `true` if `mode` changed. + #[cfg_attr(feature = "tracing", tracing::instrument)] pub fn refresh(&mut self) -> Result { let mode = self.info.mode(); if mode != self.mode { @@ -100,6 +106,7 @@ impl Device { /// Open USB interface if available, /// otherwise try open serial port if available. + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn open(&mut self) -> Result<(), Error> { if !matches!(self.mode, Mode::Data) { return Err(Error::WrongState(self.mode)); @@ -111,19 +118,20 @@ impl Device { } if self.info.have_data_interface() { - let bulk = self.open_bulk().map(|_| {}); + let bulk = self.try_bulk().map(|_| {}); if let Some(err) = bulk.err() { - self.open_serial().map_err(|err2| Error::chain(err, [err2])) + self.try_serial().map_err(|err2| Error::chain(err, [err2])) } else { self.interface() } } else { - self.open_serial() + self.try_serial() }?; Ok(()) } - fn open_bulk(&mut self) -> Result<&crate::interface::Interface, Error> { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] + fn try_bulk(&mut self) -> Result<&crate::interface::Interface, Error> { if let Some(ref io) = self.interface { Ok(io) } else if let Some(ref dev) = self.inner { @@ -137,7 +145,8 @@ impl Device { } } - fn open_serial(&mut self) -> Result<&crate::interface::Interface, Error> { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] + fn try_serial(&mut self) -> Result<&crate::interface::Interface, Error> { use crate::serial::Interface; @@ -174,17 +183,20 @@ impl Device { self.interface.as_mut().ok_or_else(|| Error::not_ready()) } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn set_interface(&mut self, interface: crate::interface::Interface) { self.close(); self.interface = Some(interface); } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn close(&mut self) { self.info.serial_number().map(|s| debug!("closing {s}")); self.interface.take(); self.inner.take(); } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn close_with_reset(&mut self) { self.info.serial_number().map(|s| debug!("closing* {s}")); self.interface.take(); @@ -192,6 +204,44 @@ impl Device { dev.reset().map_err(|err| error!("{err}")).ok(); } } + + + pub fn inspect(&self) { + inspect_device(self.info()); + // + } +} + + +/// Print debug information about device. +pub fn inspect_device(dev: &DeviceInfo) { + println!( + "Device {:03}.{:03} ({:04x}:{:04x}) {} {}", + dev.bus_number(), + dev.device_address(), + dev.vendor_id(), + dev.product_id(), + dev.manufacturer_string().unwrap_or(""), + dev.product_string().unwrap_or("") + ); + let dev = match dev.open() { + Ok(dev) => dev, + Err(e) => { + println!("Failed to open device: {}", e); + return; + }, + }; + + match dev.active_configuration() { + Ok(config) => println!("Active configuration is {}", config.configuration_value()), + Err(e) => println!("Unknown active configuration: {e}"), + } + + for config in dev.configurations() { + println!("{config:#?}"); + } + println!(""); + println!(""); } @@ -202,7 +252,7 @@ impl Device { // } impl crate::interface::blocking::Out for Interface { - #[inline(always)] + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] fn send_cmd(&self, cmd: Command) -> Result { futures_lite::future::block_on(self.write_cmd(cmd)).map_err(Into::into) } @@ -214,7 +264,7 @@ impl crate::interface::blocking::In for Interface { impl crate::interface::r#async::Out for Interface { - #[inline(always)] + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] async fn send_cmd(&self, cmd: Command) -> Result { self.write_cmd(cmd).await.map_err(Into::into) } @@ -230,12 +280,15 @@ pub struct Interface { } impl Interface { + #[cfg_attr(feature = "tracing", tracing::instrument(skip(inner)))] pub fn new(inner: nusb::Interface) -> Self { Self { inner } } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn write_cmd(&self, cmd: Command) -> impl std::future::Future> { self.write(cmd.with_break().as_bytes()) } + #[cfg_attr(feature = "tracing", tracing::instrument(skip(self)))] pub fn write(&self, data: &[u8]) -> impl std::future::Future> { self.inner.bulk_out(BULK_OUT, data.to_vec()).map(|comp| { // TODO: attach data to the pool diff --git a/support/tool2/Cargo.toml b/support/tool2/Cargo.toml index cd338f28..dd2fd0a0 100644 --- a/support/tool2/Cargo.toml +++ b/support/tool2/Cargo.toml @@ -15,6 +15,7 @@ repository.workspace = true [[bin]] path = "src/main.rs" name = "pdtool" +# required-features = ["tracing"] [dependencies] @@ -32,6 +33,12 @@ env_logger.workspace = true thiserror = "1.0" miette = { version = "7.2", features = ["fancy"] } +tracing = { version = "0.1", optional = true } +tracing-subscriber = { version = "0.3", optional = true } +console-subscriber = { version = "0.2", features = [ + "env-filter", +], optional = true } + [dependencies.clap] features = ["std", "env", "derive", "help", "usage", "color"] workspace = true @@ -40,3 +47,11 @@ workspace = true [dependencies.device] features = ["async", "tokio", "clap", "tokio-serial"] workspace = true + + +[features] +default = ["tracing"] +tracing = ["dep:tracing", "tracing-subscriber", "device/tracing"] + +# use with tokio-console, https://tokio.rs/tokio/topics/tracing-next-steps +tokio-tracing = ["tracing", "tokio/tracing", "console-subscriber", "tracing"] diff --git a/support/tool2/src/cli.rs b/support/tool2/src/cli.rs index 80e4aa1f..76f70c51 100644 --- a/support/tool2/src/cli.rs +++ b/support/tool2/src/cli.rs @@ -78,6 +78,8 @@ pub enum Command { /// Send command to specified device. // #[command(hide = true)] Send(#[command(flatten)] Send), + + Debug, } #[derive(ValueEnum, Debug, Clone, Copy)] diff --git a/support/tool2/src/main.rs b/support/tool2/src/main.rs index d4a62fc9..0fccc4b6 100644 --- a/support/tool2/src/main.rs +++ b/support/tool2/src/main.rs @@ -1,7 +1,11 @@ -// #![feature(exit_status_error)] +#[cfg(feature = "tracing")] +#[macro_use] +extern crate tracing; +#[cfg(not(feature = "tracing"))] #[macro_use] extern crate log; + extern crate device as pddev; use std::path::PathBuf; @@ -22,13 +26,66 @@ mod cli; mod report; +#[cfg(all(feature = "tracing", not(feature = "console-subscriber")))] +fn enable_tracing() { + use tracing::Level; + use tracing_subscriber::fmt::Subscriber; + + let subscriber = Subscriber::builder().compact() + .with_file(true) + .with_target(false) + .with_line_number(true) + .without_time() + .with_level(true) + .with_thread_ids(false) + .with_thread_names(true) + .with_max_level(Level::TRACE) + .finish(); + tracing::subscriber::set_global_default(subscriber).unwrap(); +} + +#[cfg(all(feature = "tracing", feature = "console-subscriber"))] +fn enable_tracing() { + use tracing::Level; + use console_subscriber::ConsoleLayer; + use tracing_subscriber::prelude::*; + + let console_layer = ConsoleLayer::builder().with_default_env().spawn(); + let fmt = tracing_subscriber::fmt::layer().with_file(true) + .with_target(false) + .with_line_number(true) + .without_time() + .with_level(true) + .with_thread_ids(true) + .with_thread_names(true) + .with_filter(tracing::level_filters::LevelFilter::from(Level::TRACE)); + + + tracing_subscriber::registry().with(console_layer) + .with(fmt) + .init(); +} + + #[tokio::main] async fn main() -> miette::Result<()> { + #[cfg(feature = "tracing")] + enable_tracing(); + #[cfg(not(feature = "tracing"))] + { + // std::env::set_var("RUST_LOG", "trace,nusb=warn,mio_serial=info,mio=info"); + std::env::set_var("RUST_LOG", "trace"); + env_logger::Builder::from_env(env_logger::Env::default()).format_indent(Some(3)) + .format_module_path(false) + .format_target(true) + .format_timestamp(None) + .init(); + } + let cfg = cli::parse(); - std::env::set_var("RUST_LOG", "trace,nusb=warn,mio_serial=info,mio=info"); - env_logger::init(); - debug!("cmd: {:#?}", cfg.cmd); + + debug!("cmd: {:?}", cfg.cmd); match cfg.cmd { cli::Command::List { kind } => discover(cfg.format, kind).await, @@ -52,10 +109,24 @@ async fn main() -> miette::Result<()> { run_with_sim(pdx, sdk, cfg.format).await }, cli::Command::Send(cli::Send { command, query, read }) => send(query, command, read, cfg.format).await, + + cli::Command::Debug => { + use mount::volume::volumes_for_map; + + volumes_for_map(usb::discover::devices()?).await? + .into_iter() + .map(|(dev, vol)| (dev, vol.map(|v| v.path().to_path_buf()))) + .for_each(|(dev, path)| { + dev.inspect(); + println!("vol: {path:?}"); + }); + Ok(()) + }, }.into_diagnostic() } +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn run_on_device(query: DeviceQuery, pdx: PathBuf, no_install: bool, @@ -93,6 +164,7 @@ async fn run_on_device(query: DeviceQuery, } +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn run_with_sim(pdx: PathBuf, sdk: Option, _format: cli::Format) -> Result<(), error::Error> { run::run_with_sim(pdx, sdk).await .inspect(|_| trace!("sim execution is done")) @@ -100,6 +172,7 @@ async fn run_with_sim(pdx: PathBuf, sdk: Option, _format: cli::Format) /// `mount_and_install` with report. +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn install_and(query: DeviceQuery, path: PathBuf, force: bool, @@ -142,6 +215,7 @@ async fn install_and(query: DeviceQuery, /// [[mount::mount_and]] with report. +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn mount_and(query: DeviceQuery, wait: bool, format: cli::Format) -> Result<(), error::Error> { if matches!(format, cli::Format::Json) { print!("["); @@ -178,6 +252,7 @@ async fn mount_and(query: DeviceQuery, wait: bool, format: cli::Format) -> Resul /// [[mount::unmount_and]] with report. +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn unmount_and(query: DeviceQuery, wait: bool, format: cli::Format) -> Result<(), error::Error> { let results: Vec<_> = mount::unmount_and(query, wait).await?.collect().await; for (i, res) in results.into_iter().enumerate() { @@ -203,6 +278,7 @@ async fn unmount_and(query: DeviceQuery, wait: bool, format: cli::Format) -> Res } +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn send(query: DeviceQuery, command: device::command::Command, read: bool, @@ -229,6 +305,7 @@ async fn send(query: DeviceQuery, } +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn read(query: DeviceQuery) -> Result<(), error::Error> { let by_dev = |mut device: device::Device| -> Result<_, Error> { device.info().serial_number().map(|s| trace!("reading {s}")); @@ -272,6 +349,7 @@ async fn read(query: DeviceQuery) -> Result<(), error::Error> { } +#[cfg_attr(feature = "tracing", tracing::instrument())] async fn discover(format: cli::Format, kind: cli::DeviceKind) -> Result<(), error::Error> { use mount::volume::volumes_for_map;