├── .gitignore ├── rust-toolchain ├── rustfmt.toml ├── Cargo.toml ├── .github └── workflows │ ├── typos.yml │ └── ci.yml ├── taplo.toml ├── README.md ├── src └── lib.rs ├── LICENSE └── Cargo.lock /.gitignore: -------------------------------------------------------------------------------- 1 | **/target 2 | /wip 3 | 4 | .editorconfig 5 | .idea 6 | -------------------------------------------------------------------------------- /rust-toolchain: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | channel = "1.80.0" 3 | components = ["cargo", "rustfmt", "clippy", "rust-analyzer"] 4 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | comment_width = 120 2 | edition = "2021" 3 | format_code_in_doc_comments = true 4 | group_imports = "StdExternalCrate" 5 | imports_granularity = "Item" 6 | normalize_comments = true 7 | overflow_delimited_expr = true 8 | reorder_imports = true 9 | style_edition = "2024" 10 | trailing_comma = "Vertical" 11 | where_single_line = true 12 | wrap_comments = true 13 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "fastrace-tower" 3 | version = "0.1.1" 4 | 5 | categories = ["development-tools::debugging"] 6 | description = "A tower layer for propagating trace context for fastrace" 7 | keywords = ["tracing", "fastrace", "tower", "traceparent", "propagation"] 8 | readme = "README.md" 9 | 10 | edition = "2021" 11 | license = "Apache-2.0" 12 | repository = "https://github.com/fast/fastrace-tower" 13 | rust-version = "1.80" 14 | 15 | [dependencies] 16 | fastrace = "0.7" 17 | http = "1.2" 18 | tower-layer = "0.3" 19 | tower-service = "0.3" 20 | -------------------------------------------------------------------------------- /.github/workflows/typos.yml: -------------------------------------------------------------------------------- 1 | name: Typos Check 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | concurrency: 10 | group: ${{ github.workflow }}-${{ github.ref }}-${{ github.event_name }} 11 | cancel-in-progress: true 12 | 13 | env: 14 | RUST_BACKTRACE: 1 15 | 16 | jobs: 17 | typos-check: 18 | name: typos check 19 | runs-on: ubuntu-latest 20 | timeout-minutes: 10 21 | env: 22 | FORCE_COLOR: 1 23 | steps: 24 | - uses: actions/checkout@v4 25 | - uses: crate-ci/typos@master 26 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | env: 10 | CARGO_TERM_COLOR: always 11 | 12 | jobs: 13 | build: 14 | runs-on: ${{ matrix.os }} 15 | strategy: 16 | fail-fast: false 17 | matrix: 18 | os: [ windows-latest, macos-latest, ubuntu-latest ] 19 | rust: [ "1.80.0", "stable", "nightly" ] 20 | env: 21 | RUST_BACKTRACE: 1 22 | steps: 23 | - uses: actions/checkout@v4 24 | - uses: Swatinem/rust-cache@v2 25 | - uses: dtolnay/rust-toolchain@master 26 | with: 27 | toolchain: ${{ matrix.rust }} 28 | components: rustfmt, clippy 29 | 30 | - name: Check format 31 | if: ${{ matrix.rust == 'nightly' }} 32 | run: cargo +${{ matrix.rust }} fmt --all -- --check 33 | 34 | - name: Check clippy 35 | if: ${{ matrix.rust == 'nightly' }} 36 | run: cargo +${{ matrix.rust }} clippy --all-targets --all-features -- --deny warnings 37 | 38 | - name: Build 39 | run: cargo +${{ matrix.rust }} build --workspace --all-targets 40 | -------------------------------------------------------------------------------- /taplo.toml: -------------------------------------------------------------------------------- 1 | include = ["Cargo.toml", "**/*.toml"] 2 | 3 | [formatting] 4 | # Align consecutive entries vertically. 5 | align_entries = false 6 | # Append trailing commas for multi-line arrays. 7 | array_trailing_comma = true 8 | # Expand arrays to multiple lines that exceed the maximum column width. 9 | array_auto_expand = true 10 | # Collapse arrays that don't exceed the maximum column width and don't contain comments. 11 | array_auto_collapse = true 12 | # Omit white space padding from single-line arrays 13 | compact_arrays = true 14 | # Omit white space padding from the start and end of inline tables. 15 | compact_inline_tables = false 16 | # Maximum column width in characters, affects array expansion and collapse, this doesn't take whitespace into account. 17 | # Note that this is not set in stone, and works on a best-effort basis. 18 | column_width = 80 19 | # Indent based on tables and arrays of tables and their subtables, subtables out of order are not indented. 20 | indent_tables = false 21 | # The substring that is used for indentation, should be tabs or spaces (but technically can be anything). 22 | indent_string = ' ' 23 | # Add trailing newline at the end of the file if not present. 24 | trailing_newline = true 25 | # Alphabetically reorder keys that are not separated by empty lines. 26 | reorder_keys = true 27 | # Maximum amount of allowed consecutive blank lines. This does not affect the whitespace at the end of the document, as it is always stripped. 28 | allowed_blank_lines = 1 29 | # Use CRLF for line endings. 30 | crlf = false 31 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # fastrace-tower 2 | 3 | [![Crates.io](https://img.shields.io/crates/v/fastrace-tower.svg?style=flat-square&logo=rust)](https://crates.io/crates/fastrace-tower) 4 | [![Documentation](https://img.shields.io/docsrs/fastrace-tower?style=flat-square&logo=rust)](https://docs.rs/fastrace-tower/) 5 | [![MSRV 1.80.0](https://img.shields.io/badge/MSRV-1.80.0-green?style=flat-square&logo=rust)](https://www.whatrustisit.com) 6 | [![CI Status](https://img.shields.io/github/actions/workflow/status/fast/fastrace-tower/ci.yml?style=flat-square&logo=github)](https://github.com/fast/fastrace-tower/actions) 7 | [![License](https://img.shields.io/crates/l/fastrace-tower?style=flat-square)](https://github.com/fast/fastrace-tower/blob/main/LICENSE) 8 | 9 | `fastrace-tower` is a middleware library that connects [fastrace](https://crates.io/crates/fastrace), a distributed tracing library, with [tower](https://crates.io/crates/tower), modular and reusable components for building robust networking clients and servers. This integration enables seamless trace context propagation across microservice boundaries in applications based on tower. 10 | 11 | ## What is Context Propagation? 12 | 13 | Context propagation is a fundamental concept in distributed tracing that enables the correlation of operations spanning multiple services. When a request moves from one service to another, trace context information needs to be passed along, ensuring that all operations are recorded as part of the same trace. 14 | 15 | `fastrace-tower` implements the [W3C Trace Context](https://www.w3.org/TR/trace-context/) standard for propagating trace information between services. This ensures compatibility with other tracing systems that follow the same standard. 16 | 17 | ## Features 18 | 19 | - 🔄 **Automatic Context Propagation**: Automatically inject trace context into outgoing gRPC requests. 20 | - 🌉 **Seamless Integration**: Works seamlessly with the `fastrace` library for complete distributed tracing. 21 | - 📊 **Full Compatibility**: Works with fastrace's collection and reporting capabilities. 22 | 23 | ## How It Works 24 | 25 | 1. When a client makes a request, `FastraceClientLayer` detects if there's an active trace and adds a `traceparent` HTTP header with the trace context. 26 | 2. When a server receives the request, `FastraceServerLayer` extracts the trace context from the `traceparent` header and creates a new span as a child of the received context. 27 | 3. If no trace context is provided, the server creates a new root span. 28 | 29 | This process ensures that all operations across services are properly connected in the resulting trace, providing visibility into the entire request lifecycle. 30 | 31 | ## License 32 | 33 | This project is licensed under the [Apache-2.0](./LICENSE) license. 34 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | #![doc = include_str!("../README.md")] 2 | 3 | use std::task::Context; 4 | use std::task::Poll; 5 | 6 | use fastrace::prelude::*; 7 | use http::HeaderValue; 8 | use http::Request; 9 | use tower_layer::Layer; 10 | use tower_service::Service; 11 | 12 | /// The standard [W3C Trace Context](https://www.w3.org/TR/trace-context/) header name for passing trace information. 13 | /// 14 | /// This is the header key used to propagate trace context between services according to 15 | /// the W3C Trace Context specification. 16 | pub const TRACEPARENT_HEADER: &str = "traceparent"; 17 | 18 | /// Server layer for intercepting and processing trace context in incoming requests. 19 | /// 20 | /// This layer extracts tracing context from incoming requests and creates a new span 21 | /// for each request. Add this to your tower server to automatically handle trace context 22 | /// propagation. 23 | #[derive(Clone)] 24 | pub struct FastraceServerLayer; 25 | 26 | impl Layer for FastraceServerLayer { 27 | type Service = FastraceServerService; 28 | 29 | fn layer(&self, service: S) -> Self::Service { 30 | FastraceServerService { service } 31 | } 32 | } 33 | 34 | /// Server-side service that handles trace context propagation. 35 | /// 36 | /// This service extracts trace context from incoming requests and creates 37 | /// spans to track the request processing. It wraps the inner service and augments 38 | /// it with tracing capabilities. 39 | #[derive(Clone)] 40 | pub struct FastraceServerService { 41 | service: S, 42 | } 43 | 44 | impl Service> for FastraceServerService 45 | where S: Service> 46 | { 47 | type Response = S::Response; 48 | type Error = S::Error; 49 | type Future = fastrace::future::InSpan; 50 | 51 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { 52 | self.service.poll_ready(cx) 53 | } 54 | 55 | fn call(&mut self, req: Request) -> Self::Future { 56 | let headers = req.headers(); 57 | let parent = headers.get(TRACEPARENT_HEADER).and_then(|traceparent| { 58 | SpanContext::decode_w3c_traceparent(traceparent.to_str().ok()?) 59 | }); 60 | 61 | let span = if let Some(parent) = &parent { 62 | Span::root(req.method().to_string(), *parent) 63 | } else { 64 | Span::noop() 65 | }; 66 | 67 | self.service.call(req).in_span(span) 68 | } 69 | } 70 | 71 | /// Client layer for injecting trace context into outgoing requests. 72 | /// 73 | /// This layer adds the current trace context to outgoing requests, 74 | /// allowing the receiving service to continue the same trace. Add this 75 | /// to your tower client to automatically propagate trace context. 76 | #[derive(Clone)] 77 | pub struct FastraceClientLayer; 78 | 79 | impl Layer for FastraceClientLayer { 80 | type Service = FastraceClientService; 81 | 82 | fn layer(&self, service: S) -> Self::Service { 83 | FastraceClientService { service } 84 | } 85 | } 86 | 87 | /// Client-side service that handles trace context propagation. 88 | /// 89 | /// This service injects the current trace context into outgoing requests, 90 | /// allowing distributed tracing across service boundaries. 91 | #[derive(Clone)] 92 | pub struct FastraceClientService { 93 | service: S, 94 | } 95 | 96 | impl Service> for FastraceClientService 97 | where S: Service> 98 | { 99 | type Response = S::Response; 100 | type Error = S::Error; 101 | type Future = S::Future; 102 | 103 | fn poll_ready(&mut self, cx: &mut Context<'_>) -> Poll> { 104 | self.service.poll_ready(cx) 105 | } 106 | 107 | fn call(&mut self, mut req: Request) -> Self::Future { 108 | if let Some(current) = SpanContext::current_local_parent() { 109 | req.headers_mut().insert( 110 | TRACEPARENT_HEADER, 111 | HeaderValue::from_str(¤t.encode_w3c_traceparent()).unwrap(), 112 | ); 113 | } 114 | 115 | self.service.call(req) 116 | } 117 | } 118 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /Cargo.lock: -------------------------------------------------------------------------------- 1 | # This file is automatically @generated by Cargo. 2 | # It is not intended for manual editing. 3 | version = 3 4 | 5 | [[package]] 6 | name = "autocfg" 7 | version = "1.4.0" 8 | source = "registry+https://github.com/rust-lang/crates.io-index" 9 | checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" 10 | 11 | [[package]] 12 | name = "bitflags" 13 | version = "2.9.0" 14 | source = "registry+https://github.com/rust-lang/crates.io-index" 15 | checksum = "5c8214115b7bf84099f1309324e63141d4c5d7cc26862f97a0a857dbefe165bd" 16 | 17 | [[package]] 18 | name = "bumpalo" 19 | version = "3.17.0" 20 | source = "registry+https://github.com/rust-lang/crates.io-index" 21 | checksum = "1628fb46dfa0b37568d12e5edd512553eccf6a22a78e8bde00bb4aed84d5bdbf" 22 | 23 | [[package]] 24 | name = "bytes" 25 | version = "1.10.1" 26 | source = "registry+https://github.com/rust-lang/crates.io-index" 27 | checksum = "d71b6127be86fdcfddb610f7182ac57211d4b18a3e9c82eb2d17662f2227ad6a" 28 | 29 | [[package]] 30 | name = "cfg-if" 31 | version = "1.0.0" 32 | source = "registry+https://github.com/rust-lang/crates.io-index" 33 | checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" 34 | 35 | [[package]] 36 | name = "fastant" 37 | version = "0.1.10" 38 | source = "registry+https://github.com/rust-lang/crates.io-index" 39 | checksum = "62bf7fa928ce0c4a43bd6e7d1235318fc32ac3a3dea06a2208c44e729449471a" 40 | dependencies = [ 41 | "small_ctor", 42 | "web-time", 43 | ] 44 | 45 | [[package]] 46 | name = "fastrace" 47 | version = "0.7.8" 48 | source = "registry+https://github.com/rust-lang/crates.io-index" 49 | checksum = "773324bb245e34a32d704c2256871377f9d7cdb4acff10c555e0dc068d6ddb55" 50 | dependencies = [ 51 | "fastant", 52 | "fastrace-macro", 53 | "once_cell", 54 | "parking_lot", 55 | "pin-project", 56 | "rand", 57 | "rtrb", 58 | "serde", 59 | ] 60 | 61 | [[package]] 62 | name = "fastrace-macro" 63 | version = "0.7.8" 64 | source = "registry+https://github.com/rust-lang/crates.io-index" 65 | checksum = "fce8ba9d9d06711bc0c3fb287689e41550d8501a0c3ac5a61c60693644e0f059" 66 | dependencies = [ 67 | "proc-macro-error2", 68 | "proc-macro2", 69 | "quote", 70 | "syn", 71 | ] 72 | 73 | [[package]] 74 | name = "fastrace-tower" 75 | version = "0.1.1" 76 | dependencies = [ 77 | "fastrace", 78 | "http", 79 | "tower-layer", 80 | "tower-service", 81 | ] 82 | 83 | [[package]] 84 | name = "fnv" 85 | version = "1.0.7" 86 | source = "registry+https://github.com/rust-lang/crates.io-index" 87 | checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" 88 | 89 | [[package]] 90 | name = "getrandom" 91 | version = "0.3.2" 92 | source = "registry+https://github.com/rust-lang/crates.io-index" 93 | checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0" 94 | dependencies = [ 95 | "cfg-if", 96 | "libc", 97 | "r-efi", 98 | "wasi", 99 | ] 100 | 101 | [[package]] 102 | name = "http" 103 | version = "1.3.1" 104 | source = "registry+https://github.com/rust-lang/crates.io-index" 105 | checksum = "f4a85d31aea989eead29a3aaf9e1115a180df8282431156e533de47660892565" 106 | dependencies = [ 107 | "bytes", 108 | "fnv", 109 | "itoa", 110 | ] 111 | 112 | [[package]] 113 | name = "itoa" 114 | version = "1.0.15" 115 | source = "registry+https://github.com/rust-lang/crates.io-index" 116 | checksum = "4a5f13b858c8d314ee3e8f639011f7ccefe71f97f96e50151fb991f267928e2c" 117 | 118 | [[package]] 119 | name = "js-sys" 120 | version = "0.3.77" 121 | source = "registry+https://github.com/rust-lang/crates.io-index" 122 | checksum = "1cfaf33c695fc6e08064efbc1f72ec937429614f25eef83af942d0e227c3a28f" 123 | dependencies = [ 124 | "once_cell", 125 | "wasm-bindgen", 126 | ] 127 | 128 | [[package]] 129 | name = "libc" 130 | version = "0.2.171" 131 | source = "registry+https://github.com/rust-lang/crates.io-index" 132 | checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" 133 | 134 | [[package]] 135 | name = "lock_api" 136 | version = "0.4.12" 137 | source = "registry+https://github.com/rust-lang/crates.io-index" 138 | checksum = "07af8b9cdd281b7915f413fa73f29ebd5d55d0d3f0155584dade1ff18cea1b17" 139 | dependencies = [ 140 | "autocfg", 141 | "scopeguard", 142 | ] 143 | 144 | [[package]] 145 | name = "log" 146 | version = "0.4.26" 147 | source = "registry+https://github.com/rust-lang/crates.io-index" 148 | checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" 149 | 150 | [[package]] 151 | name = "once_cell" 152 | version = "1.21.1" 153 | source = "registry+https://github.com/rust-lang/crates.io-index" 154 | checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" 155 | 156 | [[package]] 157 | name = "parking_lot" 158 | version = "0.12.3" 159 | source = "registry+https://github.com/rust-lang/crates.io-index" 160 | checksum = "f1bf18183cf54e8d6059647fc3063646a1801cf30896933ec2311622cc4b9a27" 161 | dependencies = [ 162 | "lock_api", 163 | "parking_lot_core", 164 | ] 165 | 166 | [[package]] 167 | name = "parking_lot_core" 168 | version = "0.9.10" 169 | source = "registry+https://github.com/rust-lang/crates.io-index" 170 | checksum = "1e401f977ab385c9e4e3ab30627d6f26d00e2c73eef317493c4ec6d468726cf8" 171 | dependencies = [ 172 | "cfg-if", 173 | "libc", 174 | "redox_syscall", 175 | "smallvec", 176 | "windows-targets", 177 | ] 178 | 179 | [[package]] 180 | name = "pin-project" 181 | version = "1.1.10" 182 | source = "registry+https://github.com/rust-lang/crates.io-index" 183 | checksum = "677f1add503faace112b9f1373e43e9e054bfdd22ff1a63c1bc485eaec6a6a8a" 184 | dependencies = [ 185 | "pin-project-internal", 186 | ] 187 | 188 | [[package]] 189 | name = "pin-project-internal" 190 | version = "1.1.10" 191 | source = "registry+https://github.com/rust-lang/crates.io-index" 192 | checksum = "6e918e4ff8c4549eb882f14b3a4bc8c8bc93de829416eacf579f1207a8fbf861" 193 | dependencies = [ 194 | "proc-macro2", 195 | "quote", 196 | "syn", 197 | ] 198 | 199 | [[package]] 200 | name = "ppv-lite86" 201 | version = "0.2.21" 202 | source = "registry+https://github.com/rust-lang/crates.io-index" 203 | checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" 204 | dependencies = [ 205 | "zerocopy", 206 | ] 207 | 208 | [[package]] 209 | name = "proc-macro-error-attr2" 210 | version = "2.0.0" 211 | source = "registry+https://github.com/rust-lang/crates.io-index" 212 | checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" 213 | dependencies = [ 214 | "proc-macro2", 215 | "quote", 216 | ] 217 | 218 | [[package]] 219 | name = "proc-macro-error2" 220 | version = "2.0.1" 221 | source = "registry+https://github.com/rust-lang/crates.io-index" 222 | checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" 223 | dependencies = [ 224 | "proc-macro-error-attr2", 225 | "proc-macro2", 226 | "quote", 227 | "syn", 228 | ] 229 | 230 | [[package]] 231 | name = "proc-macro2" 232 | version = "1.0.94" 233 | source = "registry+https://github.com/rust-lang/crates.io-index" 234 | checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" 235 | dependencies = [ 236 | "unicode-ident", 237 | ] 238 | 239 | [[package]] 240 | name = "quote" 241 | version = "1.0.40" 242 | source = "registry+https://github.com/rust-lang/crates.io-index" 243 | checksum = "1885c039570dc00dcb4ff087a89e185fd56bae234ddc7f056a945bf36467248d" 244 | dependencies = [ 245 | "proc-macro2", 246 | ] 247 | 248 | [[package]] 249 | name = "r-efi" 250 | version = "5.2.0" 251 | source = "registry+https://github.com/rust-lang/crates.io-index" 252 | checksum = "74765f6d916ee2faa39bc8e68e4f3ed8949b48cccdac59983d287a7cb71ce9c5" 253 | 254 | [[package]] 255 | name = "rand" 256 | version = "0.9.0" 257 | source = "registry+https://github.com/rust-lang/crates.io-index" 258 | checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" 259 | dependencies = [ 260 | "rand_chacha", 261 | "rand_core", 262 | "zerocopy", 263 | ] 264 | 265 | [[package]] 266 | name = "rand_chacha" 267 | version = "0.9.0" 268 | source = "registry+https://github.com/rust-lang/crates.io-index" 269 | checksum = "d3022b5f1df60f26e1ffddd6c66e8aa15de382ae63b3a0c1bfc0e4d3e3f325cb" 270 | dependencies = [ 271 | "ppv-lite86", 272 | "rand_core", 273 | ] 274 | 275 | [[package]] 276 | name = "rand_core" 277 | version = "0.9.3" 278 | source = "registry+https://github.com/rust-lang/crates.io-index" 279 | checksum = "99d9a13982dcf210057a8a78572b2217b667c3beacbf3a0d8b454f6f82837d38" 280 | dependencies = [ 281 | "getrandom", 282 | ] 283 | 284 | [[package]] 285 | name = "redox_syscall" 286 | version = "0.5.10" 287 | source = "registry+https://github.com/rust-lang/crates.io-index" 288 | checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" 289 | dependencies = [ 290 | "bitflags", 291 | ] 292 | 293 | [[package]] 294 | name = "rtrb" 295 | version = "0.3.2" 296 | source = "registry+https://github.com/rust-lang/crates.io-index" 297 | checksum = "ad8388ea1a9e0ea807e442e8263a699e7edcb320ecbcd21b4fa8ff859acce3ba" 298 | 299 | [[package]] 300 | name = "scopeguard" 301 | version = "1.2.0" 302 | source = "registry+https://github.com/rust-lang/crates.io-index" 303 | checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" 304 | 305 | [[package]] 306 | name = "serde" 307 | version = "1.0.219" 308 | source = "registry+https://github.com/rust-lang/crates.io-index" 309 | checksum = "5f0e2c6ed6606019b4e29e69dbaba95b11854410e5347d525002456dbbb786b6" 310 | dependencies = [ 311 | "serde_derive", 312 | ] 313 | 314 | [[package]] 315 | name = "serde_derive" 316 | version = "1.0.219" 317 | source = "registry+https://github.com/rust-lang/crates.io-index" 318 | checksum = "5b0276cf7f2c73365f7157c8123c21cd9a50fbbd844757af28ca1f5925fc2a00" 319 | dependencies = [ 320 | "proc-macro2", 321 | "quote", 322 | "syn", 323 | ] 324 | 325 | [[package]] 326 | name = "small_ctor" 327 | version = "0.1.2" 328 | source = "registry+https://github.com/rust-lang/crates.io-index" 329 | checksum = "88414a5ca1f85d82cc34471e975f0f74f6aa54c40f062efa42c0080e7f763f81" 330 | 331 | [[package]] 332 | name = "smallvec" 333 | version = "1.14.0" 334 | source = "registry+https://github.com/rust-lang/crates.io-index" 335 | checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" 336 | 337 | [[package]] 338 | name = "syn" 339 | version = "2.0.100" 340 | source = "registry+https://github.com/rust-lang/crates.io-index" 341 | checksum = "b09a44accad81e1ba1cd74a32461ba89dee89095ba17b32f5d03683b1b1fc2a0" 342 | dependencies = [ 343 | "proc-macro2", 344 | "quote", 345 | "unicode-ident", 346 | ] 347 | 348 | [[package]] 349 | name = "tower-layer" 350 | version = "0.3.3" 351 | source = "registry+https://github.com/rust-lang/crates.io-index" 352 | checksum = "121c2a6cda46980bb0fcd1647ffaf6cd3fc79a013de288782836f6df9c48780e" 353 | 354 | [[package]] 355 | name = "tower-service" 356 | version = "0.3.3" 357 | source = "registry+https://github.com/rust-lang/crates.io-index" 358 | checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" 359 | 360 | [[package]] 361 | name = "unicode-ident" 362 | version = "1.0.18" 363 | source = "registry+https://github.com/rust-lang/crates.io-index" 364 | checksum = "5a5f39404a5da50712a4c1eecf25e90dd62b613502b7e925fd4e4d19b5c96512" 365 | 366 | [[package]] 367 | name = "wasi" 368 | version = "0.14.2+wasi-0.2.4" 369 | source = "registry+https://github.com/rust-lang/crates.io-index" 370 | checksum = "9683f9a5a998d873c0d21fcbe3c083009670149a8fab228644b8bd36b2c48cb3" 371 | dependencies = [ 372 | "wit-bindgen-rt", 373 | ] 374 | 375 | [[package]] 376 | name = "wasm-bindgen" 377 | version = "0.2.100" 378 | source = "registry+https://github.com/rust-lang/crates.io-index" 379 | checksum = "1edc8929d7499fc4e8f0be2262a241556cfc54a0bea223790e71446f2aab1ef5" 380 | dependencies = [ 381 | "cfg-if", 382 | "once_cell", 383 | "wasm-bindgen-macro", 384 | ] 385 | 386 | [[package]] 387 | name = "wasm-bindgen-backend" 388 | version = "0.2.100" 389 | source = "registry+https://github.com/rust-lang/crates.io-index" 390 | checksum = "2f0a0651a5c2bc21487bde11ee802ccaf4c51935d0d3d42a6101f98161700bc6" 391 | dependencies = [ 392 | "bumpalo", 393 | "log", 394 | "proc-macro2", 395 | "quote", 396 | "syn", 397 | "wasm-bindgen-shared", 398 | ] 399 | 400 | [[package]] 401 | name = "wasm-bindgen-macro" 402 | version = "0.2.100" 403 | source = "registry+https://github.com/rust-lang/crates.io-index" 404 | checksum = "7fe63fc6d09ed3792bd0897b314f53de8e16568c2b3f7982f468c0bf9bd0b407" 405 | dependencies = [ 406 | "quote", 407 | "wasm-bindgen-macro-support", 408 | ] 409 | 410 | [[package]] 411 | name = "wasm-bindgen-macro-support" 412 | version = "0.2.100" 413 | source = "registry+https://github.com/rust-lang/crates.io-index" 414 | checksum = "8ae87ea40c9f689fc23f209965b6fb8a99ad69aeeb0231408be24920604395de" 415 | dependencies = [ 416 | "proc-macro2", 417 | "quote", 418 | "syn", 419 | "wasm-bindgen-backend", 420 | "wasm-bindgen-shared", 421 | ] 422 | 423 | [[package]] 424 | name = "wasm-bindgen-shared" 425 | version = "0.2.100" 426 | source = "registry+https://github.com/rust-lang/crates.io-index" 427 | checksum = "1a05d73b933a847d6cccdda8f838a22ff101ad9bf93e33684f39c1f5f0eece3d" 428 | dependencies = [ 429 | "unicode-ident", 430 | ] 431 | 432 | [[package]] 433 | name = "web-time" 434 | version = "1.1.0" 435 | source = "registry+https://github.com/rust-lang/crates.io-index" 436 | checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb" 437 | dependencies = [ 438 | "js-sys", 439 | "wasm-bindgen", 440 | ] 441 | 442 | [[package]] 443 | name = "windows-targets" 444 | version = "0.52.6" 445 | source = "registry+https://github.com/rust-lang/crates.io-index" 446 | checksum = "9b724f72796e036ab90c1021d4780d4d3d648aca59e491e6b98e725b84e99973" 447 | dependencies = [ 448 | "windows_aarch64_gnullvm", 449 | "windows_aarch64_msvc", 450 | "windows_i686_gnu", 451 | "windows_i686_gnullvm", 452 | "windows_i686_msvc", 453 | "windows_x86_64_gnu", 454 | "windows_x86_64_gnullvm", 455 | "windows_x86_64_msvc", 456 | ] 457 | 458 | [[package]] 459 | name = "windows_aarch64_gnullvm" 460 | version = "0.52.6" 461 | source = "registry+https://github.com/rust-lang/crates.io-index" 462 | checksum = "32a4622180e7a0ec044bb555404c800bc9fd9ec262ec147edd5989ccd0c02cd3" 463 | 464 | [[package]] 465 | name = "windows_aarch64_msvc" 466 | version = "0.52.6" 467 | source = "registry+https://github.com/rust-lang/crates.io-index" 468 | checksum = "09ec2a7bb152e2252b53fa7803150007879548bc709c039df7627cabbd05d469" 469 | 470 | [[package]] 471 | name = "windows_i686_gnu" 472 | version = "0.52.6" 473 | source = "registry+https://github.com/rust-lang/crates.io-index" 474 | checksum = "8e9b5ad5ab802e97eb8e295ac6720e509ee4c243f69d781394014ebfe8bbfa0b" 475 | 476 | [[package]] 477 | name = "windows_i686_gnullvm" 478 | version = "0.52.6" 479 | source = "registry+https://github.com/rust-lang/crates.io-index" 480 | checksum = "0eee52d38c090b3caa76c563b86c3a4bd71ef1a819287c19d586d7334ae8ed66" 481 | 482 | [[package]] 483 | name = "windows_i686_msvc" 484 | version = "0.52.6" 485 | source = "registry+https://github.com/rust-lang/crates.io-index" 486 | checksum = "240948bc05c5e7c6dabba28bf89d89ffce3e303022809e73deaefe4f6ec56c66" 487 | 488 | [[package]] 489 | name = "windows_x86_64_gnu" 490 | version = "0.52.6" 491 | source = "registry+https://github.com/rust-lang/crates.io-index" 492 | checksum = "147a5c80aabfbf0c7d901cb5895d1de30ef2907eb21fbbab29ca94c5b08b1a78" 493 | 494 | [[package]] 495 | name = "windows_x86_64_gnullvm" 496 | version = "0.52.6" 497 | source = "registry+https://github.com/rust-lang/crates.io-index" 498 | checksum = "24d5b23dc417412679681396f2b49f3de8c1473deb516bd34410872eff51ed0d" 499 | 500 | [[package]] 501 | name = "windows_x86_64_msvc" 502 | version = "0.52.6" 503 | source = "registry+https://github.com/rust-lang/crates.io-index" 504 | checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" 505 | 506 | [[package]] 507 | name = "wit-bindgen-rt" 508 | version = "0.39.0" 509 | source = "registry+https://github.com/rust-lang/crates.io-index" 510 | checksum = "6f42320e61fe2cfd34354ecb597f86f413484a798ba44a8ca1165c58d42da6c1" 511 | dependencies = [ 512 | "bitflags", 513 | ] 514 | 515 | [[package]] 516 | name = "zerocopy" 517 | version = "0.8.23" 518 | source = "registry+https://github.com/rust-lang/crates.io-index" 519 | checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" 520 | dependencies = [ 521 | "zerocopy-derive", 522 | ] 523 | 524 | [[package]] 525 | name = "zerocopy-derive" 526 | version = "0.8.23" 527 | source = "registry+https://github.com/rust-lang/crates.io-index" 528 | checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" 529 | dependencies = [ 530 | "proc-macro2", 531 | "quote", 532 | "syn", 533 | ] 534 | --------------------------------------------------------------------------------