diff options
Diffstat (limited to 'vendor/tracing-tree')
-rw-r--r-- | vendor/tracing-tree/.cargo-checksum.json | 1 | ||||
-rw-r--r-- | vendor/tracing-tree/Cargo.lock | 334 | ||||
-rw-r--r-- | vendor/tracing-tree/Cargo.toml | 64 | ||||
-rw-r--r-- | vendor/tracing-tree/LICENSE-APACHE | 201 | ||||
-rw-r--r-- | vendor/tracing-tree/LICENSE-MIT | 21 | ||||
-rw-r--r-- | vendor/tracing-tree/README.md | 38 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/basic.rs | 83 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/basic.stdout | 41 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/quiet.rs | 80 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/quiet.stdout | 28 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/stderr.rs | 40 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/stderr.stderr | 111 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/wraparound.rs | 31 | ||||
-rw-r--r-- | vendor/tracing-tree/examples/wraparound.stdout | 96 | ||||
-rw-r--r-- | vendor/tracing-tree/src/format.rs | 425 | ||||
-rw-r--r-- | vendor/tracing-tree/src/lib.rs | 395 | ||||
-rw-r--r-- | vendor/tracing-tree/tests/ui.rs | 79 |
17 files changed, 2068 insertions, 0 deletions
diff --git a/vendor/tracing-tree/.cargo-checksum.json b/vendor/tracing-tree/.cargo-checksum.json new file mode 100644 index 000000000..c140e495f --- /dev/null +++ b/vendor/tracing-tree/.cargo-checksum.json @@ -0,0 +1 @@ +{"files":{"Cargo.lock":"e54b0301e8816a5e2d82ba08646102d89ee556d5e9150c571123a34013e6a79a","Cargo.toml":"734e1e9cf702e362c0661b968e92fd4599b732208a65634dd516d085449d45b2","LICENSE-APACHE":"c9c77d27bd737506eee1be90c11885fad935695714eafacd6725f41fff9ec8da","LICENSE-MIT":"d31139de68f7e19f9b32cd7de53dbb125b3c68522bbbb1d0c186c33112d34466","README.md":"589c2534836513b4edfa2811269767a9ac3c48da909c8ab936db3e646410dcf7","examples/basic.rs":"b56dad20aa283aae17a9c1364cc0326714cdc89d6a02a6329034e476b3597fd7","examples/basic.stdout":"49767873eb520f3e457b48d930fa86583d9ca5ef5571d67582b08dcb788ff6f2","examples/quiet.rs":"65a4cbb650cea4939ed274c2fd4d50c953151716fa6564b23393e1df6fb7afd7","examples/quiet.stdout":"d58a3240258279821b5d08e0d39ea60dee2dbd6a955f8639daf0d149ad0616fa","examples/stderr.rs":"ce0896f50be810908fb7083661bf39da6c9733ddef9188d40499313a40fe2c7a","examples/stderr.stderr":"8a0f6553fee903f159c6ea528dda6c5b193064ef9b58c765d1f3f60ecba5ac1f","examples/wraparound.rs":"7998f2e7b9e1f0dfc4b0cf11b1cdcf0f44c85aeaabbea9749113584ac7a3879f","examples/wraparound.stdout":"1c042231b3f8b20a843c18af063e43a51fcc852597dd1713f5878d4a8128271c","src/format.rs":"a986c0a259aec3135bcfd4908f6a80173dea03b3f57efe1dfa7c9d79f2b55257","src/lib.rs":"0a62652d641131ff67c31103331b977ca42ed268a1703aa7365180c70465f536","tests/ui.rs":"32a02ef41ae5cbabe13164f8d665b287b0bb764b2dc5bcb80443cb551df5289a"},"package":"d07e90b329c621ade432823988574e820212648aa40e7a2497777d58de0fb453"}
\ No newline at end of file diff --git a/vendor/tracing-tree/Cargo.lock b/vendor/tracing-tree/Cargo.lock new file mode 100644 index 000000000..82a94c9e0 --- /dev/null +++ b/vendor/tracing-tree/Cargo.lock @@ -0,0 +1,334 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "ansi_term" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d52a9bb7ec0cf484c551830a7ce27bd20d67eac647e1befb56b0be4ee39a55d2" +dependencies = [ + "winapi", +] + +[[package]] +name = "assert_cmd" +version = "1.0.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c98233c6673d8601ab23e77eb38f999c51100d46c5703b17288c57fddf3a1ffe" +dependencies = [ + "bstr", + "doc-comment", + "predicates", + "predicates-core", + "predicates-tree", + "wait-timeout", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", +] + +[[package]] +name = "cfg-if" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" + +[[package]] +name = "difflib" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6184e33543162437515c2e2b48714794e37845ec9851711914eec9d308f6ebe8" + +[[package]] +name = "doc-comment" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fea41bba32d969b513997752735605054bc0dfa92b4c56bf1189f2e174be7a10" + +[[package]] +name = "either" +version = "1.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e78d4f1cc4ae33bbfc157ed5d5a5ef3bc29227303d595861deb238fcec4e9457" + +[[package]] +name = "glob" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b919933a397b79c37e33b77bb2aa3dc8eb6e165ad809e58ff75bc7db2e34574" + +[[package]] +name = "hermit-abi" +version = "0.1.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62b467343b94ba476dcb2500d242dadbb39557df889310ac77c5d99100aaac33" +dependencies = [ + "libc", +] + +[[package]] +name = "itertools" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a9a9d19fa1e79b6215ff29b9d6880b706147f16e9b1dbb1e4e5947b5b02bc5e3" +dependencies = [ + "either", +] + +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + +[[package]] +name = "libc" +version = "0.2.126" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "349d5a591cd28b49e1d1037471617a32ddcda5731b99419008085f72d5a53836" + +[[package]] +name = "log" +version = "0.4.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "abb12e687cfb44aa40f41fc3978ef76448f9b6038cad6aef4259d3c095a2382e" +dependencies = [ + "cfg-if", +] + +[[package]] +name = "memchr" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" + +[[package]] +name = "once_cell" +version = "1.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7709cef83f0c1f58f666e746a08b21e0085f7440fa6a29cc194d68aac97a4225" + +[[package]] +name = "pin-project-lite" +version = "0.2.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" + +[[package]] +name = "predicates" +version = "2.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5aab5be6e4732b473071984b3164dbbfb7a3674d30ea5ff44410b6bcd960c3c" +dependencies = [ + "difflib", + "itertools", + "predicates-core", +] + +[[package]] +name = "predicates-core" +version = "1.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "da1c2388b1513e1b605fcec39a95e0a9e8ef088f71443ef37099fa9ae6673fcb" + +[[package]] +name = "predicates-tree" +version = "1.0.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d86de6de25020a36c6d3643a86d9a6a9f552107c0559c60ea03551b5e16c032" +dependencies = [ + "predicates-core", + "termtree", +] + +[[package]] +name = "proc-macro2" +version = "1.0.39" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c54b25569025b7fc9651de43004ae593a75ad88543b17178aa5e1b9c4f15f56f" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1feb54ed693b93a84e14094943b84b7c4eae204c512b7ccb95ab0c66d278ad1" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + +[[package]] +name = "sharded-slab" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "900fba806f70c630b0a382d0d825e17a0f19fcd059a2ade1ff237bcddf446b31" +dependencies = [ + "lazy_static", +] + +[[package]] +name = "syn" +version = "1.0.95" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fbaf6116ab8924f39d52792136fb74fd60a80194cf1b1c6ffa6453eef1c3f942" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "termtree" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "507e9898683b6c43a9aa55b64259b721b52ba226e0f3779137e50ad114a4c90b" + +[[package]] +name = "thread_local" +version = "1.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5516c27b78311c50bf42c071425c560ac799b11c30b31f87e3081965fe5e0180" +dependencies = [ + "once_cell", +] + +[[package]] +name = "tracing" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5d0ecdcb44a79f0fe9844f0c4f33a342cbcbb5117de8001e6ba0dc2351327d09" +dependencies = [ + "cfg-if", + "pin-project-lite", + "tracing-attributes", + "tracing-core", +] + +[[package]] +name = "tracing-attributes" +version = "0.1.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc6b8ad3567499f98a1db7a752b07a7c8c7c7c34c332ec00effb2b0027974b7c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "tracing-core" +version = "0.1.26" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f54c8ca710e81886d498c2fd3331b56c93aa248d49de2222ad2742247c60072f" +dependencies = [ + "lazy_static", + "valuable", +] + +[[package]] +name = "tracing-log" +version = "0.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "78ddad33d2d10b1ed7eb9d1f518a5674713876e97e5bb9b7345a7984fbb4f922" +dependencies = [ + "lazy_static", + "log", + "tracing-core", +] + +[[package]] +name = "tracing-subscriber" +version = "0.3.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4bc28f93baff38037f64e6f43d34cfa1605f27a49c34e8a04c5e78b0babf2596" +dependencies = [ + "sharded-slab", + "thread_local", + "tracing-core", +] + +[[package]] +name = "tracing-tree" +version = "0.2.1" +dependencies = [ + "ansi_term", + "assert_cmd", + "atty", + "glob", + "log", + "tracing", + "tracing-core", + "tracing-log", + "tracing-subscriber", +] + +[[package]] +name = "unicode-ident" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d22af068fba1eb5edcb4aea19d382b2a3deb4c8f9d475c589b6ada9e0fd493ee" + +[[package]] +name = "valuable" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" + +[[package]] +name = "wait-timeout" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9f200f5b12eb75f8c1ed65abd4b2db8a6e1b138a20de009dacee265a2498f3f6" +dependencies = [ + "libc", +] + +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/vendor/tracing-tree/Cargo.toml b/vendor/tracing-tree/Cargo.toml new file mode 100644 index 000000000..32c47092f --- /dev/null +++ b/vendor/tracing-tree/Cargo.toml @@ -0,0 +1,64 @@ +# THIS FILE IS AUTOMATICALLY GENERATED BY CARGO +# +# When uploading crates to the registry Cargo will automatically +# "normalize" Cargo.toml files for maximal compatibility +# with all versions of Cargo and also rewrite `path` dependencies +# to registry (e.g., crates.io) dependencies. +# +# If you are reading this file be aware that the original Cargo.toml +# will likely look very different (and much more reasonable). +# See Cargo.toml.orig for the original contents. + +[package] +edition = "2018" +name = "tracing-tree" +version = "0.2.1" +authors = [ + "David Barsky <me@davidbarsky.com>", + "Nathan Whitaker", +] +description = "A Tracing Layer which prints a tree of spans and events." +readme = "README.md" +license = "MIT OR Apache-2.0" +repository = "https://github.com/davidbarsky/tracing-tree" + +[[test]] +name = "ui" +harness = false + +[dependencies.ansi_term] +version = "0.12" + +[dependencies.atty] +version = "0.2" + +[dependencies.tracing-core] +version = "0.1" + +[dependencies.tracing-log] +version = "0.1" +optional = true + +[dependencies.tracing-subscriber] +version = "0.3" +features = [ + "registry", + "fmt", + "std", +] +default-features = false + +[dev-dependencies.assert_cmd] +version = "1" + +[dev-dependencies.glob] +version = "0.3" + +[dev-dependencies.log] +version = "0.4" + +[dev-dependencies.tracing] +version = "0.1" + +[features] +default = ["tracing-log"] diff --git a/vendor/tracing-tree/LICENSE-APACHE b/vendor/tracing-tree/LICENSE-APACHE new file mode 100644 index 000000000..cb38739ee --- /dev/null +++ b/vendor/tracing-tree/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2021 tracing-tree contributors + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/vendor/tracing-tree/LICENSE-MIT b/vendor/tracing-tree/LICENSE-MIT new file mode 100644 index 000000000..d0afab4a5 --- /dev/null +++ b/vendor/tracing-tree/LICENSE-MIT @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 tracing-tree contributors + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/vendor/tracing-tree/README.md b/vendor/tracing-tree/README.md new file mode 100644 index 000000000..06751d4ec --- /dev/null +++ b/vendor/tracing-tree/README.md @@ -0,0 +1,38 @@ +# tracing-tree + +Instrument your application with [tracing](https://github.com/tokio-rs/tracing) +and get tree-structured summaries of your application activity with timing +information on the console: + +<pre> + <b>server</b>{host="localhost", port=8080<b>}</b> + 0ms <b> INFO</b> starting + 300ms <b> INFO</b> listening + <b>conn</b>{peer_addr="82.9.9.9", port=42381<b>}</b> + 0ms <b>DEBUG</b> connected + 300ms <b>DEBUG</b> message received, length=2 + <b>conn</b>{peer_addr="8.8.8.8", port=18230<b>}</b> + 300ms <b>DEBUG</b> connected + <b>conn</b>{peer_addr="82.9.9.9", port=42381<b>}</b> + 600ms <b> WARN</b> weak encryption requested, algo="xor" + 901ms <b>DEBUG</b> response sent, length=8 + 901ms <b>DEBUG</b> disconnected + <b>conn</b>{peer_addr="8.8.8.8", port=18230<b>}</b> + 600ms <b>DEBUG</b> message received, length=5 + 901ms <b>DEBUG</b> response sent, length=8 + 901ms <b>DEBUG</b> disconnected + 1502ms <b> WARN</b> internal error + 1502ms <b> INFO</b> exit +</pre> + +(Format inspired by [slog-term](https://github.com/slog-rs/slog#terminal-output-example)) + +## Setup + +After instrumenting your app with +[tracing](https://github.com/tokio-rs/tracing), add this subscriber like this: + +```rust +let subscriber = Registry::default().with(HierarchicalLayer::new(2)); +tracing::subscriber::set_global_default(subscriber).unwrap(); +```
\ No newline at end of file diff --git a/vendor/tracing-tree/examples/basic.rs b/vendor/tracing-tree/examples/basic.rs new file mode 100644 index 000000000..97f6263ff --- /dev/null +++ b/vendor/tracing-tree/examples/basic.rs @@ -0,0 +1,83 @@ +use tracing::{debug, error, info, instrument, span, warn, Level}; +use tracing_subscriber::{layer::SubscriberExt, registry::Registry}; +use tracing_tree::HierarchicalLayer; + +fn main() { + let layer = HierarchicalLayer::default() + .with_writer(std::io::stdout) + .with_indent_lines(true) + .with_indent_amount(2) + .with_thread_names(true) + .with_thread_ids(true) + .with_verbose_exit(true) + .with_verbose_entry(true) + .with_targets(true); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + #[cfg(feature = "tracing-log")] + tracing_log::LogTracer::init().unwrap(); + + let app_span = span!(Level::TRACE, "hierarchical-example", version = %0.1); + let _e = app_span.enter(); + + let server_span = span!(Level::TRACE, "server", host = "localhost", port = 8080); + let _e2 = server_span.enter(); + info!("starting"); + std::thread::sleep(std::time::Duration::from_millis(300)); + info!("listening"); + let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381); + peer1.in_scope(|| { + debug!("connected"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 2, "message received"); + }); + drop(peer1); + let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230); + peer2.in_scope(|| { + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!("connected"); + }); + drop(peer2); + let peer3 = span!( + Level::TRACE, + "foomp", + normal_var = 43, + "{} <- format string", + 42 + ); + peer3.in_scope(|| { + error!("hello"); + }); + drop(peer3); + let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381); + peer1.in_scope(|| { + warn!(algo = "xor", "weak encryption requested"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 8, "response sent"); + debug!("disconnected"); + }); + drop(peer1); + let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230); + peer2.in_scope(|| { + debug!(length = 5, "message received"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 8, "response sent"); + debug!("disconnected"); + }); + drop(peer2); + warn!("internal error"); + log::error!("this is a log message"); + info!("exit"); +} + +#[instrument] +fn call_a(name: &str) { + info!(name, "got a name"); + call_b(name) +} + +#[instrument] +fn call_b(name: &str) { + info!(name, "got a name"); +} diff --git a/vendor/tracing-tree/examples/basic.stdout b/vendor/tracing-tree/examples/basic.stdout new file mode 100644 index 000000000..4a2d83f11 --- /dev/null +++ b/vendor/tracing-tree/examples/basic.stdout @@ -0,0 +1,41 @@ +1:main┐basic::hierarchical-example version=0.1 +1:main├┐basic::hierarchical-example version=0.1 +1:main│└┐basic::server host="localhost", port=8080 +1:main│ ├─ms INFO basic starting +1:main│ ├─ms INFO basic listening +1:main│ ├┐basic::server host="localhost", port=8080 +1:main│ │└┐basic::conn peer_addr="82.9.9.9", port=42381 +1:main│ │ ├─ms DEBUG basic connected +1:main│ │ ├─ms DEBUG basic message received, length=2 +1:main│ │┌┘basic::conn peer_addr="82.9.9.9", port=42381 +1:main│ ├┘basic::server host="localhost", port=8080 +1:main│ ├┐basic::server host="localhost", port=8080 +1:main│ │└┐basic::conn peer_addr="8.8.8.8", port=18230 +1:main│ │ ├─ms DEBUG basic connected +1:main│ │┌┘basic::conn peer_addr="8.8.8.8", port=18230 +1:main│ ├┘basic::server host="localhost", port=8080 +1:main│ ├┐basic::server host="localhost", port=8080 +1:main│ │└┐basic::foomp 42 <- format string, normal_var=43 +1:main│ │ ├─ms ERROR basic hello +1:main│ │┌┘basic::foomp 42 <- format string, normal_var=43 +1:main│ ├┘basic::server host="localhost", port=8080 +1:main│ ├┐basic::server host="localhost", port=8080 +1:main│ │└┐basic::conn peer_addr="82.9.9.9", port=42381 +1:main│ │ ├─ms WARN basic weak encryption requested, algo="xor" +1:main│ │ ├─ms DEBUG basic response sent, length=8 +1:main│ │ ├─ms DEBUG basic disconnected +1:main│ │┌┘basic::conn peer_addr="82.9.9.9", port=42381 +1:main│ ├┘basic::server host="localhost", port=8080 +1:main│ ├┐basic::server host="localhost", port=8080 +1:main│ │└┐basic::conn peer_addr="8.8.8.8", port=18230 +1:main│ │ ├─ms DEBUG basic message received, length=5 +1:main│ │ ├─ms DEBUG basic response sent, length=8 +1:main│ │ ├─ms DEBUG basic disconnected +1:main│ │┌┘basic::conn peer_addr="8.8.8.8", port=18230 +1:main│ ├┘basic::server host="localhost", port=8080 +1:main│ ├─ms WARN basic internal error +1:main│ ├─ms ERROR basic this is a log message +1:main│ ├─ms INFO basic exit +1:main│┌┘basic::server host="localhost", port=8080 +1:main├┘basic::hierarchical-example version=0.1 +1:main┘basic::hierarchical-example version=0.1 diff --git a/vendor/tracing-tree/examples/quiet.rs b/vendor/tracing-tree/examples/quiet.rs new file mode 100644 index 000000000..81b0c9c2f --- /dev/null +++ b/vendor/tracing-tree/examples/quiet.rs @@ -0,0 +1,80 @@ +use tracing::{debug, error, info, instrument, span, warn, Level}; +use tracing_subscriber::{layer::SubscriberExt, registry::Registry}; +use tracing_tree::HierarchicalLayer; + +fn main() { + let layer = HierarchicalLayer::default() + .with_writer(std::io::stdout) + .with_indent_lines(true) + .with_indent_amount(2) + .with_thread_names(true) + .with_thread_ids(true) + .with_verbose_exit(false) + .with_verbose_entry(false) + .with_targets(true); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + let app_span = span!(Level::TRACE, "hierarchical-example", version = %0.1); + let _e = app_span.enter(); + + let server_span = span!(Level::TRACE, "server", host = "localhost", port = 8080); + let _e2 = server_span.enter(); + info!("starting"); + std::thread::sleep(std::time::Duration::from_millis(300)); + info!("listening"); + let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381); + peer1.in_scope(|| { + debug!("connected"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 2, "message received"); + }); + drop(peer1); + let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230); + peer2.in_scope(|| { + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!("connected"); + }); + drop(peer2); + let peer3 = span!( + Level::TRACE, + "foomp", + normal_var = 43, + "{} <- format string", + 42 + ); + peer3.in_scope(|| { + error!("hello"); + }); + drop(peer3); + let peer1 = span!(Level::TRACE, "conn", peer_addr = "82.9.9.9", port = 42381); + peer1.in_scope(|| { + warn!(algo = "xor", "weak encryption requested"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 8, "response sent"); + debug!("disconnected"); + }); + drop(peer1); + let peer2 = span!(Level::TRACE, "conn", peer_addr = "8.8.8.8", port = 18230); + peer2.in_scope(|| { + debug!(length = 5, "message received"); + std::thread::sleep(std::time::Duration::from_millis(300)); + debug!(length = 8, "response sent"); + debug!("disconnected"); + }); + drop(peer2); + warn!("internal error"); + info!("exit"); +} + +#[instrument] +fn call_a(name: &str) { + info!(name, "got a name"); + call_b(name) +} + +#[instrument] +fn call_b(name: &str) { + info!(name, "got a name"); +} diff --git a/vendor/tracing-tree/examples/quiet.stdout b/vendor/tracing-tree/examples/quiet.stdout new file mode 100644 index 000000000..96589655a --- /dev/null +++ b/vendor/tracing-tree/examples/quiet.stdout @@ -0,0 +1,28 @@ +1:main┐quiet::hierarchical-example version=0.1 +1:main├─┐quiet::server host="localhost", port=8080 +1:main│ ├─ms INFO quiet starting +1:main│ ├─ms INFO quiet listening +1:main│ ├─┐quiet::conn peer_addr="82.9.9.9", port=42381 +1:main│ │ ├─ms DEBUG quiet connected +1:main│ │ ├─ms DEBUG quiet message received, length=2 +1:main│ ├─┘ +1:main│ ├─┐quiet::conn peer_addr="8.8.8.8", port=18230 +1:main│ │ ├─ms DEBUG quiet connected +1:main│ ├─┘ +1:main│ ├─┐quiet::foomp 42 <- format string, normal_var=43 +1:main│ │ ├─ms ERROR quiet hello +1:main│ ├─┘ +1:main│ ├─┐quiet::conn peer_addr="82.9.9.9", port=42381 +1:main│ │ ├─ms WARN quiet weak encryption requested, algo="xor" +1:main│ │ ├─ms DEBUG quiet response sent, length=8 +1:main│ │ ├─ms DEBUG quiet disconnected +1:main│ ├─┘ +1:main│ ├─┐quiet::conn peer_addr="8.8.8.8", port=18230 +1:main│ │ ├─ms DEBUG quiet message received, length=5 +1:main│ │ ├─ms DEBUG quiet response sent, length=8 +1:main│ │ ├─ms DEBUG quiet disconnected +1:main│ ├─┘ +1:main│ ├─ms WARN quiet internal error +1:main│ ├─ms INFO quiet exit +1:main├─┘ +1:main┘ diff --git a/vendor/tracing-tree/examples/stderr.rs b/vendor/tracing-tree/examples/stderr.rs new file mode 100644 index 000000000..75880a376 --- /dev/null +++ b/vendor/tracing-tree/examples/stderr.rs @@ -0,0 +1,40 @@ +use tracing::{debug, info, instrument}; +use tracing_subscriber::{layer::SubscriberExt, registry::Registry}; +use tracing_tree::HierarchicalLayer; + +#[instrument] +fn nth_fibonacci(n: u64) -> u64 { + if n == 0 || n == 1 { + debug!("Base case"); + 1 + } else { + debug!("Recursing"); + nth_fibonacci(n - 1) + nth_fibonacci(n - 2) + } +} + +#[instrument] +fn fibonacci_seq(to: u64) -> Vec<u64> { + let mut sequence = vec![]; + + for n in 0..=to { + debug!("Pushing {n} fibonacci", n = n); + sequence.push(nth_fibonacci(n)); + } + + sequence +} + +fn main() { + let layer = HierarchicalLayer::default() + .with_indent_lines(true) + .with_indent_amount(2) + .with_bracketed_fields(true); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + let n = 5; + let sequence = fibonacci_seq(n); + info!("The first {} fibonacci numbers are {:?}", n, sequence); +} diff --git a/vendor/tracing-tree/examples/stderr.stderr b/vendor/tracing-tree/examples/stderr.stderr new file mode 100644 index 000000000..0060f268f --- /dev/null +++ b/vendor/tracing-tree/examples/stderr.stderr @@ -0,0 +1,111 @@ +┐fibonacci_seq{to=5} +├─ms DEBUG Pushing 0 fibonacci +├─┐nth_fibonacci{n=0} +│ ├─ms DEBUG Base case +├─┘ +├─ms DEBUG Pushing 1 fibonacci +├─┐nth_fibonacci{n=1} +│ ├─ms DEBUG Base case +├─┘ +├─ms DEBUG Pushing 2 fibonacci +├─┐nth_fibonacci{n=2} +│ ├─ms DEBUG Recursing +│ ├─┐nth_fibonacci{n=1} +│ │ ├─ms DEBUG Base case +│ ├─┘ +│ ├─┐nth_fibonacci{n=0} +│ │ ├─ms DEBUG Base case +│ ├─┘ +├─┘ +├─ms DEBUG Pushing 3 fibonacci +├─┐nth_fibonacci{n=3} +│ ├─ms DEBUG Recursing +│ ├─┐nth_fibonacci{n=2} +│ │ ├─ms DEBUG Recursing +│ │ ├─┐nth_fibonacci{n=1} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ │ ├─┐nth_fibonacci{n=0} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ ├─┘ +│ ├─┐nth_fibonacci{n=1} +│ │ ├─ms DEBUG Base case +│ ├─┘ +├─┘ +├─ms DEBUG Pushing 4 fibonacci +├─┐nth_fibonacci{n=4} +│ ├─ms DEBUG Recursing +│ ├─┐nth_fibonacci{n=3} +│ │ ├─ms DEBUG Recursing +│ │ ├─┐nth_fibonacci{n=2} +│ │ │ ├─ms DEBUG Recursing +│ │ │ ├─┐nth_fibonacci{n=1} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ │ ├─┐nth_fibonacci{n=0} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ ├─┘ +│ │ ├─┐nth_fibonacci{n=1} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ ├─┘ +│ ├─┐nth_fibonacci{n=2} +│ │ ├─ms DEBUG Recursing +│ │ ├─┐nth_fibonacci{n=1} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ │ ├─┐nth_fibonacci{n=0} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ ├─┘ +├─┘ +├─ms DEBUG Pushing 5 fibonacci +├─┐nth_fibonacci{n=5} +│ ├─ms DEBUG Recursing +│ ├─┐nth_fibonacci{n=4} +│ │ ├─ms DEBUG Recursing +│ │ ├─┐nth_fibonacci{n=3} +│ │ │ ├─ms DEBUG Recursing +│ │ │ ├─┐nth_fibonacci{n=2} +│ │ │ │ ├─ms DEBUG Recursing +│ │ │ │ ├─┐nth_fibonacci{n=1} +│ │ │ │ │ ├─ms DEBUG Base case +│ │ │ │ ├─┘ +│ │ │ │ ├─┐nth_fibonacci{n=0} +│ │ │ │ │ ├─ms DEBUG Base case +│ │ │ │ ├─┘ +│ │ │ ├─┘ +│ │ │ ├─┐nth_fibonacci{n=1} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ ├─┘ +│ │ ├─┐nth_fibonacci{n=2} +│ │ │ ├─ms DEBUG Recursing +│ │ │ ├─┐nth_fibonacci{n=1} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ │ ├─┐nth_fibonacci{n=0} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ ├─┘ +│ ├─┘ +│ ├─┐nth_fibonacci{n=3} +│ │ ├─ms DEBUG Recursing +│ │ ├─┐nth_fibonacci{n=2} +│ │ │ ├─ms DEBUG Recursing +│ │ │ ├─┐nth_fibonacci{n=1} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ │ ├─┐nth_fibonacci{n=0} +│ │ │ │ ├─ms DEBUG Base case +│ │ │ ├─┘ +│ │ ├─┘ +│ │ ├─┐nth_fibonacci{n=1} +│ │ │ ├─ms DEBUG Base case +│ │ ├─┘ +│ ├─┘ +├─┘ +┘ +INFO The first 5 fibonacci numbers are [1, 1, 2, 3, 5, 8] diff --git a/vendor/tracing-tree/examples/wraparound.rs b/vendor/tracing-tree/examples/wraparound.rs new file mode 100644 index 000000000..e045eb9f2 --- /dev/null +++ b/vendor/tracing-tree/examples/wraparound.rs @@ -0,0 +1,31 @@ +use tracing::{instrument, warn}; +use tracing_subscriber::{layer::SubscriberExt, registry::Registry}; +use tracing_tree::HierarchicalLayer; + +fn main() { + let layer = HierarchicalLayer::default() + .with_writer(std::io::stdout) + .with_indent_lines(true) + .with_indent_amount(2) + .with_thread_names(true) + .with_thread_ids(true) + .with_targets(true) + .with_wraparound(5); + + let subscriber = Registry::default().with(layer); + tracing::subscriber::set_global_default(subscriber).unwrap(); + + recurse(0); +} + +#[instrument] +fn recurse(i: usize) { + warn!("boop"); + if i > 20 { + warn!("bop"); + return; + } else { + recurse(i + 1); + } + warn!("bop"); +} diff --git a/vendor/tracing-tree/examples/wraparound.stdout b/vendor/tracing-tree/examples/wraparound.stdout new file mode 100644 index 000000000..bbf422545 --- /dev/null +++ b/vendor/tracing-tree/examples/wraparound.stdout @@ -0,0 +1,96 @@ +1:main┐wraparound::recurse i=0 +1:main├─ms WARN wraparound boop +1:main├─┐wraparound::recurse i=1 +1:main│ ├─ms WARN wraparound boop +1:main│ ├─┐wraparound::recurse i=2 +1:main│ │ ├─ms WARN wraparound boop +1:main│ │ ├─┐wraparound::recurse i=3 +1:main│ │ │ ├─ms WARN wraparound boop +1:main│ │ │ ├─┐wraparound::recurse i=4 +1:main────────┘ +1:mainms WARN wraparound boop +1:main┐wraparound::recurse i=5 +1:main├─ms WARN wraparound boop +1:main├─┐wraparound::recurse i=6 +1:main│ ├─ms WARN wraparound boop +1:main│ ├─┐wraparound::recurse i=7 +1:main│ │ ├─ms WARN wraparound boop +1:main│ │ ├─┐wraparound::recurse i=8 +1:main│ │ │ ├─ms WARN wraparound boop +1:main│ │ │ ├─┐wraparound::recurse i=9 +1:main────────┘ +1:mainms WARN wraparound boop +1:main┐wraparound::recurse i=10 +1:main├─ms WARN wraparound boop +1:main├─┐wraparound::recurse i=11 +1:main│ ├─ms WARN wraparound boop +1:main│ ├─┐wraparound::recurse i=12 +1:main│ │ ├─ms WARN wraparound boop +1:main│ │ ├─┐wraparound::recurse i=13 +1:main│ │ │ ├─ms WARN wraparound boop +1:main│ │ │ ├─┐wraparound::recurse i=14 +1:main────────┘ +1:mainms WARN wraparound boop +1:main┐wraparound::recurse i=15 +1:main├─ms WARN wraparound boop +1:main├─┐wraparound::recurse i=16 +1:main│ ├─ms WARN wraparound boop +1:main│ ├─┐wraparound::recurse i=17 +1:main│ │ ├─ms WARN wraparound boop +1:main│ │ ├─┐wraparound::recurse i=18 +1:main│ │ │ ├─ms WARN wraparound boop +1:main│ │ │ ├─┐wraparound::recurse i=19 +1:main────────┘ +1:mainms WARN wraparound boop +1:main┐wraparound::recurse i=20 +1:main├─ms WARN wraparound boop +1:main├─┐wraparound::recurse i=21 +1:main│ ├─ms WARN wraparound boop +1:main│ ├─ms WARN wraparound bop +1:main├─┘ +1:main├─ms WARN wraparound bop +1:main┘ +1:mainms WARN wraparound bop +1:main────────┐ +1:main│ │ │ ├─┘ +1:main│ │ │ ├─ms WARN wraparound bop +1:main│ │ ├─┘ +1:main│ │ ├─ms WARN wraparound bop +1:main│ ├─┘ +1:main│ ├─ms WARN wraparound bop +1:main├─┘ +1:main├─ms WARN wraparound bop +1:main┘ +1:mainms WARN wraparound bop +1:main────────┐ +1:main│ │ │ ├─┘ +1:main│ │ │ ├─ms WARN wraparound bop +1:main│ │ ├─┘ +1:main│ │ ├─ms WARN wraparound bop +1:main│ ├─┘ +1:main│ ├─ms WARN wraparound bop +1:main├─┘ +1:main├─ms WARN wraparound bop +1:main┘ +1:mainms WARN wraparound bop +1:main────────┐ +1:main│ │ │ ├─┘ +1:main│ │ │ ├─ms WARN wraparound bop +1:main│ │ ├─┘ +1:main│ │ ├─ms WARN wraparound bop +1:main│ ├─┘ +1:main│ ├─ms WARN wraparound bop +1:main├─┘ +1:main├─ms WARN wraparound bop +1:main┘ +1:mainms WARN wraparound bop +1:main────────┐ +1:main│ │ │ ├─┘ +1:main│ │ │ ├─ms WARN wraparound bop +1:main│ │ ├─┘ +1:main│ │ ├─ms WARN wraparound bop +1:main│ ├─┘ +1:main│ ├─ms WARN wraparound bop +1:main├─┘ +1:main├─ms WARN wraparound bop +1:main┘ diff --git a/vendor/tracing-tree/src/format.rs b/vendor/tracing-tree/src/format.rs new file mode 100644 index 000000000..067ea9771 --- /dev/null +++ b/vendor/tracing-tree/src/format.rs @@ -0,0 +1,425 @@ +use ansi_term::Color; +use std::{ + fmt::{self, Write as _}, + io, +}; +use tracing_core::{ + field::{Field, Visit}, + Level, +}; + +pub(crate) const LINE_VERT: &str = "│"; +const LINE_HORIZ: &str = "─"; +pub(crate) const LINE_BRANCH: &str = "├"; +pub(crate) const LINE_CLOSE: &str = "┘"; +pub(crate) const LINE_OPEN: &str = "┐"; + +#[derive(Copy, Clone)] +pub(crate) enum SpanMode { + PreOpen, + Open { verbose: bool }, + Close { verbose: bool }, + PostClose, + Event, +} + +#[derive(Debug)] +pub struct Config { + /// Whether to use colors. + pub ansi: bool, + /// Whether an ascii art tree is used or (if false) whether to just use whitespace indent + pub indent_lines: bool, + /// The amount of chars to indent. + pub indent_amount: usize, + /// Whether to show the module paths. + pub targets: bool, + /// Whether to show thread ids. + pub render_thread_ids: bool, + /// Whether to show thread names. + pub render_thread_names: bool, + /// Specifies after how many indentation levels we will wrap back around to zero + pub wraparound: usize, + /// Whether to print the current span before activating a new one + pub verbose_entry: bool, + /// Whether to print the current span before exiting it. + pub verbose_exit: bool, + /// Whether to print squiggly brackets (`{}`) around the list of fields in a span. + pub bracketed_fields: bool, +} + +impl Config { + pub fn with_ansi(self, ansi: bool) -> Self { + Self { ansi, ..self } + } + + pub fn with_indent_lines(self, indent_lines: bool) -> Self { + Self { + indent_lines, + ..self + } + } + + pub fn with_targets(self, targets: bool) -> Self { + Self { targets, ..self } + } + + pub fn with_thread_ids(self, render_thread_ids: bool) -> Self { + Self { + render_thread_ids, + ..self + } + } + + pub fn with_thread_names(self, render_thread_names: bool) -> Self { + Self { + render_thread_names, + ..self + } + } + + pub fn with_wraparound(self, wraparound: usize) -> Self { + Self { wraparound, ..self } + } + + pub fn with_verbose_entry(self, verbose_entry: bool) -> Self { + Self { + verbose_entry, + ..self + } + } + + pub fn with_verbose_exit(self, verbose_exit: bool) -> Self { + Self { + verbose_exit, + ..self + } + } + + pub fn with_bracketed_fields(self, bracketed_fields: bool) -> Self { + Self { + bracketed_fields, + ..self + } + } + + pub(crate) fn prefix(&self) -> String { + let mut buf = String::new(); + if self.render_thread_ids { + write!(buf, "{:?}", std::thread::current().id()).unwrap(); + if buf.ends_with(')') { + buf.truncate(buf.len() - 1); + } + if buf.starts_with("ThreadId(") { + buf.drain(0.."ThreadId(".len()); + } + } + if self.render_thread_names { + if let Some(name) = std::thread::current().name() { + if self.render_thread_ids { + buf.push(':'); + } + buf.push_str(name); + } + } + buf + } +} + +impl Default for Config { + fn default() -> Self { + Self { + ansi: true, + indent_lines: false, + indent_amount: 2, + targets: false, + render_thread_ids: false, + render_thread_names: false, + wraparound: usize::max_value(), + verbose_entry: false, + verbose_exit: false, + bracketed_fields: false, + } + } +} + +#[derive(Debug)] +pub struct Buffers { + pub current_buf: String, + pub indent_buf: String, +} + +impl Buffers { + pub fn new() -> Self { + Self { + current_buf: String::new(), + indent_buf: String::new(), + } + } + + pub fn flush_current_buf(&mut self, mut writer: impl io::Write) { + write!(writer, "{}", &self.current_buf).unwrap(); + self.current_buf.clear(); + } + + pub fn flush_indent_buf(&mut self) { + self.current_buf.push_str(&self.indent_buf); + self.indent_buf.clear(); + } + + pub(crate) fn indent_current(&mut self, indent: usize, config: &Config, style: SpanMode) { + self.current_buf.push('\n'); + let prefix = config.prefix(); + + // Render something when wraparound occurs so the user is aware of it + if config.indent_lines { + match style { + SpanMode::Close { .. } | SpanMode::PostClose => { + if indent > 0 && (indent + 1) % config.wraparound == 0 { + self.indent_buf.push_str(&prefix); + for _ in 0..(indent % config.wraparound * config.indent_amount) { + self.indent_buf.push_str(LINE_HORIZ); + } + self.indent_buf.push_str(LINE_OPEN); + self.indent_buf.push('\n'); + } + } + _ => {} + } + } + + indent_block( + &mut self.current_buf, + &mut self.indent_buf, + indent % config.wraparound, + config.indent_amount, + config.indent_lines, + &prefix, + style, + ); + self.current_buf.clear(); + self.flush_indent_buf(); + + // Render something when wraparound occurs so the user is aware of it + if config.indent_lines { + match style { + SpanMode::PreOpen | SpanMode::Open { .. } => { + if indent > 0 && (indent + 1) % config.wraparound == 0 { + self.current_buf.push_str(&prefix); + for _ in 0..(indent % config.wraparound * config.indent_amount) { + self.current_buf.push_str(LINE_HORIZ); + } + self.current_buf.push_str(LINE_CLOSE); + self.current_buf.push('\n'); + } + } + _ => {} + } + } + } +} + +pub struct FmtEvent<'a> { + pub bufs: &'a mut Buffers, + pub comma: bool, +} + +impl<'a> Visit for FmtEvent<'a> { + fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { + let buf = &mut self.bufs.current_buf; + let comma = if self.comma { "," } else { "" }; + match field.name() { + "message" => { + write!(buf, "{} {:?}", comma, value).unwrap(); + self.comma = true; + } + // Skip fields that are actually log metadata that have already been handled + #[cfg(feature = "tracing-log")] + name if name.starts_with("log.") => {} + name => { + write!(buf, "{} {}={:?}", comma, name, value).unwrap(); + self.comma = true; + } + } + } +} + +pub struct ColorLevel<'a>(pub &'a Level); + +impl<'a> fmt::Display for ColorLevel<'a> { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + match *self.0 { + Level::TRACE => Color::Purple.bold().paint("TRACE"), + Level::DEBUG => Color::Blue.bold().paint("DEBUG"), + Level::INFO => Color::Green.bold().paint(" INFO"), + Level::WARN => Color::RGB(252, 234, 160).bold().paint(" WARN"), // orange + Level::ERROR => Color::Red.bold().paint("ERROR"), + } + .fmt(f) + } +} + +fn indent_block_with_lines( + lines: &[&str], + buf: &mut String, + indent: usize, + indent_amount: usize, + prefix: &str, + style: SpanMode, +) { + let indent_spaces = indent * indent_amount; + if lines.is_empty() { + return; + } else if indent_spaces == 0 { + for line in lines { + buf.push_str(prefix); + // The first indent is special, we only need to print open/close and nothing else + if indent == 0 { + match style { + SpanMode::Open { .. } => buf.push_str(LINE_OPEN), + SpanMode::Close { .. } => buf.push_str(LINE_CLOSE), + SpanMode::PreOpen | SpanMode::PostClose => {} + SpanMode::Event => {} + } + } + buf.push_str(line); + buf.push('\n'); + } + return; + } + let mut s = String::with_capacity(indent_spaces + prefix.len()); + s.push_str(prefix); + + // instead of using all spaces to indent, draw a vertical line at every indent level + // up until the last indent + for i in 0..(indent_spaces - indent_amount) { + if i % indent_amount == 0 { + s.push_str(LINE_VERT); + } else { + s.push(' '); + } + } + + // draw branch + buf.push_str(&s); + + match style { + SpanMode::PreOpen => { + buf.push_str(LINE_BRANCH); + for _ in 1..(indent_amount / 2) { + buf.push_str(LINE_HORIZ); + } + buf.push_str(LINE_OPEN); + } + SpanMode::Open { verbose: false } => { + buf.push_str(LINE_BRANCH); + for _ in 1..indent_amount { + buf.push_str(LINE_HORIZ); + } + buf.push_str(LINE_OPEN); + } + SpanMode::Open { verbose: true } => { + buf.push_str(LINE_VERT); + for _ in 1..(indent_amount / 2) { + buf.push(' '); + } + // We don't have the space for fancy rendering at single space indent. + if indent_amount > 1 { + buf.push('└'); + } + for _ in (indent_amount / 2)..(indent_amount - 1) { + buf.push_str(LINE_HORIZ); + } + // We don't have the space for fancy rendering at single space indent. + if indent_amount > 1 { + buf.push_str(LINE_OPEN); + } else { + buf.push_str(LINE_VERT); + } + } + SpanMode::Close { verbose: false } => { + buf.push_str(LINE_BRANCH); + for _ in 1..indent_amount { + buf.push_str(LINE_HORIZ); + } + buf.push_str(LINE_CLOSE); + } + SpanMode::Close { verbose: true } => { + buf.push_str(LINE_VERT); + for _ in 1..(indent_amount / 2) { + buf.push(' '); + } + // We don't have the space for fancy rendering at single space indent. + if indent_amount > 1 { + buf.push('┌'); + } + for _ in (indent_amount / 2)..(indent_amount - 1) { + buf.push_str(LINE_HORIZ); + } + // We don't have the space for fancy rendering at single space indent. + if indent_amount > 1 { + buf.push_str(LINE_CLOSE); + } else { + buf.push_str(LINE_VERT); + } + } + SpanMode::PostClose => { + buf.push_str(LINE_BRANCH); + for _ in 1..(indent_amount / 2) { + buf.push_str(LINE_HORIZ); + } + buf.push_str(LINE_CLOSE); + } + SpanMode::Event => { + buf.push_str(LINE_BRANCH); + + // add `indent_amount - 1` horizontal lines before the span/event + for _ in 0..(indent_amount - 1) { + buf.push_str(LINE_HORIZ); + } + } + } + buf.push_str(lines[0]); + buf.push('\n'); + + // add the rest of the indentation, since we don't want to draw horizontal lines + // for subsequent lines + for i in 0..indent_amount { + if i % indent_amount == 0 { + s.push_str(LINE_VERT); + } else { + s.push(' '); + } + } + + // add all of the actual content, with each line preceded by the indent string + for line in &lines[1..] { + buf.push_str(&s); + buf.push_str(line); + buf.push('\n'); + } +} + +fn indent_block( + block: &mut String, + buf: &mut String, + indent: usize, + indent_amount: usize, + indent_lines: bool, + prefix: &str, + style: SpanMode, +) { + let lines: Vec<&str> = block.lines().collect(); + let indent_spaces = indent * indent_amount; + buf.reserve(block.len() + (lines.len() * indent_spaces)); + if indent_lines { + indent_block_with_lines(&lines, buf, indent, indent_amount, prefix, style); + } else { + let indent_str = String::from(" ").repeat(indent_spaces); + for line in lines { + buf.push_str(prefix); + buf.push_str(&indent_str); + buf.push_str(line); + buf.push('\n'); + } + } +} diff --git a/vendor/tracing-tree/src/lib.rs b/vendor/tracing-tree/src/lib.rs new file mode 100644 index 000000000..dbacaa57e --- /dev/null +++ b/vendor/tracing-tree/src/lib.rs @@ -0,0 +1,395 @@ +pub(crate) mod format; + +use ansi_term::{Color, Style}; +use format::{Buffers, ColorLevel, Config, FmtEvent, SpanMode}; +use std::{ + fmt::{self, Write as _}, + io, + sync::Mutex, + time::Instant, +}; +use tracing_core::{ + field::{Field, Visit}, + span::{Attributes, Id}, + Event, Subscriber, +}; +#[cfg(feature = "tracing-log")] +use tracing_log::NormalizeEvent; +use tracing_subscriber::{ + fmt::MakeWriter, + layer::{Context, Layer}, + registry::{self, LookupSpan}, +}; + +pub(crate) struct Data { + start: Instant, + kvs: Vec<(&'static str, String)>, +} + +impl Data { + pub fn new(attrs: &Attributes<'_>) -> Self { + let mut span = Self { + start: Instant::now(), + kvs: Vec::new(), + }; + attrs.record(&mut span); + span + } +} + +impl Visit for Data { + fn record_debug(&mut self, field: &Field, value: &dyn fmt::Debug) { + self.kvs.push((field.name(), format!("{:?}", value))) + } +} +#[derive(Debug)] +pub struct HierarchicalLayer<W = fn() -> io::Stderr> +where + W: for<'writer> MakeWriter<'writer> + 'static, +{ + make_writer: W, + bufs: Mutex<Buffers>, + config: Config, +} + +impl Default for HierarchicalLayer { + fn default() -> Self { + Self::new(2) + } +} + +impl HierarchicalLayer<fn() -> io::Stderr> { + pub fn new(indent_amount: usize) -> Self { + let ansi = atty::is(atty::Stream::Stderr); + let config = Config { + ansi, + indent_amount, + ..Default::default() + }; + Self { + make_writer: io::stderr, + bufs: Mutex::new(Buffers::new()), + config, + } + } +} + +impl<W> HierarchicalLayer<W> +where + W: for<'writer> MakeWriter<'writer> + 'static, +{ + /// Enables terminal colors, boldness and italics. + pub fn with_ansi(self, ansi: bool) -> Self { + Self { + config: self.config.with_ansi(ansi), + ..self + } + } + + pub fn with_writer<W2>(self, make_writer: W2) -> HierarchicalLayer<W2> + where + W2: for<'writer> MakeWriter<'writer>, + { + HierarchicalLayer { + make_writer, + config: self.config, + bufs: self.bufs, + } + } + + pub fn with_indent_amount(self, indent_amount: usize) -> Self { + let config = Config { + indent_amount, + ..self.config + }; + Self { config, ..self } + } + + /// Renders an ascii art tree instead of just using whitespace indentation. + pub fn with_indent_lines(self, indent_lines: bool) -> Self { + Self { + config: self.config.with_indent_lines(indent_lines), + ..self + } + } + + /// Whether to render the event and span targets. Usually targets are the module path to the + /// event/span macro invocation. + pub fn with_targets(self, targets: bool) -> Self { + Self { + config: self.config.with_targets(targets), + ..self + } + } + + /// Whether to render the thread id in the beginning of every line. This is helpful to + /// untangle the tracing statements emitted by each thread. + pub fn with_thread_ids(self, thread_ids: bool) -> Self { + Self { + config: self.config.with_thread_ids(thread_ids), + ..self + } + } + + /// Whether to render the thread name in the beginning of every line. Not all threads have + /// names, but if they do, this may be more helpful than the generic thread ids. + pub fn with_thread_names(self, thread_names: bool) -> Self { + Self { + config: self.config.with_thread_names(thread_names), + ..self + } + } + + /// Resets the indentation to zero after `wraparound` indentation levels. + /// This is helpful if you expect very deeply nested spans as otherwise the indentation + /// just runs out of your screen. + pub fn with_wraparound(self, wraparound: usize) -> Self { + Self { + config: self.config.with_wraparound(wraparound), + ..self + } + } + + /// Whether to print the currently active span's message again before entering a new span. + /// This helps if the entry to the current span was quite a while back (and with scrolling + /// upwards in logs). + pub fn with_verbose_entry(self, verbose_entry: bool) -> Self { + Self { + config: self.config.with_verbose_entry(verbose_entry), + ..self + } + } + + /// Whether to print the currently active span's message again before dropping it. + /// This helps if the entry to the current span was quite a while back (and with scrolling + /// upwards in logs). + pub fn with_verbose_exit(self, verbose_exit: bool) -> Self { + Self { + config: self.config.with_verbose_exit(verbose_exit), + ..self + } + } + + /// Whether to print `{}` around the fields when printing a span. + /// This can help visually distinguish fields from the rest of the message. + pub fn with_bracketed_fields(self, bracketed_fields: bool) -> Self { + Self { + config: self.config.with_bracketed_fields(bracketed_fields), + ..self + } + } + + fn styled(&self, style: Style, text: impl AsRef<str>) -> String { + if self.config.ansi { + style.paint(text.as_ref()).to_string() + } else { + text.as_ref().to_string() + } + } + + fn print_kvs<'a, I, V>(&self, buf: &mut impl fmt::Write, kvs: I) -> fmt::Result + where + I: IntoIterator<Item = (&'a str, V)>, + V: fmt::Display + 'a, + { + let mut kvs = kvs.into_iter(); + if let Some((k, v)) = kvs.next() { + if k == "message" { + write!(buf, "{}", v)?; + } else { + write!(buf, "{}={}", k, v)?; + } + } + for (k, v) in kvs { + write!(buf, ", {}={}", k, v)?; + } + Ok(()) + } + + fn write_span_info<S>(&self, id: &Id, ctx: &Context<S>, style: SpanMode) + where + S: Subscriber + for<'span> LookupSpan<'span>, + { + let span = ctx + .span(id) + .expect("in on_enter/on_exit but span does not exist"); + let ext = span.extensions(); + let data = ext.get::<Data>().expect("span does not have data"); + + let mut guard = self.bufs.lock().unwrap(); + let bufs = &mut *guard; + let mut current_buf = &mut bufs.current_buf; + + let indent = ctx + .lookup_current() + .as_ref() + .map(registry::SpanRef::scope) + .map(registry::Scope::from_root) + .into_iter() + .flatten() + .count(); + + if self.config.verbose_entry || matches!(style, SpanMode::Open { .. } | SpanMode::Event) { + if self.config.targets { + let target = span.metadata().target(); + write!( + &mut current_buf, + "{}::", + self.styled(Style::new().dimmed(), target,), + ) + .expect("Unable to write to buffer"); + } + + write!( + current_buf, + "{name}", + name = self.styled(Style::new().fg(Color::Green).bold(), span.metadata().name()) + ) + .unwrap(); + if self.config.bracketed_fields { + write!( + current_buf, + "{}", + self.styled(Style::new().fg(Color::Green).bold(), "{") // Style::new().fg(Color::Green).dimmed().paint("{") + ) + .unwrap(); + } else { + write!(current_buf, " ").unwrap(); + } + self.print_kvs(&mut current_buf, data.kvs.iter().map(|(k, v)| (*k, v))) + .unwrap(); + if self.config.bracketed_fields { + write!( + current_buf, + "{}", + self.styled(Style::new().fg(Color::Green).bold(), "}") // Style::new().dimmed().paint("}") + ) + .unwrap(); + } + } + + bufs.indent_current(indent, &self.config, style); + let writer = self.make_writer.make_writer(); + bufs.flush_current_buf(writer) + } +} + +impl<S, W> Layer<S> for HierarchicalLayer<W> +where + S: Subscriber + for<'span> LookupSpan<'span>, + W: for<'writer> MakeWriter<'writer> + 'static, +{ + fn on_new_span(&self, attrs: &Attributes, id: &Id, ctx: Context<S>) { + let span = ctx.span(id).expect("in new_span but span does not exist"); + if span.extensions().get::<Data>().is_none() { + let data = Data::new(attrs); + span.extensions_mut().insert(data); + } + + if self.config.verbose_exit { + if let Some(span) = span.parent() { + self.write_span_info(&span.id(), &ctx, SpanMode::PreOpen); + } + } + + self.write_span_info( + id, + &ctx, + SpanMode::Open { + verbose: self.config.verbose_entry, + }, + ); + } + + fn on_event(&self, event: &Event<'_>, ctx: Context<S>) { + let mut guard = self.bufs.lock().unwrap(); + let bufs = &mut *guard; + let mut event_buf = &mut bufs.current_buf; + + // printing the indentation + let indent = if ctx.current_span().id().is_some() { + // size hint isn't implemented on Scope. + ctx.event_scope(event) + .expect("Unable to get span scope; this is a bug") + .count() + } else { + 0 + }; + + // check if this event occurred in the context of a span. + // if it has, get the start time of this span. + let start = match ctx.current_span().id() { + Some(id) => match ctx.span(id) { + // if the event is in a span, get the span's starting point. + Some(ctx) => { + let ext = ctx.extensions(); + let data = ext + .get::<Data>() + .expect("Data cannot be found in extensions"); + Some(data.start) + } + None => None, + }, + None => None, + }; + if let Some(start) = start { + let elapsed = start.elapsed(); + write!( + &mut event_buf, + "{timestamp}{unit} ", + timestamp = self.styled(Style::new().dimmed(), elapsed.as_millis().to_string()), + unit = self.styled(Style::new().dimmed(), "ms"), + ) + .expect("Unable to write to buffer"); + } + + #[cfg(feature = "tracing-log")] + let normalized_meta = event.normalized_metadata(); + #[cfg(feature = "tracing-log")] + let metadata = normalized_meta.as_ref().unwrap_or_else(|| event.metadata()); + #[cfg(not(feature = "tracing-log"))] + let metadata = event.metadata(); + + let level = metadata.level(); + let level = if self.config.ansi { + ColorLevel(level).to_string() + } else { + level.to_string() + }; + write!(&mut event_buf, "{level}", level = level).expect("Unable to write to buffer"); + + if self.config.targets { + let target = metadata.target(); + write!( + &mut event_buf, + " {}", + self.styled(Style::new().dimmed(), target,), + ) + .expect("Unable to write to buffer"); + } + + let mut visitor = FmtEvent { comma: false, bufs }; + event.record(&mut visitor); + visitor + .bufs + .indent_current(indent, &self.config, SpanMode::Event); + let writer = self.make_writer.make_writer(); + bufs.flush_current_buf(writer) + } + + fn on_close(&self, id: Id, ctx: Context<S>) { + self.write_span_info( + &id, + &ctx, + SpanMode::Close { + verbose: self.config.verbose_exit, + }, + ); + + if self.config.verbose_exit { + if let Some(span) = ctx.span(&id).and_then(|span| span.parent()) { + self.write_span_info(&span.id(), &ctx, SpanMode::PostClose); + } + } + } +} diff --git a/vendor/tracing-tree/tests/ui.rs b/vendor/tracing-tree/tests/ui.rs new file mode 100644 index 000000000..68c54e66e --- /dev/null +++ b/vendor/tracing-tree/tests/ui.rs @@ -0,0 +1,79 @@ +use assert_cmd::prelude::*; + +use std::process::Command; + +// Timings are flaky, so tests would spuriously fail. +// Thus we replace all `/([0-9]+)ms/` with underscores +fn replace_ms(data: &[u8]) -> Vec<u8> { + let mut skip = false; + let mut seen_s = false; + let mut v: Vec<u8> = data + .iter() + .rev() + .filter_map(|&b| match (b, skip, seen_s) { + (b'0'..=b'9', true, _) => None, + (_, true, _) => { + skip = false; + Some(b) + } + (b's', _, _) => { + seen_s = true; + Some(b) + } + (b'm', _, true) => { + seen_s = false; + skip = true; + Some(b) + } + _ => Some(b), + }) + .collect(); + v.reverse(); + v +} + +fn main() { + for entry in glob::glob("examples/*.rs").expect("Failed to read glob pattern") { + let entry = entry.unwrap(); + let mut cmd = Command::cargo_bin(entry.with_extension("").to_str().unwrap()).unwrap(); + let output = cmd.unwrap(); + let stderr = entry.with_extension("stderr"); + let stdout = entry.with_extension("stdout"); + + if std::env::args().any(|arg| arg == "--bless") { + if output.stderr.is_empty() { + let _ = std::fs::remove_file(stderr); + } else { + std::fs::write(stderr, replace_ms(&output.stderr)).unwrap(); + } + if output.stdout.is_empty() { + let _ = std::fs::remove_file(stdout); + } else { + std::fs::write(stdout, replace_ms(&output.stdout)).unwrap(); + } + } else { + if output.stderr.is_empty() { + assert!( + !stderr.exists(), + "{} exists but there was no stderr output", + stderr.display() + ); + } else { + assert!( + std::fs::read(&stderr).unwrap() == replace_ms(&output.stderr), + "{} is not the expected output, rerun the test with `cargo test -- -- --bless`", + stderr.display() + ); + } + if output.stdout.is_empty() { + assert!(!stdout.exists()); + } else { + assert!( + std::fs::read(&stdout).unwrap() == replace_ms(&output.stdout), + "{} is not the expected output, rerun the test with `cargo test -- -- --bless`", + stdout.display() + ); + } + } + } +} |