[
  {
    "path": ".cargo/config",
    "content": "[alias]\n# Run against all targets\ncheck-all = \"check --all --all-targets --all-features\"\nclippy-all = \"clippy --all --all-targets --all-features -- -Dwarnings -Drust-2018-idioms -Adeprecated\"\n# Format Rust code with stable-compatible nightly features\nfmt-unstable = \"fmt --all -- --config-path rustfmt-unstable.toml\"\n\n"
  },
  {
    "path": ".gitignore",
    "content": "/target\n**/target\n**/*.rs.bk\nCargo.lock\n"
  },
  {
    "path": ".travis.yml",
    "content": "language: rust\n\ncache: cargo\n\nrust:\n  - stable\n  - beta\n  - nightly\n\nmatrix:\n  allow_failures:\n    - rust: nightly\n  fast_finish: true\n\nscript:\n  - cargo build --verbose --all\n  - cargo test --verbose --all\n\nnotifications:\n  email: false\n \n"
  },
  {
    "path": "Cargo.toml",
    "content": "[workspace]\nmembers = [\n  \"metered\",\n  \"metered-macro\",\n]\n"
  },
  {
    "path": "LICENSE-APACHE",
    "content": "       Apache License\n                           Version 2.0, January 2004\n                        http://www.apache.org/licenses/\n\n   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n   1. Definitions.\n\n      \"License\" shall mean the terms and conditions for use, reproduction,\n      and distribution as defined by Sections 1 through 9 of this document.\n\n      \"Licensor\" shall mean the copyright owner or entity authorized by\n      the copyright owner that is granting the License.\n\n      \"Legal Entity\" shall mean the union of the acting entity and all\n      other entities that control, are controlled by, or are under common\n      control with that entity. For the purposes of this definition,\n      \"control\" means (i) the power, direct or indirect, to cause the\n      direction or management of such entity, whether by contract or\n      otherwise, or (ii) ownership of fifty percent (50%) or more of the\n      outstanding shares, or (iii) beneficial ownership of such entity.\n\n      \"You\" (or \"Your\") shall mean an individual or Legal Entity\n      exercising permissions granted by this License.\n\n      \"Source\" form shall mean the preferred form for making modifications,\n      including but not limited to software source code, documentation\n      source, and configuration files.\n\n      \"Object\" form shall mean any form resulting from mechanical\n      transformation or translation of a Source form, including but\n      not limited to compiled object code, generated documentation,\n      and conversions to other media types.\n\n      \"Work\" shall mean the work of authorship, whether in Source or\n      Object form, made available under the License, as indicated by a\n      copyright notice that is included in or attached to the work\n      (an example is provided in the Appendix below).\n\n      \"Derivative Works\" shall mean any work, whether in Source or Object\n      form, that is based on (or derived from) the Work and for which the\n      editorial revisions, annotations, elaborations, or other modifications\n      represent, as a whole, an original work of authorship. For the purposes\n      of this License, Derivative Works shall not include works that remain\n      separable from, or merely link (or bind by name) to the interfaces of,\n      the Work and Derivative Works thereof.\n\n      \"Contribution\" shall mean any work of authorship, including\n      the original version of the Work and any modifications or additions\n      to that Work or Derivative Works thereof, that is intentionally\n      submitted to Licensor for inclusion in the Work by the copyright owner\n      or by an individual or Legal Entity authorized to submit on behalf of\n      the copyright owner. For the purposes of this definition, \"submitted\"\n      means any form of electronic, verbal, or written communication sent\n      to the Licensor or its representatives, including but not limited to\n      communication on electronic mailing lists, source code control systems,\n      and issue tracking systems that are managed by, or on behalf of, the\n      Licensor for the purpose of discussing and improving the Work, but\n      excluding communication that is conspicuously marked or otherwise\n      designated in writing by the copyright owner as \"Not a Contribution.\"\n\n      \"Contributor\" shall mean Licensor and any individual or Legal Entity\n      on behalf of whom a Contribution has been received by Licensor and\n      subsequently incorporated within the Work.\n\n   2. Grant of Copyright License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      copyright license to reproduce, prepare Derivative Works of,\n      publicly display, publicly perform, sublicense, and distribute the\n      Work and such Derivative Works in Source or Object form.\n\n   3. Grant of Patent License. Subject to the terms and conditions of\n      this License, each Contributor hereby grants to You a perpetual,\n      worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n      (except as stated in this section) patent license to make, have made,\n      use, offer to sell, sell, import, and otherwise transfer the Work,\n      where such license applies only to those patent claims licensable\n      by such Contributor that are necessarily infringed by their\n      Contribution(s) alone or by combination of their Contribution(s)\n      with the Work to which such Contribution(s) was submitted. If You\n      institute patent litigation against any entity (including a\n      cross-claim or counterclaim in a lawsuit) alleging that the Work\n      or a Contribution incorporated within the Work constitutes direct\n      or contributory patent infringement, then any patent licenses\n      granted to You under this License for that Work shall terminate\n      as of the date such litigation is filed.\n\n   4. Redistribution. You may reproduce and distribute copies of the\n      Work or Derivative Works thereof in any medium, with or without\n      modifications, and in Source or Object form, provided that You\n      meet the following conditions:\n\n      (a) You must give any other recipients of the Work or\n          Derivative Works a copy of this License; and\n\n      (b) You must cause any modified files to carry prominent notices\n          stating that You changed the files; and\n\n      (c) You must retain, in the Source form of any Derivative Works\n          that You distribute, all copyright, patent, trademark, and\n          attribution notices from the Source form of the Work,\n          excluding those notices that do not pertain to any part of\n          the Derivative Works; and\n\n      (d) If the Work includes a \"NOTICE\" text file as part of its\n          distribution, then any Derivative Works that You distribute must\n          include a readable copy of the attribution notices contained\n          within such NOTICE file, excluding those notices that do not\n          pertain to any part of the Derivative Works, in at least one\n          of the following places: within a NOTICE text file distributed\n          as part of the Derivative Works; within the Source form or\n          documentation, if provided along with the Derivative Works; or,\n          within a display generated by the Derivative Works, if and\n          wherever such third-party notices normally appear. The contents\n          of the NOTICE file are for informational purposes only and\n          do not modify the License. You may add Your own attribution\n          notices within Derivative Works that You distribute, alongside\n          or as an addendum to the NOTICE text from the Work, provided\n          that such additional attribution notices cannot be construed\n          as modifying the License.\n\n      You may add Your own copyright statement to Your modifications and\n      may provide additional or different license terms and conditions\n      for use, reproduction, or distribution of Your modifications, or\n      for any such Derivative Works as a whole, provided Your use,\n      reproduction, and distribution of the Work otherwise complies with\n      the conditions stated in this License.\n\n   5. Submission of Contributions. Unless You explicitly state otherwise,\n      any Contribution intentionally submitted for inclusion in the Work\n      by You to the Licensor shall be under the terms and conditions of\n      this License, without any additional terms or conditions.\n      Notwithstanding the above, nothing herein shall supersede or modify\n      the terms of any separate license agreement you may have executed\n      with Licensor regarding such Contributions.\n\n   6. Trademarks. This License does not grant permission to use the trade\n      names, trademarks, service marks, or product names of the Licensor,\n      except as required for reasonable and customary use in describing the\n      origin of the Work and reproducing the content of the NOTICE file.\n\n   7. Disclaimer of Warranty. Unless required by applicable law or\n      agreed to in writing, Licensor provides the Work (and each\n      Contributor provides its Contributions) on an \"AS IS\" BASIS,\n      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or\n      implied, including, without limitation, any warranties or conditions\n      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A\n      PARTICULAR PURPOSE. You are solely responsible for determining the\n      appropriateness of using or redistributing the Work and assume any\n      risks associated with Your exercise of permissions under this License.\n\n   8. Limitation of Liability. In no event and under no legal theory,\n      whether in tort (including negligence), contract, or otherwise,\n      unless required by applicable law (such as deliberate and grossly\n      negligent acts) or agreed to in writing, shall any Contributor be\n      liable to You for damages, including any direct, indirect, special,\n      incidental, or consequential damages of any character arising as a\n      result of this License or out of the use or inability to use the\n      Work (including but not limited to damages for loss of goodwill,\n      work stoppage, computer failure or malfunction, or any and all\n      other commercial damages or losses), even if such Contributor\n      has been advised of the possibility of such damages.\n\n   9. Accepting Warranty or Additional Liability. While redistributing\n      the Work or Derivative Works thereof, You may choose to offer,\n      and charge a fee for, acceptance of support, warranty, indemnity,\n      or other liability obligations and/or rights consistent with this\n      License. However, in accepting such obligations, You may act only\n      on Your own behalf and on Your sole responsibility, not on behalf\n      of any other Contributor, and only if You agree to indemnify,\n      defend, and hold each Contributor harmless for any liability\n      incurred by, or claims asserted against, such Contributor by reason\n      of your accepting any such warranty or additional liability.\n\n   END OF TERMS AND CONDITIONS\n\n   APPENDIX: How to apply the Apache License to your work.\n\n      To apply the Apache License to your work, attach the following\n      boilerplate notice, with the fields enclosed by brackets \"{}\"\n      replaced with your own identifying information. (Don't include\n      the brackets!)  The text should be enclosed in the appropriate\n      comment syntax for the file format. We also recommend that a\n      file or class name and description of purpose be included on the\n      same \"printed page\" as the copyright notice for easier\n      identification within third-party archives.\n\n   Copyright 2018-2019 Simon Chemouil\n\n   Licensed under the Apache License, Version 2.0 (the \"License\");\n   you may not use this file except in compliance with the License.\n   You may obtain a copy of the License at\n\n       http://www.apache.org/licenses/LICENSE-2.0\n\n   Unless required by applicable law or agreed to in writing, software\n   distributed under the License is distributed on an \"AS IS\" BASIS,\n   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\n   See the License for the specific language governing permissions and\n   limitations under the License."
  },
  {
    "path": "LICENSE-MIT",
    "content": "Copyright (c) 2018-2019 Simon Chemouil\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE."
  },
  {
    "path": "README.md",
    "content": "# metered-rs\n[![Build Status](https://travis-ci.org/magnet/metered-rs.svg?branch=master)](https://travis-ci.org/magnet/metered-rs)\n[![License](https://img.shields.io/badge/license-MIT%2FApache--2.0-blue.svg)](\nhttps://github.com/magnet/metered-rs)\n[![Cargo](https://img.shields.io/crates/v/metered.svg)](\nhttps://crates.io/crates/metered)\n[![Documentation](https://docs.rs/metered/badge.svg)](\nhttps://docs.rs/metered)\n[![Rust 1.31+](https://img.shields.io/badge/rust-1.31+-lightgray.svg)](\nhttps://www.rust-lang.org)\n\n## Fast, ergonomic metrics for Rust!\n\nMetered helps you measure the performance of your programs in production. Inspired by Coda Hale's Java metrics library, Metered makes live measurements easy by providing declarative and procedural macros to measure your program without altering your logic.\n\nMetered is built with the following principles in mind:\n * **high ergonomics but no magic**: measuring code should just be a matter of annotating code. Metered lets you build your own metric registries from bare metrics, or will generate one using procedural macros. It does not use shared globals or statics.\n\n * **constant, very low overhead**: good ergonomics should not come with an overhead; the only overhead is the one imposed by actual metric back-ends themselves (e.g, counters, gauges, histograms), and those provided in Metered do not allocate after initialization.  Metered will generate metric registries as regular Rust `struct`s, so there is no lookup involved with finding a metric. Metered provides both unsynchronized and thread-safe metric back-ends so that single-threaded or share-nothing architectures don't pay for synchronization. Where possible, thread-safe metric back-ends provided by Metered use lock-free data-structures.\n\n * **extensible**: metrics are just regular types that implement the [`Metric`](https://docs.rs/metered/latest/metered/metric/trait.Metric.html) trait with a specific behavior. Metered's macros let you refer to any Rust type, resulting in user-extensible attributes!\n\n Many metrics are only meaningful if we get precise statistics. When it comes to low-latency, high-range histograms, there's nothing better than [Gil Tene's High Dynamic Range Histograms](http://hdrhistogram.org/) and Metered uses [the official Rust port](https://github.com/HdrHistogram/HdrHistogram_rust) by default for its histograms.\n\n\n## Changelog\n\n* 0.9.0:\n  * Wrapping int metrics instead of under/overflow\n  * Provide methods to increment or decrement int metrics by more than 1, useful for batched computations\n  * Add blanket implementations for `Clear` (contributed by [@plankton6](https://github.com/plankton6)) \n  * Add len method to `HdrHistogram` (contributed by [@plankton6](https://github.com/plankton6)) \n  * Code quality fixes and dependency updates\n* 0.8.0:\n  * Update Metrics via `OnResultMut` rather than an `OnResult` to support metrics that require mutable access to the result - for instance to consume a `Stream` (contributed by [@w4](https://github.com/w4))\n* 0.7.0:\n  * Expose inner metric backend `Throughput` type (fixes issue #30)\n  * Implement `Deref` for all top-level metrics\n  * Expose inner metric backend `Throughput` type\n  * Add `skip_cleared` option to `error_count` attribute  (contributed by [@w4](https://github.com/w4))\n     * Introduce a new `Clearable` trait that exposes behavior for metrics that implement `Clear` (in an effort of backwards compatibility).  Currently only implemented on counters.\n     * Default behavior can be controlled by the a build-time feature, `error-count-skip-cleared-by-default`\n* 0.6.0:\n  * Extend `error_count` macro to allow `nested` enum error variants to be reported, providing zero-cost error tracking for nested errors (contributed by [@w4](https://github.com/w4))\n* 0.5.0:\n  * Make inner metrics public (contributed by [@nemosupremo](https://github.com/nemosupremo))\n  * Provide `error_count` macro to generate a tailored `ErrorCount` metric counting variants for an error enum (contributed by [@w4](https://github.com/w4))\n  * Use `Drop` to automatically trigger metrics that don't rely on the result value (affects `InFlight`, `ResponseTime`, `Throughput`)\n* 0.4.0:\n  * Add allow(missing_docs) to generated structs (This allows to use metered structs in Rust code with lint level warn(missing_docs) or even deny(missing_docs)) (contributed by [@reyk](https://github.com/reyk))\n  * Implement `Clear` for generated registries (contributed by [@eliaslevy](https://github.com/eliaslevy))\n  * Implement `Histogram` and `Clear` for `RefCell<HdrHistogram>` (contributed by [@eliaslevy](https://github.com/eliaslevy))\n  * Introduce an `Instant` with microsecond precision (contributed by [@eliaslevy](https://github.com/eliaslevy))\n     * API breaking change: `Instant.elapsed_millis` is renamed to `elapsed_time`, and a new associated constant, `ONE_SEC` is introduced to specify one second in the instant units.\n  * Make `AtomicTxPerSec` and `TxPerSec` visible by reexporting  (contributed by [@eliaslevy](https://github.com/eliaslevy))\n  * Add `StdInstant` as the default type parameter for `T: Instant` in `TxPerSec`  (contributed by [@eliaslevy](https://github.com/eliaslevy))\n  * Modify HdrHistogram to work with serde_prometheus (contributed by [@w4](https://github.com/w4))\n     * To be used with [serde_prometheus](https://github.com/w4/serde_prometheus) and any HTTP server.\n  * Bumped dependencies:\n     * `indexmap`: 1.1 -> 1.3 \n     * `hdrhistogram`: 6.3 -> 7.1 \n     * `parking_lot`: 0.9 -> 0.10  \n* 0.3.0:\n  * Fix to preserve span in `async` measured methods.\n  * Update nightly sample for new syntax and Tokio 0.2-alpha (using std futures, will need Rust >= 1.39, nightly or not)\n  * Updated dependencies to use `syn`, `proc-macro2` and `quote` 1.0\n* 0.2.2:\n  * Async support in `#measured` methods don't rely on async closures anymore, so client code will not require the `async_closure` feature gate.\n  * Updated dependency versions\n* 0.2.1:\n  * Under certain circumstances, Serde would serialize \"nulls\" for `PhantomData` markers in `ResponseTime` and `Throughput` metrics. They are now explicitely excluded.\n* 0.2.0:\n  * Support for `.await` notation users (no more `await!()`)\n* 0.1.3:\n  * Fix for early returns in `#[measure]`'ed methods\n  * Removed usage of crate `AtomicRefCell` which sometimes panicked .\n  * Support for custom registry visibility.\n  * Support for `async` + `await!()` macro users.\n\n\n## Using Metered\n\nMetered comes with a variety of useful metrics ready out-of-the-box:\n* `HitCount`: a counter tracking how much a piece of code was hit.\n* `ErrorCount`: a counter tracking how many errors were returned -- (works on any expression returning a std `Result`)\n* `InFlight`: a gauge tracking how many requests are active \n* `ResponseTime`: statistics backed by an HdrHistogram of the duration of an expression\n* `Throughput`: statistics backed by an HdrHistogram of how many times an expression is called per second.\n\nThese metrics are usually applied to methods, using provided procedural macros that generate the boilerplate.\n\nTo achieve higher performance, these stock metrics can be customized to use non-thread safe (`!Sync`/`!Send`) datastructures, but they default to thread-safe datastructures implemented using lock-free strategies where possible. This is an ergonomical choice to provide defaults that work in all situations.\n\nMetered is designed as a zero-overhead abstraction -- in the sense that the higher-level ergonomics should not cost over manually adding metrics. Notably, stock metrics will *not* allocate memory after they're initialized the first time.  However, they are triggered at every method call and it can be interesting to use lighter metrics (e.g `HitCount`) in hot code paths and favour heavier metrics (`Throughput`, `ResponseTime`) in higher-level entry points.\n\nIf a metric you need is missing, or if you want to customize a metric (for instance, to track how many times a specific error occurs, or react depending on your return type), it is possible to implement your own metrics simply by implementing the trait `metered::metric::Metric`.\n\nMetered does not use statics or shared global state. Instead, it lets you either build your own metric registry using the metrics you need, or can generate a metric registry for you using method attributes. Metered will generate one registry per `impl` block annotated with the `metered` attribute, under the name provided as the `registry` parameter. By default, Metered will expect the registry to be accessed as `self.metrics` but the expression can be overridden with the `registry_expr` attribute parameter. See the demos for more examples.\n\nMetered will generate metric registries that derive `Debug` and `serde::Serialize` to extract your metrics easily. Metered generates one sub-registry per method annotated with the `measure` attribute, hence organizing metrics hierarchically. This ensures access time to metrics in generated registries is always constant (and, when possible, cache-friendly), without any overhead other than the metric itself.\n\nMetered will happily measure any method, whether it is `async` or not, and the metrics will work as expected (e.g, `ResponseTime` will return the completion time across `await`'ed invocations).\n\nRight now, Metered does not provide bridges to external metric storage or monitoring systems. Such support is planned in separate modules (contributions welcome!).\n\n## Required Rust version\n\nMetered works on `Rust` stable, starting 1.31.0.\n\nIt does not use any nightly features. There may be a `nightly` feature flag at some point to use upcoming Rust features (such as `const fn`s), and similar features from crates Metered depends on, but this is low priority (contributions welcome).\n\n## Example using procedural macros (recommended)\n\n```rust\nuse metered::{metered, Throughput, HitCount};\n\n#[derive(Default, Debug, serde::Serialize)]\npub struct Biz {\n    metrics: BizMetrics,\n}\n\n#[metered(registry = BizMetrics)]\nimpl Biz {\n    #[measure([HitCount, Throughput])]\n    pub fn biz(&self) {        \n        let delay = std::time::Duration::from_millis(rand::random::<u64>() % 200);\n        std::thread::sleep(delay);\n    }   \n}\n```\n\nIn the snippet above, we will measure the `HitCount` and `Throughput` of the `biz` method.\n\nThis works by first annotating the `impl` block with the `metered` annotation and specifying the name Metered should give to the metric registry (here `BizMetrics`). Later, Metered will assume the expression to access that repository is `self.metrics`, hence we need a `metrics` field with the `BizMetrics` type in `Biz`. It would be possible to use another field name by specificying another registry expression, such as `#[metered(registry = BizMetrics, registry_expr = self.my_custom_metrics)]`.\n\nThen, we must annotate which methods we wish to measure using the `measure` attribute, specifying the metrics we wish to apply: the metrics here are simply types of structures implementing the `Metric` trait, and you can define your own. Since there is no magic, we must ensure `self.metrics` can be accessed, and this will only work on methods with a `&self` or `&mut self` receiver.\n\nLet's look at `biz`'s code a second: it's a blocking method that returns after between 0 and 200ms, using `rand::random`. Since `random` has a random distribution, we can expect the mean sleep time to be around 100ms. That would mean around 10 calls per second per thread.\n\nIn the following test, we spawn 5 threads that each will call `biz()` 200 times. We thus can expect a hit count of 1000, that it will take around 20 seconds (which means 20 samples, since we collect one sample per second), and around 50 calls per second (10 per thread, with 5 threads).\n\n```rust\nuse std::thread;\nuse std::sync::Arc;\n\nfn test_biz() {\n    let biz = Arc::new(Biz::default());\n    let mut threads = Vec::new();\n    for _ in 0..5 {\n        let biz = Arc::clone(&biz);\n        let t = thread::spawn(move || {\n            for _ in 0..200 {\n                biz.biz();\n            }\n        });\n        threads.push(t);\n    }\n    for t in threads {\n        t.join().unwrap();\n    }\n    // Print the results!\n    let serialized = serde_yaml::to_string(&*biz).unwrap();\n    println!(\"{}\", serialized);\n}\n```\n\nWe can then use serde to serialize our type as YAML:\n```yaml\nmetrics:\n  biz:\n    hit_count: 1000\n    throughput:\n      - samples: 20\n        min: 35\n        max: 58\n        mean: 49.75\n        stdev: 5.146600819958742\n        90%ile: 55\n        95%ile: 55\n        99%ile: 58\n        99.9%ile: 58\n        99.99%ile: 58\n      - ~\n```\n\nWe see we indead have a mean of 49.75 calls per second, which corresponds to our expectations.\n\nThe Hdr Histogram backing these statistics is able to give much more than fixed percentiles, but this is a practical view when using text. For a better performance analysis, please watch Gil Tene's talks ;-).\n\n## Macro Reference\n\n### The `metered` attribute\n\n`#[metered(registry = YourRegistryName, registry_expr = self.wrapper.my_registry)]` \n\n`registry` is mandatory and must be a valid Rust ident.\n\n`registry_expr` defaults to `self.metrics`, alternate values must be a valid Rust expression. This setting lets you configure the expression which resolves to the registry. Please note that this triggers an immutable borrow of that expression.\n\n`visibility` defaults to `pub(crate)`, and must be a valid struct Rust visibility (e.g, `pub`, `<nothing>`, `pub(self)`, etc). This setting lets you alter the visibility of the generated registry `struct`s. The registry fields are always public and named after snake cased methods or metrics.\n\n### The `measure` attribute\n\nSingle metric:\n\n`#[measure(path::to::MyMetric<u64>)]`\n\nor: \n\n`#[measure(type = path::to::MyMetric<u64>)]`\n\nMultiple metrics:\n\n`#[measure([path::to::MyMetric<u64>, path::AnotherMetric])]`\n\nor\n\n`#[measure(type = [path::to::MyMetric<u64>, path::AnotherMetric])]`\n\nThe `type` keyword is allowed because other keywords are planned for future extra attributes (e.g, instantation options).\n\nWhen `measure` attribute is applied to an `impl` block, it applies for every method that has a `measure` attribute. If a method does not need extra measure infos, it is possible to annotate it with simply `#[measure]` and the `impl` block's `measure` configuration will be applied.\n\nThe `measure` keyword can be added several times on an `impl` block or method, which will add to the list of metrics applied. Adding the same metric several time will lead in a name clash.\n\n### Design\n\nMetered's custom attribute parsing supports using reserved keywords and arbitrary Rust syntax. The code has been extracted to the [Synattra](https://github.com/magnet/synattra) project, which provides useful methods on top of the Syn parser for Attribute parsing.\n\nMetered's metrics can wrap any piece of code, regardless of whether they're `async` blocks or not, using hygienic macros to emulate an approach similar to aspect-oriented programming. That code has been extracted to the [Aspect-rs](https://github.com/magnet/aspect-rs) project!\n\n\n## License\n\nLicensed under either of\n\n * Apache License, Version 2.0, ([LICENSE-APACHE](LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)\n * MIT license ([LICENSE-MIT](LICENSE-MIT) or http://opensource.org/licenses/MIT)\n\nat your option.\n\n### Contribution\n\nUnless you explicitly state otherwise, any contribution intentionally\nsubmitted for inclusion in the work by you, as defined in the Apache-2.0\nlicense, shall be dual licensed as above, without any additional terms or\nconditions.\n"
  },
  {
    "path": "demos/Cargo.toml",
    "content": "[package]\nname = \"metered-demo\"\nversion = \"0.1.0\"\nauthors = [\"Simon Chemouil <simon.chemouil@lambdacube.fr>\"]\nedition = \"2018\"\n\n#break out of workspace\n[workspace]\n\n[dependencies]\nhdrhistogram = \"7.5\"\nrand = \"0.8\"\natomic = \"0.5\"\ntokio = { version = \"1.19\", features = [ \"rt\", \"rt-multi-thread\", \"time\" ] }\nserde = { version = \"1.0\", features = [\"derive\"] }\nserde_prometheus = \"0.1\"\nthiserror = \"1.0\"\n\n[dependencies.metered]\nversion = \"0.9\"\npath = \"../metered\"\nfeatures = [\n    # Enable to override the default and skip \"cleared\" entries from the `error_count`\n    # even when the attribute is not specified.\n    \"error-count-skip-cleared-by-default\"\n    ]\n"
  },
  {
    "path": "demos/src/baz.rs",
    "content": "#![allow(dead_code)]\n\nuse metered::{metered, ErrorCount, HitCount, InFlight, ResponseTime};\nuse thiserror::Error;\n\n#[metered::error_count(name = LibErrorCount, visibility = pub)]\n#[derive(Debug, Error)]\npub enum LibError {\n    #[error(\"I failed!\")]\n    Failure,\n    #[error(\"Bad input\")]\n    BadInput,\n}\n\n#[metered::error_count(name = BazErrorCount, visibility = pub, skip_cleared = true)]\n#[derive(Debug, Error)]\npub enum BazError {\n    #[error(\"lib error: {0}\")]\n    Lib(#[from] #[nested] LibError),\n    #[error(\"io error\")]\n    Io,\n}\n\n#[derive(Default, Debug, serde::Serialize)]\npub struct Baz {\n    metric_reg: BazMetricRegistry,\n}\n\n#[metered(registry = BazMetricRegistry, /* default = self.metrics */ registry_expr = self.metric_reg, visibility = pub(self))]\n#[measure(InFlight)] // Applies to all methods that have the `measure` attribute\nimpl Baz {\n    // This is measured with an InFlight gauge, because it's the default on the block.\n    #[measure]\n    pub fn bir(&self) {\n        println!(\"bir\");\n        let delay = std::time::Duration::from_millis(rand::random::<u64>() % 2000);\n        std::thread::sleep(delay);\n    }\n\n    // This is not measured\n    pub fn bor(&self) {\n        println!(\"bor\");\n    }\n\n    #[measure(ResponseTime)]\n    pub fn foo(&self) {\n        println!(\"foo !\");\n        let delay = std::time::Duration::from_millis(rand::random::<u64>() % 2000);\n        std::thread::sleep(delay);\n    }\n\n    #[measure(type = HitCount<metered::atomic::AtomicInt<u64>>)]\n    #[measure(ErrorCount)]\n    #[measure(ResponseTime)]\n    pub fn bar(&self, should_fail: bool) -> Result<(), &'static str> {\n        if !should_fail {\n            println!(\"bar !\");\n            Ok(())\n        } else {\n            Err(\"I failed!\")\n        }\n    }\n    #[measure([ErrorCount, ResponseTime])]\n    pub async fn baz(&self, should_fail: bool) -> Result<(), &'static str> {\n        let delay = std::time::Duration::from_millis(rand::random::<u64>() % 2000);\n        tokio::time::sleep(delay).await;\n        if !should_fail {\n            println!(\"baz !\");\n            Ok(())\n        } else {\n            Err(\"I failed!\")\n        }\n    }\n\n    #[measure([ResponseTime])]\n    pub fn bazium(\n        &self,\n        should_fail: bool,\n    ) -> impl std::future::Future<Output = Result<(), &'static str>> {\n        async move {\n            let delay = std::time::Duration::from_millis(rand::random::<u64>() % 2000);\n            tokio::time::sleep(delay).await;\n            if !should_fail {\n                println!(\"baz !\");\n                Ok(())\n            } else {\n                Err(\"I failed!\")\n            }\n        }\n    }\n\n    #[measure([HitCount, BazErrorCount])]\n    pub async fn bazle(&self, should_fail: bool) -> Result<(), BazError> {\n        if !should_fail {\n            println!(\"bazle !\");\n            Ok(())\n        } else {\n            Err(LibError::Failure.into())\n        }\n    }\n\n    #[measure]\n    pub unsafe fn bad(&self, v: &[u8]) {\n        let _ = std::str::from_utf8_unchecked(v);\n    }\n\n    // This is not measured either\n    pub fn bur() {\n        println!(\"bur\");\n    }\n}\n"
  },
  {
    "path": "demos/src/biz.rs",
    "content": "use metered::{metered, HitCount, Throughput};\n\n#[derive(Default, Debug, serde::Serialize)]\npub struct Biz {\n    pub(crate) metrics: BizMetrics,\n}\n\n#[metered(registry = BizMetrics)]\n#[measure([HitCount, Throughput])]\nimpl Biz {\n    // This is measured with an Throughput metric (TPS)\n    #[measure]\n    pub fn biz(&self) {\n        let delay = std::time::Duration::from_millis(rand::random::<u64>() % 200);\n        std::thread::sleep(delay);\n    }\n}\n"
  },
  {
    "path": "demos/src/main.rs",
    "content": "use metered::clear::Clear;\nuse metered::*;\nmod baz;\nuse baz::Baz;\nmod biz;\nuse biz::Biz;\nuse std::collections::HashMap;\n\n#[derive(Default, Debug, serde::Serialize)]\nstruct TestMetrics {\n    hit_count: HitCount,\n    error_count: ErrorCount,\n}\n\nfn test(should_fail: bool, metrics: &TestMetrics) -> Result<(), ()> {\n    let hit_count = &metrics.hit_count;\n    let error_count = &metrics.error_count;\n    measure!(hit_count, {\n        measure!(error_count, {\n            println!(\"test !\");\n            if should_fail {\n                Err(())\n            } else {\n                Ok(())\n            }\n        })\n    })\n}\n\nfn test_incr(metrics: &TestMetrics) -> Result<(), ()> {\n    let hit_count = &metrics.hit_count;\n    hit_count.incr_by(3);\n    Ok(())\n}\n\nfn sync_procmacro_demo(baz: &Baz) {\n    for i in 1..=10 {\n        baz.foo();\n        let _ = baz.bar(i % 3 == 0);\n    }\n}\n\nasync fn async_procmacro_demo(baz: Baz) {\n    for i in 1..=5 {\n        let _ = baz.baz(i % 3 == 0).await;\n        let _ = baz.bazle(i % 3 == 0).await;\n    }\n\n    // Print the results!\n    let serialized = serde_prometheus::to_string(&baz, None, HashMap::new()).unwrap();\n    println!(\"{}\", serialized);\n}\n\nfn simple_api_demo() {\n    let metrics = TestMetrics::default();\n\n    let _ = test(false, &metrics);\n    let _ = test(true, &metrics);\n    let _ = test_incr(&metrics);\n\n    // Print the results!\n    let serialized = serde_prometheus::to_string(&metrics, None, HashMap::new()).unwrap();\n    println!(\"{}\", serialized);\n}\n\nuse std::sync::Arc;\nuse std::thread;\n\nfn test_biz() {\n    println!(\"Running Biz throughput demo...(will take 20 seconds)\");\n    let biz = Arc::new(Biz::default());\n    do_test_biz(&biz);\n    println!(\"Clearing Biz metrics and running throughput demo again...(will take 20 seconds)\");\n    biz.metrics.clear();\n    do_test_biz(&biz);\n}\n\nfn do_test_biz(biz: &Arc<Biz>) {\n    let mut threads = Vec::new();\n    for _ in 0..5 {\n        let biz = Arc::clone(&biz);\n        let t = thread::spawn(move || {\n            for _ in 0..200 {\n                biz.biz();\n            }\n        });\n        threads.push(t);\n    }\n    for t in threads {\n        t.join().unwrap();\n    }\n    println!(\"Running Biz throughput demo... done! Here are the metrics for that run:\");\n    // Print the results!\n    let serialized = serde_prometheus::to_string(&**biz, None, HashMap::new()).unwrap();\n    println!(\"{}\", serialized);\n}\n\nfn main() {\n    simple_api_demo();\n\n    test_biz();\n\n    let baz = Baz::default();\n\n    sync_procmacro_demo(&baz);\n    let rt = tokio::runtime::Runtime::new().unwrap();\n    rt.block_on(async_procmacro_demo(baz));\n}\n"
  },
  {
    "path": "metered/Cargo.toml",
    "content": "[package]\nname = \"metered\"\nversion = \"0.9.0\"\nauthors = [\"Simon Chemouil <simon.chemouil@lambdacube.fr>\"]\nlicense = \"Apache-2.0 OR MIT\"\nreadme = \"../README.md\"\nkeywords = [\"metrics\", \"macro\"]\nrepository = \"https://github.com/magnet/metered-rs\"\ndescription = \"\"\"\nFast, ergonomic metrics for Rust!\n\"\"\"\ncategories = [\"rust-patterns\", \"development-tools::profiling\", \"data-structures\", \"algorithms\", \"asynchronous\"]\nedition = \"2018\"\n\n[dependencies]\nmetered-macro = { version = \"0.9.0\", path = \"../metered-macro\" }\naspect = \"0.3\"\nhdrhistogram = \"7.5\"\natomic = \"0.5\"\nparking_lot = \"0.12\"\nserde = { version = \"1.0\", features = [\"derive\"] }\ncfg-if = \"1.0.0\"\n\n[dev-dependencies]\nrand = \"0.8\"\nproptest = \"1.0\"\n\n[features]\n# no features by default\ndefault = []\n\n# Use the serde feature to make metered' types implement Serialize\nserialize = []\n\n# When enabled, the error count macro will skip serializing cleared entries (e.g counters with value 0)\n# This can be overridden with the `skip_cleared` macro attribute\nerror-count-skip-cleared-by-default = [\"metered-macro/error-count-skip-cleared-by-default\"]\n\n"
  },
  {
    "path": "metered/proptest-regressions/num_wrapper.txt",
    "content": "# Seeds for failure cases proptest has generated in the past. It is\n# automatically read and these particular cases re-run before any\n# novel cases are generated.\n#\n# It is recommended to check this file in to source control so that\n# everyone who runs the test benefits from these saved cases.\ncc 8a90d39ed68bfe0be7ac677e9dde1d980a2ea3208a402db987e3c6ae79187527 # shrinks to x = 0, y = 0\n"
  },
  {
    "path": "metered/src/atomic.rs",
    "content": "//! A module providing new-type Atomic wrapper that implements Debug &\n//! Serialize.\n\nuse serde::{Serialize, Serializer};\nuse std::{\n    fmt,\n    fmt::{Debug, Display},\n    sync::atomic::Ordering,\n};\n\n/// A new-type wrapper over `atomic::Atomic` that supports serde serialization\n/// and a cleaner debug output.\n///\n/// All default operations on the wrapper type are using a relaxed memory\n/// ordering, which makes it suitable for counters and little else.\n#[derive(Default)]\npub struct AtomicInt<T: Copy> {\n    /// The inner atomic instance\n    pub inner: atomic::Atomic<T>,\n}\n\nimpl<T: Copy> AtomicInt<T> {\n    /// Returns the current value\n    pub fn get(&self) -> T {\n        self.inner.load(Ordering::Relaxed)\n    }\n}\n\nimpl<T: Copy + Display> Debug for AtomicInt<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{}\", self.get())\n    }\n}\n\nmacro_rules! impl_blocks_for {\n    ($int:path: $method_name:ident) => {\n        impl AtomicInt<$int> {\n            /// Increments self\n            ///\n            /// Returns the previous count\n            pub fn incr(&self) -> $int {\n                self.inner.fetch_add(1, Ordering::Relaxed)\n            }\n\n            /// Increments self by count\n            ///\n            /// Returns the previous count\n            pub fn incr_by(&self, count: $int) -> $int {\n                self.inner.fetch_add(count, Ordering::Relaxed)\n            }\n\n            /// Decrements self\n            ///\n            /// Returns the previous count\n            pub fn decr(&self) -> $int {\n                self.inner.fetch_sub(1, Ordering::Relaxed)\n            }\n\n            /// Decrements self by count\n            ///\n            /// Returns the previous count\n            pub fn decr_by(&self, count: $int) -> $int {\n                self.inner.fetch_sub(count, Ordering::Relaxed)\n            }\n\n            /// Sets self to a new value\n            pub fn set(&self, v: $int) {\n                self.inner.store(v, Ordering::Relaxed);\n            }\n        }\n\n        impl Serialize for AtomicInt<$int> {\n            fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n            where\n                S: Serializer,\n            {\n                serializer.$method_name(self.get())\n            }\n        }\n    };\n}\n\nimpl_blocks_for!(u8: serialize_u8);\nimpl_blocks_for!(u16: serialize_u16);\nimpl_blocks_for!(u32: serialize_u32);\nimpl_blocks_for!(u64: serialize_u64);\nimpl_blocks_for!(u128: serialize_u128);\n\n#[cfg(test)]\nmod tests {\n    // The `atomic` crate makes no explicit guarantees on wrapping on overflow\n    // however `std` atomics that it uses underneath do.\n    //\n    // This test ensures `atomic`'s behavior does not deviate.\n    #[test]\n    fn test_atomic_wraps() {\n        use super::*;\n        let a = AtomicInt {\n            inner: atomic::Atomic::<u8>::new(255u8),\n        };\n\n        a.incr();\n        assert_eq!(a.get(), 0u8);\n\n        a.decr();\n        assert_eq!(a.get(), 255u8);\n    }\n}\n"
  },
  {
    "path": "metered/src/clear.rs",
    "content": "//! A module providing a Clear trait which signals metrics to clear their state\n//! if applicable.\n\nuse std::sync::Arc;\n\n/// The `Clear` trait is used to signal metrics to clear their state if\n/// applicable\n///\n/// While it is recommended all metrics should implement `Clear`, for instance\n/// to derive `Clear` on registries, some metrics may choose to do nothing. For\n/// instance, Gauges would be left in an inconsistent state if they were altered\n/// during clear.\npub trait Clear {\n    /// Requests to clear self.\n    fn clear(&self);\n}\n\nimpl<T: Clear> Clear for Arc<T> {\n    fn clear(&self) {\n        (**self).clear();\n    }\n}\n\nimpl<T: Clear> Clear for &T {\n    fn clear(&self) {\n        (*self).clear();\n    }\n}\n\n/// The `Clearable` trait is used to provide metadata around some types that can\n/// be cleared.\npub trait Clearable {\n    /// Returns true if self has been cleared and not yet been written to since.\n    fn is_cleared(&self) -> bool;\n}\n"
  },
  {
    "path": "metered/src/common/error_count.rs",
    "content": "//! A module providing the `ErrorCount` metric.\n\nuse crate::{\n    atomic::AtomicInt,\n    clear::Clear,\n    metric::{Counter, Metric},\n};\nuse aspect::{Advice, Enter, OnResult};\nuse serde::Serialize;\nuse std::ops::Deref;\n\n/// A metric counting how many times an expression typed std `Result` as\n/// returned an `Err` variant.\n///\n/// This is a light-weight metric.\n///\n/// By default, `ErrorCount` uses a lock-free `u64` `Counter`, which makes sense\n/// in multithread scenarios. Non-threaded applications can gain performance by\n/// using a `std::cell:Cell<u64>` instead.\n#[derive(Clone, Default, Debug, Serialize)]\npub struct ErrorCount<C: Counter = AtomicInt<u64>>(pub C);\n\nimpl<C: Counter, T, E> Metric<Result<T, E>> for ErrorCount<C> {}\n\nimpl<C: Counter> Enter for ErrorCount<C> {\n    type E = ();\n    fn enter(&self) {}\n}\n\nimpl<C: Counter, T, E> OnResult<Result<T, E>> for ErrorCount<C> {\n    fn on_result(&self, _: (), r: &Result<T, E>) -> Advice {\n        if r.is_err() {\n            self.0.incr();\n        }\n        Advice::Return\n    }\n}\n\nimpl<C: Counter> Clear for ErrorCount<C> {\n    fn clear(&self) {\n        self.0.clear()\n    }\n}\n\nimpl<C: Counter> Deref for ErrorCount<C> {\n    type Target = C;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/hit_count.rs",
    "content": "//! A module providing the `HitCount` metric.\n\nuse crate::{\n    atomic::AtomicInt,\n    clear::Clear,\n    metric::{Counter, Metric},\n};\nuse aspect::{Enter, OnResult};\nuse serde::Serialize;\nuse std::ops::Deref;\n\n/// A metric counting how many times an expression as been hit, before it\n/// returns.\n///\n/// This is a light-weight metric.\n///\n/// By default, `HitCount` uses a lock-free `u64` `Counter`, which makes sense\n/// in multithread scenarios. Non-threaded applications can gain performance by\n/// using a `std::cell:Cell<u64>` instead.\n#[derive(Clone, Default, Debug, Serialize)]\npub struct HitCount<C: Counter = AtomicInt<u64>>(pub C);\n\nimpl<C: Counter, R> Metric<R> for HitCount<C> {}\n\nimpl<C: Counter> Enter for HitCount<C> {\n    type E = ();\n    fn enter(&self) -> Self::E {\n        self.0.incr();\n    }\n}\n\nimpl<C: Counter, R> OnResult<R> for HitCount<C> {}\n\nimpl<C: Counter> Clear for HitCount<C> {\n    fn clear(&self) {\n        self.0.clear()\n    }\n}\n\nimpl<C: Counter> Deref for HitCount<C> {\n    type Target = C;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/in_flight.rs",
    "content": "//! A module providing the `InFlight` metric.\n\nuse crate::{\n    atomic::AtomicInt,\n    clear::Clear,\n    metric::{Gauge, Metric},\n};\nuse aspect::{Advice, Enter, OnResult};\nuse serde::Serialize;\nuse std::ops::Deref;\n\n/// A metric providing an in-flight gauge, showing how many calls are currently\n/// active for an expression.\n///\n/// This is a light-weight metric.\n///\n/// This makes sense mostly in a multi-threaded situation where several threads\n/// may call the same method constantly, and we want to monitor how many are\n/// active at a given time.\n///\n/// The [`Throughput`] metric shows an alternative view\n/// of the same picture, by reporting how many transactions per seconds are\n/// processed by an expression.\n///\n/// By default, `InFlight` uses a lock-free `u64` [`Gauge`], which makes sense\n/// in multithread scenarios. Non-threaded applications can gain performance by\n/// using a `std::cell:Cell<u64>` instead.\n\n#[derive(Clone, Default, Debug, Serialize)]\npub struct InFlight<G: Gauge = AtomicInt<u64>>(pub G);\n\nimpl<G: Gauge, R> Metric<R> for InFlight<G> {}\n\nimpl<G: Gauge> Enter for InFlight<G> {\n    type E = ();\n    fn enter(&self) {\n        self.0.incr();\n    }\n}\n\nimpl<G: Gauge, R> OnResult<R> for InFlight<G> {\n    fn leave_scope(&self, _: ()) -> Advice {\n        self.0.decr();\n        Advice::Return\n    }\n}\n\nimpl<G: Gauge> Clear for InFlight<G> {\n    fn clear(&self) {\n        // Do nothing: an InFlight metric\n        // would get in an inconsistent state if cleared\n    }\n}\n\nimpl<G: Gauge> Deref for InFlight<G> {\n    type Target = G;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/mod.rs",
    "content": "//! A module providing common metrics.\n\nmod error_count;\nmod hit_count;\nmod in_flight;\nmod none_count;\nmod response_time;\nmod throughput;\n\npub use error_count::ErrorCount;\npub use hit_count::HitCount;\npub use in_flight::InFlight;\npub use none_count::NoneCount;\npub use response_time::ResponseTime;\npub use throughput::{AtomicTxPerSec, RecordThroughput, Throughput, TxPerSec};\n"
  },
  {
    "path": "metered/src/common/none_count.rs",
    "content": "//! A module providing the `NoneCount` metric.\n\nuse crate::{\n    atomic::AtomicInt,\n    clear::Clear,\n    metric::{Counter, Metric},\n};\nuse aspect::{Advice, Enter, OnResult};\nuse serde::Serialize;\nuse std::ops::Deref;\n\n/// A metric counting how many times the return value is Ok(None) or None.\n///\n/// `SomeCount` is not provided since can be calculated by subtracting `NoneCount` from `HitCount`.\n///\n/// This is a light-weight metric.\n///\n/// By default, `NoneCount` uses a lock-free `u64` `Counter`, which makes sense\n/// in multithread scenarios. Non-threaded applications can gain performance by\n/// using a `std::cell:Cell<u64>` instead.\n#[derive(Clone, Default, Debug, Serialize)]\npub struct NoneCount<C: Counter = AtomicInt<u64>>(pub C);\n\nimpl<C: Counter, T, E> Metric<Result<Option<T>, E>> for NoneCount<C> {}\n\nimpl<C: Counter, T> Metric<Option<T>> for NoneCount<C> {}\n\nimpl<C: Counter> Enter for NoneCount<C> {\n    type E = ();\n    fn enter(&self) {}\n}\n\nimpl<C: Counter, T, E> OnResult<Result<Option<T>, E>> for NoneCount<C> {\n    fn on_result(&self, _: (), r: &Result<Option<T>, E>) -> Advice {\n        if matches!(r, Ok(None)) {\n            self.0.incr();\n        }\n        Advice::Return\n    }\n}\n\nimpl<C: Counter, T> OnResult<Option<T>> for NoneCount<C> {\n    fn on_result(&self, _: (), r: &Option<T>) -> Advice {\n        if r.is_none() {\n            self.0.incr();\n        }\n        Advice::Return\n    }\n}\n\nimpl<C: Counter> Clear for NoneCount<C> {\n    fn clear(&self) {\n        self.0.clear();\n    }\n}\n\nimpl<C: Counter> Deref for NoneCount<C> {\n    type Target = C;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/response_time.rs",
    "content": "//! A module providing the `ResponseTime` metric.\n\nuse crate::{\n    clear::Clear,\n    hdr_histogram::AtomicHdrHistogram,\n    metric::{Histogram, Metric},\n    time_source::{Instant, StdInstant},\n};\nuse aspect::{Advice, Enter, OnResult};\nuse serde::{Serialize, Serializer};\nuse std::{ops::Deref, time::Duration};\n\n/// A metric measuring the response time of an expression, that is the duration\n/// the expression needed to complete.\n///\n/// Because it retrieves the current time before calling the expression,\n/// computes the elapsed duration and registers it to an histogram, this is a\n/// rather heavy-weight metric better applied at entry-points.\n///\n/// By default, `ResponseTime` uses an atomic hdr histogram and a synchronized\n/// time source, which work better in multithread scenarios. Non-threaded\n/// applications can gain performance by using unsynchronized structures\n/// instead.\n#[derive(Clone)]\npub struct ResponseTime<H: Histogram = AtomicHdrHistogram, T: Instant = StdInstant>(\n    pub H,\n    std::marker::PhantomData<T>,\n);\n\nimpl<H: Histogram, T: Instant> ResponseTime<H, T> {\n    /// Build a ResponseTime with a custom histogram bound\n    /// \n    /// ```rust\n    /// use std::time::Duration;\n    /// use metered::{ResponseTime, hdr_histogram::AtomicHdrHistogram, time_source::StdInstantMicros};\n    /// \n    /// let response_time_millis: ResponseTime =\n    ///     ResponseTime::with_bound(Duration::from_secs(4));\n    /// \n    /// assert_eq!(response_time_millis.histogram().bound(), 4_000);\n    /// \n    /// let response_time_micros: ResponseTime<AtomicHdrHistogram, StdInstantMicros> =\n    ///     ResponseTime::with_bound(Duration::from_secs(4));\n    /// \n    /// assert_eq!(response_time_micros.histogram().bound(), 4_000_000);\n    /// ```\n    pub fn with_bound(bound: Duration) -> Self {\n        ResponseTime(H::with_bound(T::units(bound)), std::marker::PhantomData)\n    }\n}\n\nimpl<H: Histogram, T: Instant> Default for ResponseTime<H, T> {\n    fn default() -> Self {\n        // A HdrHistogram measuring latencies from 1ms to 5minutes\n        // All recordings will be saturating, that is, a value higher than 5 minutes\n        // will be replace by 5 minutes...\n        ResponseTime(H::with_bound(5 * 60 * T::ONE_SEC), std::marker::PhantomData)\n    }\n}\n\nimpl<H: Histogram, T: Instant, R> Metric<R> for ResponseTime<H, T> {}\n\nimpl<H: Histogram, T: Instant> Enter for ResponseTime<H, T> {\n    type E = T;\n\n    fn enter(&self) -> T {\n        T::now()\n    }\n}\n\nimpl<H: Histogram, T: Instant, R> OnResult<R> for ResponseTime<H, T> {\n    fn leave_scope(&self, enter: T) -> Advice {\n        let elapsed = enter.elapsed_time();\n        self.0.record(elapsed);\n        Advice::Return\n    }\n}\n\nimpl<H: Histogram, T: Instant> Clear for ResponseTime<H, T> {\n    fn clear(&self) {\n        self.0.clear();\n    }\n}\n\nimpl<H: Histogram + Serialize, T: Instant> Serialize for ResponseTime<H, T> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        Serialize::serialize(&self.0, serializer)\n    }\n}\n\nuse std::{fmt, fmt::Debug};\nimpl<H: Histogram + Debug, T: Instant> Debug for ResponseTime<H, T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{:?}\", &self.0)\n    }\n}\n\nimpl<H: Histogram, T: Instant> Deref for ResponseTime<H, T> {\n    type Target = H;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/throughput/atomic_tps.rs",
    "content": "use super::{tx_per_sec::TxPerSec, RecordThroughput};\nuse crate::{\n    clear::Clear,\n    hdr_histogram::HdrHistogram,\n    time_source::{Instant, StdInstant},\n};\nuse parking_lot::Mutex;\nuse serde::{Serialize, Serializer};\n\n/// Thread-safe implementation of [`super::RecordThroughput`]. It uses a `Mutex`\n/// to wrap `TxPerSec`.\npub struct AtomicTxPerSec<T: Instant = StdInstant> {\n    /// The inner mutex protecting the `TxPerSec` value holding the histogram\n    pub inner: Mutex<TxPerSec<T>>,\n}\n\nimpl<T: Instant> AtomicTxPerSec<T> {\n    /// Returns a cloned snapshot of the inner histogram.\n    pub fn histogram(&self) -> HdrHistogram {\n        self.inner.lock().hdr_histogram.clone()\n    }\n}\n\nimpl<T: Instant> RecordThroughput for AtomicTxPerSec<T> {\n    #[inline]\n    fn on_result(&self) {\n        self.inner.lock().on_result()\n    }\n}\n\nimpl<T: Instant> Default for AtomicTxPerSec<T> {\n    fn default() -> Self {\n        AtomicTxPerSec {\n            inner: Mutex::new(TxPerSec::default()),\n        }\n    }\n}\n\nimpl<T: Instant> Clear for AtomicTxPerSec<T> {\n    fn clear(&self) {\n        self.inner.lock().clear();\n    }\n}\n\nimpl<T: Instant> Serialize for AtomicTxPerSec<T> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        let inner = self.inner.lock();\n        Serialize::serialize(&*inner, serializer)\n    }\n}\n\nuse std::{fmt, fmt::Debug};\nimpl<T: Instant> Debug for AtomicTxPerSec<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let inner = self.inner.lock();\n        write!(f, \"{:?}\", &*inner)\n    }\n}\n"
  },
  {
    "path": "metered/src/common/throughput/mod.rs",
    "content": "//! A module providing the `Throughput` metric.\n\nuse crate::{\n    clear::Clear,\n    metric::Metric,\n    time_source::{Instant, StdInstant},\n};\nuse aspect::{Advice, Enter, OnResult};\nuse serde::{Serialize, Serializer};\nuse std::ops::Deref;\n\nmod atomic_tps;\nmod tx_per_sec;\n\npub use atomic_tps::AtomicTxPerSec;\npub use tx_per_sec::TxPerSec;\n\n/// A metric providing a transaction per second count backed by a histogram.\n///\n/// Because it retrieves the current time before calling the expression, stores\n/// it to appropriately build time windows of 1 second and registers results to\n/// a histogram, this is a rather heavy-weight metric better applied at\n/// entry-points.\n///\n/// By default, `Throughput` uses an atomic transaction count backend and a\n/// synchronized time source, which work better in multithread scenarios.\n/// Non-threaded applications can gain performance by using unsynchronized\n/// structures instead.\n#[derive(Clone)]\npub struct Throughput<T: Instant = StdInstant, P: RecordThroughput = AtomicTxPerSec<T>>(\n    pub P,\n    std::marker::PhantomData<T>,\n);\n\n/// Trait to record the throughput on a [`Throughput`] instance.\npub trait RecordThroughput: Default {\n    /// Called after the execution that the throughput metric is measuring.\n    fn on_result(&self);\n}\n\nimpl<P: RecordThroughput, T: Instant> Default for Throughput<T, P> {\n    fn default() -> Self {\n        Throughput(P::default(), std::marker::PhantomData)\n    }\n}\n\nimpl<P: RecordThroughput + Serialize + Clear, T: Instant, R> Metric<R> for Throughput<T, P> {}\n\nimpl<P: RecordThroughput, T: Instant> Enter for Throughput<T, P> {\n    type E = ();\n\n    fn enter(&self) {}\n}\n\nimpl<P: RecordThroughput + Clear, T: Instant> Clear for Throughput<T, P> {\n    fn clear(&self) {\n        self.0.clear();\n    }\n}\n\nimpl<P: RecordThroughput + Serialize, T: Instant, R> OnResult<R> for Throughput<T, P> {\n    fn leave_scope(&self, _enter: ()) -> Advice {\n        self.0.on_result();\n        Advice::Return\n    }\n}\n\nimpl<P: RecordThroughput + Serialize, T: Instant> Serialize for Throughput<T, P> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        Serialize::serialize(&self.0, serializer)\n    }\n}\n\nuse std::{fmt, fmt::Debug};\nimpl<P: RecordThroughput + Debug, T: Instant> Debug for Throughput<T, P> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{:?}\", &self.0)\n    }\n}\n\nimpl<P: RecordThroughput, T: Instant> Deref for Throughput<T, P> {\n    type Target = P;\n\n    fn deref(&self) -> &Self::Target {\n        &self.0\n    }\n}\n"
  },
  {
    "path": "metered/src/common/throughput/tx_per_sec.rs",
    "content": "use super::RecordThroughput;\nuse crate::{\n    clear::Clear,\n    hdr_histogram::HdrHistogram,\n    time_source::{Instant, StdInstant},\n};\nuse serde::{Serialize, Serializer};\n\n/// Non-thread safe implementation of `RecordThroughput`. Use as\n/// `RefCell<TxPerSec<T>>`.\npub struct TxPerSec<T: Instant = StdInstant> {\n    /// The inner histogram\n    pub hdr_histogram: HdrHistogram,\n    start_time: Option<T>,\n    last_window: u64,\n    count: u64,\n    time_source: std::marker::PhantomData<T>,\n}\n\nimpl<T: Instant> Default for TxPerSec<T> {\n    fn default() -> Self {\n        TxPerSec {\n            // Bound at 100K TPS, higher values will be saturated...\n            // TODO: make this configurable :)\n            hdr_histogram: HdrHistogram::with_bound(100_000),\n            start_time: None,\n            last_window: 0,\n            count: 0,\n            time_source: std::marker::PhantomData,\n        }\n    }\n}\n\nimpl<T: Instant> RecordThroughput for std::cell::RefCell<TxPerSec<T>> {\n    #[inline]\n    fn on_result(&self) {\n        self.borrow_mut().on_result()\n    }\n}\n\nimpl<T: Instant> Clear for std::cell::RefCell<TxPerSec<T>> {\n    fn clear(&self) {\n        self.borrow_mut().clear();\n    }\n}\n\nimpl<T: Instant> TxPerSec<T> {\n    /// Record previous count if the 1-sec window has closed and advance time window\n    fn update(&mut self) {\n        if let Some(ref start_time) = self.start_time {\n            let elapsed = start_time.elapsed_time();\n            let this_window = elapsed / T::ONE_SEC;\n            if this_window > self.last_window {\n                // Record this window\n                self.hdr_histogram.record(self.count);\n                self.count = 0;\n\n                // Record windows with no samples\n                let empty_windows = this_window - self.last_window - 1;\n                if empty_windows > 0 {\n                    self.hdr_histogram.record_n(0, empty_windows)\n                }\n\n                // Advance window\n                self.last_window = this_window;\n            }\n        } else {\n            // Set first window start time\n            self.start_time = Some(T::now());\n        };\n    }\n    pub(crate) fn on_result(&mut self) {\n        self.update();\n        self.count += 1;\n    }\n\n    pub(crate) fn clear(&mut self) {\n        self.hdr_histogram.clear();\n        self.start_time = None;\n        self.last_window = 0;\n        self.count = 0;\n    }\n}\n\nimpl<T: Instant> Serialize for TxPerSec<T> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        Serialize::serialize(&self.hdr_histogram, serializer)\n    }\n}\n\nuse std::{fmt, fmt::Debug};\nimpl<T: Instant> Debug for TxPerSec<T> {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        write!(f, \"{:?}\", &self.hdr_histogram)\n    }\n}\n"
  },
  {
    "path": "metered/src/hdr_histogram.rs",
    "content": "//! A module providing thread-safe and unsynchronized implementations for\n//! Histograms, based on HdrHistogram.\n\nuse crate::{clear::Clear, metric::Histogram};\nuse parking_lot::Mutex;\nuse serde::{Serialize, Serializer};\n\n/// A thread-safe implementation of HdrHistogram\npub struct AtomicHdrHistogram {\n    inner: Mutex<HdrHistogram>,\n}\n\nimpl AtomicHdrHistogram {\n    /// Returns a cloned snapshot of the inner histogram.\n    pub fn histogram(&self) -> HdrHistogram {\n        self.inner.lock().clone()\n    }\n}\n\nimpl Histogram for AtomicHdrHistogram {\n    fn with_bound(max_bound: u64) -> Self {\n        let histo = HdrHistogram::with_bound(max_bound);\n        let inner = Mutex::new(histo);\n        AtomicHdrHistogram { inner }\n    }\n\n    fn record(&self, value: u64) {\n        self.inner.lock().record(value);\n    }\n}\n\nimpl Clear for AtomicHdrHistogram {\n    fn clear(&self) {\n        self.inner.lock().clear();\n    }\n}\n\nimpl Serialize for AtomicHdrHistogram {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        use std::ops::Deref;\n        let inner = self.inner.lock();\n        let inner = inner.deref();\n        Serialize::serialize(inner, serializer)\n    }\n}\n\nuse std::{fmt, fmt::Debug};\nimpl Debug for AtomicHdrHistogram {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let histo = self.inner.lock();\n        write!(f, \"AtomicHdrHistogram {{ {:?} }}\", &*histo)\n    }\n}\n\n/// An High-Dynamic Range Histogram\n///\n/// HdrHistograms can record and analyze sampled data in low-latency applications. Read more about HDR Histograms on [http://hdrhistogram.org/](http://hdrhistogram.org/)\n///\n/// This structure uses the `hdrhistogram` crate under the hood.\n#[derive(Clone)]\npub struct HdrHistogram {\n    histo: hdrhistogram::Histogram<u64>,\n}\n\nimpl HdrHistogram {\n    /// Instantiates a new HdrHistogram with a max_bound\n    ///\n    /// For instance, a max_bound of 60 * 60 * 1000 will allow to record\n    /// durations varying from 1 millisecond to 1 hour.\n    pub fn with_bound(max_bound: u64) -> Self {\n        let histo = hdrhistogram::Histogram::<u64>::new_with_bounds(1, max_bound, 2)\n            .expect(\"Could not instantiate HdrHistogram\");\n\n        HdrHistogram { histo }\n    }\n\n    /// Get the histogram bound\n    pub fn bound(&self) -> u64 {\n        self.histo.high()\n    }\n\n    /// Records a value to the histogram\n    ///\n    /// This is a saturating record: if the value is higher than `max_bound`,\n    /// max_bound will be recorded instead.\n    pub fn record(&mut self, value: u64) {\n        // All recordings will be saturating\n        self.histo.saturating_record(value);\n    }\n\n    /// Records  multiple samples for a value to the histogram\n    ///\n    /// This is a saturating record: if the value is higher than `max_bound`,\n    /// max_bound will be recorded instead.\n    pub fn record_n(&mut self, value: u64, count: u64) {\n        // All recordings will be saturating\n        self.histo.saturating_record_n(value, count);\n    }\n\n    /// Clears the values of the histogram\n    pub fn clear(&mut self) {\n        self.histo.reset();\n    }\n\n    /// Get the number of recorded values in the histogram.\n    pub fn len(&self) -> u64 {\n        self.histo.len()\n    }\n\n    /// Check if the histogram's recorded values are empty\n    pub fn is_empty(&self) -> bool {\n        self.histo.is_empty()\n    }\n\n    /// Get the lowest recorded value level in the histogram.\n    /// If the histogram has no recorded values, the value returned will be 0.\n    pub fn min(&self) -> u64 {\n        self.histo.min()\n    }\n\n    /// Get the highest recorded value level in the histogram.\n    /// If the histogram has no recorded values, the value returned is\n    /// undefined.\n    pub fn max(&self) -> u64 {\n        self.histo.max()\n    }\n\n    /// Get the computed mean value of all recorded values in the histogram.\n    pub fn mean(&self) -> f64 {\n        self.histo.mean()\n    }\n\n    /// Get the computed standard deviation of all recorded\n    /// values in the histogram\n    pub fn stdev(&self) -> f64 {\n        self.histo.stdev()\n    }\n\n    /// Get the value at the 90% quantile.\n    pub fn p90(&self) -> u64 {\n        self.histo.value_at_quantile(0.9)\n    }\n\n    /// Get the value at the 95% quantile.\n    pub fn p95(&self) -> u64 {\n        self.histo.value_at_quantile(0.95)\n    }\n\n    /// Get the value at the 99% quantile.\n    pub fn p99(&self) -> u64 {\n        self.histo.value_at_quantile(0.99)\n    }\n\n    /// Get the value at the 99.9% quantile.\n    pub fn p999(&self) -> u64 {\n        self.histo.value_at_quantile(0.999)\n    }\n\n    /// Get the value at the 99.99% quantile.\n    pub fn p9999(&self) -> u64 {\n        self.histo.value_at_quantile(0.9999)\n    }\n}\n\nimpl Serialize for HdrHistogram {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        let hdr = &self.histo;\n\n        /// A percentile of this histogram - for supporting serializers this\n        /// will ignore the key (such as `90%ile`) and instead add a\n        /// dimension to the metrics (such as `quantile=0.9`).\n        macro_rules! ile {\n            ($e:expr) => {\n                &MetricAlias(concat!(\"!|quantile=\", $e), hdr.value_at_quantile($e))\n            };\n        }\n\n        /// A 'qualified' metric name - for supporting serializers this will\n        /// prepend the metric name to this key, outputting\n        /// `response_time_count`, for example rather than just `count`.\n        macro_rules! qual {\n            ($e:expr) => {\n                &MetricAlias(\"<|\", $e)\n            };\n        }\n\n        use serde::ser::SerializeMap;\n\n        let mut tup = serializer.serialize_map(Some(10))?;\n        tup.serialize_entry(\"samples\", qual!(hdr.len()))?;\n        tup.serialize_entry(\"min\", qual!(hdr.min()))?;\n        tup.serialize_entry(\"max\", qual!(hdr.max()))?;\n        tup.serialize_entry(\"mean\", qual!(hdr.mean()))?;\n        tup.serialize_entry(\"stdev\", qual!(hdr.stdev()))?;\n        tup.serialize_entry(\"90%ile\", ile!(0.9))?;\n        tup.serialize_entry(\"95%ile\", ile!(0.95))?;\n        tup.serialize_entry(\"99%ile\", ile!(0.99))?;\n        tup.serialize_entry(\"99.9%ile\", ile!(0.999))?;\n        tup.serialize_entry(\"99.99%ile\", ile!(0.9999))?;\n        tup.end()\n    }\n}\n\n/// This is a mocked 'newtype' (eg. `A(u64)`) that instead allows us to\n/// define our own type name that doesn't have to abide by Rust's constraints\n/// on type names. This allows us to do some manipulation of our metrics,\n/// allowing us to add dimensionality to our metrics via key=value pairs, or\n/// key manipulation on serializers that support it.\nstruct MetricAlias<T: Serialize>(&'static str, T);\nimpl<T: Serialize> Serialize for MetricAlias<T> {\n    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>\n    where\n        S: Serializer,\n    {\n        serializer.serialize_newtype_struct(self.0, &self.1)\n    }\n}\n\nimpl Debug for HdrHistogram {\n    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {\n        let hdr = &self.histo;\n        let ile = |v| hdr.value_at_percentile(v);\n        write!(\n            f,\n            \"HdrHistogram {{\n            samples: {}, min: {}, max: {}, mean: {}, stdev: {},\n            90%ile = {}, 95%ile = {}, 99%ile = {}, 99.9%ile = {}, 99.99%ile = {} }}\",\n            hdr.len(),\n            hdr.min(),\n            hdr.max(),\n            hdr.mean(),\n            hdr.stdev(),\n            ile(90.0),\n            ile(95.0),\n            ile(99.0),\n            ile(99.9),\n            ile(99.99)\n        )\n    }\n}\n\nuse std::cell::RefCell;\n\nimpl Histogram for RefCell<HdrHistogram> {\n    fn with_bound(max_value: u64) -> Self {\n        RefCell::new(HdrHistogram::with_bound(max_value))\n    }\n\n    fn record(&self, value: u64) {\n        self.borrow_mut().record(value);\n    }\n}\n\nimpl Clear for RefCell<HdrHistogram> {\n    fn clear(&self) {\n        self.borrow_mut().clear();\n    }\n}\n"
  },
  {
    "path": "metered/src/int_counter.rs",
    "content": "//! A module providing thread-safe and unsynchronized implementations for\n//! Counters on various unsized integers.\n\nuse crate::{\n    atomic::AtomicInt,\n    clear::{Clear, Clearable},\n    metric::Counter,\n    num_wrapper::NumWrapper,\n};\nuse std::cell::Cell;\n\nmacro_rules! impl_counter_for {\n    ($int:path) => {\n        impl Counter for Cell<$int> {\n            fn incr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                self.set(self.get().wrapping_add(v));\n            }\n        }\n\n        impl Clear for Cell<$int> {\n            fn clear(&self) {\n                self.set(0);\n            }\n        }\n\n        impl Clearable for Cell<$int> {\n            fn is_cleared(&self) -> bool {\n                self.get() == 0\n            }\n        }\n\n        impl Counter for AtomicInt<$int> {\n            fn incr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                AtomicInt::<$int>::incr_by(&self, v);\n            }\n        }\n\n        impl Clear for AtomicInt<$int> {\n            fn clear(&self) {\n                AtomicInt::<$int>::set(&self, 0);\n            }\n        }\n\n        impl Clearable for AtomicInt<$int> {\n            fn is_cleared(&self) -> bool {\n                AtomicInt::<$int>::get(&self) == 0\n            }\n        }\n    };\n}\n\nimpl_counter_for!(u8);\nimpl_counter_for!(u16);\nimpl_counter_for!(u32);\nimpl_counter_for!(u64);\nimpl_counter_for!(u128);\n"
  },
  {
    "path": "metered/src/int_gauge.rs",
    "content": "//! A module providing thread-safe and unsynchronized implementations for Gauges\n//! on various unsized integers.\n\nuse crate::{atomic::AtomicInt, metric::Gauge, num_wrapper::NumWrapper};\nuse std::cell::Cell;\n\nmacro_rules! impl_gauge_for {\n    ($int:path) => {\n        impl Gauge for Cell<$int> {\n            fn incr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                self.set(self.get().wrapping_add(v));\n            }\n\n            fn decr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                self.set(self.get().wrapping_sub(v));\n            }\n        }\n\n        impl Gauge for AtomicInt<$int> {\n            fn incr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                AtomicInt::<$int>::incr_by(&self, v);\n            }\n\n            fn decr_by(&self, count: usize) {\n                let v = NumWrapper::<$int>::wrap(count);\n                AtomicInt::<$int>::decr_by(&self, v);\n            }\n        }\n    };\n}\n\nimpl_gauge_for!(u8);\nimpl_gauge_for!(u16);\nimpl_gauge_for!(u32);\nimpl_gauge_for!(u64);\nimpl_gauge_for!(u128);\n"
  },
  {
    "path": "metered/src/lib.rs",
    "content": "//! # Fast, ergonomic metrics for Rust!\n//!\n//! Metered helps you measure the performance of your programs in production.\n//! Inspired by Coda Hale's Java metrics library, Metered makes live\n//! measurements easy by providing measurement declarative and procedural\n//! macros, and a variety of useful metrics ready out-of-the-box:\n//! * [`HitCount`]: a counter tracking how much a piece of code was hit.\n//! * [`ErrorCount`]: a counter tracking how many errors were returned -- (works\n//!   on any expression returning a std `Result`)\n//! * [`InFlight`]: a gauge tracking how many requests are active\n//! * [`ResponseTime`]: statistics backed by an HdrHistogram of the duration of\n//!   an expression\n//! * [`Throughput`]: statistics backed by an HdrHistogram of how many times an\n//!   expression is called per second.\n//!\n//! These metrics are usually applied to methods, using provided procedural\n//! macros that generate the boilerplate.\n//!\n//! To achieve higher performance, these stock metrics can be customized to use\n//! non-thread safe (`!Sync`/`!Send`) datastructures, but they default to\n//! thread-safe datastructures implemented using lock-free strategies where\n//! possible. This is an ergonomical choice to provide defaults that work in all\n//! situations.\n//!\n//! Metered is designed as a zero-overhead abstraction -- in the sense that the\n//! higher-level ergonomics should not cost over manually adding metrics.\n//! Notably, stock metrics will *not* allocate memory after they're initialized\n//! the first time.  However, they are triggered at every method call and it can\n//! be interesting to use lighter metrics (e.g\n//! [`HitCount`]) in hot code paths and favour\n//! heavier metrics ([`Throughput`],\n//! [`ResponseTime`]) in higher-level entry\n//! points.\n//!\n//! If a metric you need is missing, or if you want to customize a metric (for\n//! instance, to track how many times a specific error occurs, or react\n//! depending on your return type), it is possible to implement your own metrics\n//! simply by implementing the [`Metric`] trait .\n//!\n//! Metered does not use statics or shared global state. Instead, it lets you\n//! either build your own metric registry using the metrics you need, or can\n//! generate a metric registry for you using method attributes. Metered will\n//! generate one registry per `impl` block annotated with the `metered`\n//! attribute, under the name provided as the `registry` parameter. By default,\n//! Metered will expect the registry to be accessed as `self.metrics` but the\n//! expression can be overridden with the `registry_expr` attribute parameter.\n//! See the demos for more examples.\n//!\n//! Metered will generate metric registries that derive [`std::fmt::Debug`] and\n//! [`serde::Serialize`] to extract your metrics easily. Metered generates one\n//! sub-registry per method annotated with the `measure` attribute, hence\n//! organizing metrics hierarchically. This ensures access time to metrics in\n//! generated registries is always constant (and, when possible,\n//! cache-friendly), without any overhead other than the metric itself.\n//!\n//! Metered will happily measure any method, whether it is `async` or not, and\n//! the metrics will work as expected (e.g,\n//! [`ResponseTime`] will return the completion\n//! time across `await`'ed invocations).\n//!\n//! Metered's serialized metrics can be used in conjunction with\n//! [`serde_prometheus`](https://github.com/w4/serde_prometheus) to publish\n//! metrics to Prometheus.\n//!\n//! ## Example using procedural macros (recommended)\n//!\n//! ```\n//! # extern crate metered;\n//! # extern crate rand;\n//!\n//! use metered::{metered, Throughput, HitCount};\n//!\n//! #[derive(Default, Debug)]\n//! pub struct Biz {\n//!     metrics: BizMetrics,\n//! }\n//!\n//! #[metered::metered(registry = BizMetrics)]\n//! impl Biz {\n//!     #[measure([HitCount, Throughput])]\n//!     pub fn biz(&self) {        \n//!         let delay = std::time::Duration::from_millis(rand::random::<u64>() % 200);\n//!         std::thread::sleep(delay);\n//!     }   \n//! }\n//!\n//! # fn main() {\n//! # }\n//! ```\n//!\n//! In the snippet above, we will measure the\n//! [`HitCount`] and\n//! [`Throughput`] of the `biz` method.\n//!\n//! This works by first annotating the `impl` block with the `metered`\n//! annotation and specifying the name Metered should give to the metric\n//! registry (here `BizMetrics`). Later, Metered will assume the expression to\n//! access that repository is `self.metrics`, hence we need a `metrics` field\n//! with the `BizMetrics` type in `Biz`. It would be possible to use another\n//! field name by specificying another registry expression, such as\n//! `#[metered(registry = BizMetrics, registry_expr = self.my_custom_metrics)]`.\n//!\n//! Then, we must annotate which methods we wish to measure using the `measure`\n//! attribute, specifying the metrics we wish to apply: the metrics here are\n//! simply types of structures implementing the `Metric` trait, and you can\n//! define your own. Since there is no magic, we must ensure `self.metrics` can\n//! be accessed, and this will only work on methods with a `&self` or `&mut\n//! self` receiver.\n//!\n//! ## Example of manually using metrics\n//!\n//! ```\n//! use metered::{measure, HitCount, ErrorCount};\n//!\n//! #[derive(Default, Debug)]\n//! struct TestMetrics {\n//!     hit_count: HitCount,\n//!     error_count: ErrorCount,\n//! }\n//!\n//! fn test(should_fail: bool, metrics: &TestMetrics) -> Result<u32, &'static str> {\n//!     let hit_count = &metrics.hit_count;\n//!     let error_count = &metrics.error_count;\n//!     measure!(hit_count, {\n//!         measure!(error_count, {\n//!             if should_fail {\n//!                 Err(\"Failed!\")\n//!             } else {\n//!                 Ok(42)\n//!             }\n//!         })\n//!     })\n//! }\n//! ```\n//!\n//! The code above shows how different metrics compose, and in general the kind\n//! of boilerplate generated by the `#[metered]` procedural macro.\n\n#![deny(missing_docs)]\n#![deny(warnings)]\n\npub mod atomic;\npub mod clear;\npub mod common;\npub mod hdr_histogram;\npub mod int_counter;\npub mod int_gauge;\npub mod metric;\npub(crate) mod num_wrapper;\npub mod time_source;\n\npub use common::{ErrorCount, HitCount, InFlight, ResponseTime, Throughput};\npub use metered_macro::{error_count, metered};\npub use metric::{Counter, Gauge, Histogram, Metric};\n\n/// Re-export this type so 3rd-party crates don't need to depend on the\n/// `aspect-rs` crate.\npub use aspect::Enter;\n\n/// The `measure!` macro takes a reference to a metric and an expression.\n///\n/// It applies the metric and the expression is returned unchanged.\n/// \n/// ```rust\n/// use metered::{ResponseTime, measure};\n/// \n/// let response_time: ResponseTime = ResponseTime::default();\n/// \n/// measure!(&response_time, {\n///     std::thread::sleep(std::time::Duration::from_millis(100));\n/// });\n/// \n/// assert!(response_time.histogram().mean() > 0.0);\n/// ```\n/// \n/// It also allows to pass an array of references, which will expand recursively.\n/// \n/// ```rust\n/// use metered::{HitCount, ResponseTime, measure};\n/// \n/// let hit_count: HitCount = HitCount::default();\n/// let response_time: ResponseTime = ResponseTime::default();\n/// \n/// measure!([&hit_count, &response_time], {\n///     std::thread::sleep(std::time::Duration::from_millis(100));\n/// });\n/// \n/// assert_eq!(hit_count.get(), 1);\n/// assert!(response_time.histogram().mean() > 0.0);\n/// ```\n///\n#[macro_export]\nmacro_rules! measure {\n    ([$metric:expr], $expr:expr) => {{\n        $crate::measure!($metric, $expr)\n    }};\n    \n    ([$metric:expr, $($metrics:expr),*], $expr:expr) => {\n        $crate::measure!($metric, $crate::measure!([$($metrics),*], $expr))\n    };\n\n    ($metric:expr, $e:expr) => {{\n        let metric = $metric;\n        let guard = $crate::metric::ExitGuard::new(metric);\n        let mut result = $e;\n        guard.on_result(&mut result);\n        result\n    }};\n}\n\n/// Serializer for values within a struct generated by\n/// `metered::metered_error_variants` that adds an `error_kind` label when being\n/// serialized by `serde_prometheus`.\npub fn error_variant_serializer<S: serde::Serializer, T: serde::Serialize>(\n    value: &T,\n    serializer: S,\n) -> Result<S::Ok, S::Error> {\n    serializer.serialize_newtype_struct(\"!|variant[::]==<\", value)\n}\n\n/// Serializer for values within a struct generated by\n/// `metered::metered_error_variants` that adds an `error_kind` label when being\n/// serialized by `serde_prometheus`. If the `value` has been cleared. This\n/// operation is a no-op and the value wont be written to the `serializer`.\npub fn error_variant_serializer_skip_cleared<\n    S: serde::Serializer,\n    T: serde::Serialize + clear::Clearable,\n>(\n    value: &T,\n    serializer: S,\n) -> Result<S::Ok, S::Error> {\n    if value.is_cleared() {\n        serializer.serialize_none()\n    } else {\n        error_variant_serializer(value, serializer)\n    }\n}\n\n/// Trait applied to error enums by `#[metered::error_count]` to identify\n/// generated error count structs.\npub trait ErrorBreakdown<C: metric::Counter> {\n    /// The generated error count struct.\n    type ErrorCount;\n}\n\n/// Generic trait for `ErrorBreakdown::ErrorCount` to increase error count for a\n/// specific variant by 1.\npub trait ErrorBreakdownIncr<E> {\n    /// Increase count for given variant by 1.\n    fn incr(&self, e: &E);\n}\n"
  },
  {
    "path": "metered/src/metric.rs",
    "content": "//! A module defining the [`Metric`] trait and common metric backends.\n\nuse crate::clear::{Clear, Clearable};\n/// Re-export `aspect-rs`'s types to avoid crates depending on it.\npub use aspect::{Advice, Enter, OnResult, OnResultMut};\nuse serde::Serialize;\nuse std::marker::PhantomData;\n\n/// A trait to implement to be used in the `measure!` macro\n///\n/// Metrics wrap expressions to measure them.\n///\n/// The return type, R, of the expression can be captured to perform special\n/// handling.\npub trait Metric<R>: Default + OnResultMut<R> + Clear + Serialize {}\n\n// Needed to force `measure!` to work only with the [`Metric`] trait.\n#[doc(hidden)]\npub fn on_result<R, A: Metric<R>>(metric: &A, _enter: <A as Enter>::E, _result: &mut R) -> Advice {\n    metric.on_result(_enter, _result)\n}\n/// Handles a metric's lifecycle, guarding against early returns and panics.\npub struct ExitGuard<'a, R, M: Metric<R>> {\n    metric: &'a M,\n    enter: Option<<M as Enter>::E>,\n    _phantom: PhantomData<R>,\n}\n\nimpl<'a, R, M: Metric<R>> ExitGuard<'a, R, M> {\n    /// Enter a metric and create the guard for its exit.\n    /// This calls [`aspect::Enter::enter`] on the metric internally.\n    pub fn new(metric: &'a M) -> Self {\n        Self {\n            metric,\n            enter: Some(metric.enter()),\n            _phantom: PhantomData,\n        }\n    }\n\n    /// If no unexpected exit occurred, record the expression's result.\n    pub fn on_result(mut self, result: &mut R) {\n        if let Some(enter) = self.enter.take() {\n            self.metric.on_result(enter, result);\n        } else {\n            // OnResult called twice - we ignore\n        }\n    }\n}\n\nimpl<'a, R, M: Metric<R>> Drop for ExitGuard<'a, R, M> {\n    fn drop(&mut self) {\n        if let Some(enter) = self.enter.take() {\n            self.metric.leave_scope(enter);\n        } else {\n            // on_result was called, so the result was already recorded\n        }\n    }\n}\n\n/// A trait for Counters\npub trait Counter: Default + Clear + Clearable + Serialize {\n    /// Increment the counter\n    fn incr(&self) {\n        self.incr_by(1)\n    }\n\n    /// Increment the counter by count in one step\n    ///\n    /// Supplying a count larger than the underlying counter's remaining\n    /// capacity will wrap like [`u8::wrapping_add`] and similar methods.\n    fn incr_by(&self, count: usize);\n}\n\n/// A trait for Gauges\npub trait Gauge: Default + Clear + Serialize {\n    /// Increment the counter\n    fn incr(&self) {\n        self.incr_by(1)\n    }\n\n    /// Decrement the counter\n    fn decr(&self) {\n        self.decr_by(1)\n    }\n\n    /// Increment the gauge by count in one step\n    ///\n    /// Supplying a count larger than the underlying counter's remaining\n    /// capacity will wrap like [`u8::wrapping_add`] and similar methods.\n    fn incr_by(&self, count: usize);\n\n    /// Decrement the gauge by count in one step\n    ///\n    /// Supplying a count larger than the underlying counter's current value\n    /// will wrap like [`u8::wrapping_sub`] and similar methods.\n    fn decr_by(&self, count: usize);\n}\n\n/// A trait for Histograms\npub trait Histogram: Clear + Serialize {\n    /// Build a new histogram with the given max bounds\n    fn with_bound(max_value: u64) -> Self;\n\n    /// Record a value to the histogram.\n    ///\n    /// It will saturate if the value is higher than the histogram's\n    /// `max_value`.\n    fn record(&self, value: u64);\n}\n"
  },
  {
    "path": "metered/src/num_wrapper.rs",
    "content": "use std::marker::PhantomData;\n\n/// Metered metrics wrap when the counters are at capacity instead of\n/// overflowing or underflowing.\n///\n/// This struct provides wrapping logic where a metric can be incremented or\n/// decremented `N` times, where `N` is `usize`.\n///\n/// This is the most logical default:\n/// * It is observable\n/// * Metered should never panic business code\n/// * While we could argue that gauges saturate at max capacity, doing\n/// so will unbalance the gauge when decrementing the count after a saturated\n/// add. Instead we guarantee that for all `N`, each `incr_by(N)` followed by a\n/// `decr_by(N)` results in the original value.\n///\n/// Should we avoid calling `NumWrapper` with `count = 1`, i.e is the optimizer\n/// able to get rid of the wrapping computations?  The Godbolt compiler explorer\n/// shows that starting `opt-level = 1`, the generated call is equivalent.\n/// Program below for future reference:\n/// ```rust\n/// pub fn wrap(count: usize) -> u8 {\n///     (count % (u8::MAX as usize + 1)) as u8\n/// }\n///\n/// pub fn naive(c: u8) -> u8 {\n///     c.wrapping_add(wrap(1))\n/// }\n///\n/// pub fn manual(c: u8) -> u8  {\n///     c.wrapping_add(1)\n/// }\n///\n///\n/// pub fn main(){\n///     let m = manual(42);\n///     let n = naive(42);\n///     println!(\"{n} {m}\");\n/// }\n/// ```\npub(crate) struct NumWrapper<T>(PhantomData<T>);\n\nmacro_rules! impl_num_wrapper_for_smaller_than_usize {\n    ($int:path) => {\n        impl NumWrapper<$int> {\n            /// Wrap count wrapped over $int\n            pub(crate) fn wrap(count: usize) -> $int {\n                (count % (<$int>::MAX as usize + 1)) as $int\n            }\n        }\n    };\n}\n\nmacro_rules! impl_num_wrapper_for_equal_or_larger_than_usize {\n    ($int:path) => {\n        impl NumWrapper<$int> {\n            /// Return count as $int\n            pub(crate) fn wrap(count: usize) -> $int {\n                count as $int\n            }\n        }\n    };\n}\n\ncfg_if::cfg_if! {\n    if #[cfg(target_pointer_width = \"8\")] {\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u8);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u16);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u32);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u64);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u128);\n    } else if #[cfg(target_pointer_width = \"16\")] {\n        impl_num_wrapper_for_smaller_than_usize!(u8);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u16);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u32);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u64);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u128);\n    } else if #[cfg(target_pointer_width = \"32\")] {\n        impl_num_wrapper_for_smaller_than_usize!(u8);\n        impl_num_wrapper_for_smaller_than_usize!(u16);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u32);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u64);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u128);\n    } else if #[cfg(target_pointer_width = \"64\")] {\n        impl_num_wrapper_for_smaller_than_usize!(u8);\n        impl_num_wrapper_for_smaller_than_usize!(u16);\n        impl_num_wrapper_for_smaller_than_usize!(u32);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u64);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u128);\n    } else if #[cfg(target_pointer_width = \"128\")] {\n        impl_num_wrapper_for_smaller_than_usize!(u8);\n        impl_num_wrapper_for_smaller_than_usize!(u16);\n        impl_num_wrapper_for_smaller_than_usize!(u32);\n        impl_num_wrapper_for_smaller_than_usize!(u64);\n        impl_num_wrapper_for_equal_or_larger_than_usize!(u128);\n    } else {\n        compile_error!(\"Unsupported architecture - unhandled pointer size.\");\n    }\n}\n\n#[cfg(test)]\nmod tests {\n    use super::*;\n    use proptest::prelude::*;\n\n    // test with u8 for more wrapping - same model/properties applies to other ints.\n    fn incr_by(cc: u8, count: usize) -> u8 {\n        let v = NumWrapper::<u8>::wrap(count);\n        cc.wrapping_add(v)\n    }\n    fn incr_by_naive(mut cc: u8, count: usize) -> u8 {\n        for _ in 0..count {\n            cc = cc.wrapping_add(1);\n        }\n        cc\n    }\n\n    fn decr_by(cc: u8, count: usize) -> u8 {\n        let v = NumWrapper::<u8>::wrap(count);\n        cc.wrapping_sub(v)\n    }\n    fn decr_by_naive(mut cc: u8, count: usize) -> u8 {\n        for _ in 0..count {\n            cc = cc.wrapping_sub(1);\n        }\n        cc\n    }\n\n    proptest! {\n        #[test]\n        fn test_wrapping_incr(x: u8, y in 0..4096usize) {\n            // Tests if calling incr() Y times returns the same value\n            // as the optimized version\n            assert_eq!(incr_by_naive(x, y), incr_by(x, y));\n        }\n\n        #[test]\n        fn test_wrapping_decr(x: u8,  y in 0..4096usize) {\n            // Tests if calling decr() Y times returns the same value\n            // as the optimized version\n            assert_eq!(decr_by_naive(x, y), decr_by(x, y));\n        }\n\n        #[test]\n        fn test_wrapping_incr_decr_symmetric(x: u8, y: usize) {\n            // reduce strategy space, usize takes too long\n            // Tests if calling decr() Y times on incr() Y times returns\n            // the original value\n            assert_eq!(x, decr_by(incr_by(x, y), y));\n        }\n    }\n}\n"
  },
  {
    "path": "metered/src/time_source.rs",
    "content": "//! A module for Time Sources.\n\nuse std::convert::TryFrom;\nuse std::time::Duration;\n\n/// A trait for any time source providing time measurements in milliseconds.\n///\n/// It is useful to let users provide an unsynchronized  (`!Send`/`!Sync`) time\n/// source, unlike std's `Instant`.\npub trait Instant {\n    /// Creates a new Instant representing the current time.\n    fn now() -> Self;\n\n    /// Returns the elapsed time since an Instant was created.\n    ///\n    /// The unit depends on the Instant's resolution, as defined by the\n    /// `ONE_SEC` constant.\n    fn elapsed_time(&self) -> u64;\n\n    /// Return the amount of units from a Duration.\n    fn units(duration: Duration) -> u64;\n\n    /// One second in the instant units.\n    const ONE_SEC: u64;\n}\n\n/// A new-type wrapper for std Instants and Metered's\n/// [Instant] trait that measures time in milliseconds.\n#[derive(Debug, Clone)]\npub struct StdInstant(std::time::Instant);\nimpl Instant for StdInstant {\n    const ONE_SEC: u64 = 1_000;\n\n    fn now() -> Self {\n        StdInstant(std::time::Instant::now())\n    }\n\n    fn elapsed_time(&self) -> u64 {\n        let elapsed = self.0.elapsed();\n\n        elapsed.as_secs() * Self::ONE_SEC + u64::from(elapsed.subsec_millis())\n    }\n\n    fn units(duration: Duration) -> u64 {\n        u64::try_from(duration.as_millis()).unwrap_or(u64::MAX)\n    }\n}\n\n/// A new-type wrapper for std Instants and Metered's\n/// [Instant] trait that measures time in microseconds.\n#[derive(Debug, Clone)]\npub struct StdInstantMicros(std::time::Instant);\nimpl Instant for StdInstantMicros {\n    const ONE_SEC: u64 = 1_000_000;\n\n    fn now() -> Self {\n        StdInstantMicros(std::time::Instant::now())\n    }\n\n    fn elapsed_time(&self) -> u64 {\n        let elapsed = self.0.elapsed();\n\n        elapsed.as_secs() * Self::ONE_SEC + u64::from(elapsed.subsec_micros())\n    }\n\n    fn units(duration: Duration) -> u64 {\n        u64::try_from(duration.as_micros()).unwrap_or(u64::MAX)\n    }\n}\n"
  },
  {
    "path": "metered-macro/Cargo.toml",
    "content": "[package]\nname = \"metered-macro\"\nversion = \"0.9.0\"\nauthors = [\"Simon Chemouil <simon.chemouil@lambdacube.fr>\"]\nlicense = \"Apache-2.0 OR MIT\"\nreadme = \"../README.md\"\nkeywords = [\"metrics\", \"macro\"]\nrepository = \"https://github.com/magnet/metered-rs\"\ndescription = \"\"\"\nFast, ergonomic metrics for Rust!\n\"\"\"\ncategories = [\"rust-patterns\", \"development-tools::profiling\", \"data-structures\", \"algorithms\", \"asynchronous\"]\nedition = \"2018\"\n\n[dependencies]\nsyn = {version= \"1.0\", features = [\"full\"] }\naspect-weave = \"0.2\"\nsynattra = \"0.2\"\nquote = \"1.0\"\nproc-macro2 = \"1.0\"\nheck = \"0.4\"\nindexmap = \"1.8\"\n\n[dev-dependencies]\nserde = { version = \"1.0\", features = [\"derive\"] }\nmetered = { path = \"../metered\" }\nthiserror = \"1.0\"\nrand = \"0.8\"\n\n[features]\n# When enabled, the error count macro will skip serializing cleared entries (e.g counters with value 0)\n# This can be overridden with the `skip_cleared` macro attribute\nerror-count-skip-cleared-by-default = []\n\n[lib]\nproc-macro = true"
  },
  {
    "path": "metered-macro/src/error_count.rs",
    "content": "use crate::error_count_opts::ErrorCountKeyValAttribute;\nuse heck::ToSnakeCase;\nuse proc_macro::TokenStream;\nuse syn::{Attribute, Field, Fields, Ident, ItemEnum};\n\npub fn error_count(attrs: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {\n    let attrs: ErrorCountKeyValAttribute = syn::parse(attrs)?;\n    let attrs = attrs.to_error_count_opts();\n    let vis = attrs.visibility;\n    let metrics_ident = attrs.name_ident;\n\n    let mut input: ItemEnum = syn::parse(item)?;\n\n    let nested_attrs = get_nested_attrs(&mut input)?;\n\n    // get the type of the metric for each variant, most of the time this will be\n    // `C`, but if `#[nested(Abc)]` is on a variant field, the type will instead\n    // be set to `Abc` and incrs will be delegated there\n    let metric_type = nested_attrs\n        .iter()\n        .map(|(_, v)| {\n            if let Some((field, attr)) = v {\n                let error_type = &field.ty;\n                attr.parse_args::<proc_macro2::TokenStream>()\n                    .unwrap_or_else(\n                        |_| quote!(<#error_type as metered::ErrorBreakdown<C>>::ErrorCount),\n                    )\n            } else {\n                quote!(C)\n            }\n        })\n        .collect::<Vec<_>>();\n\n    let ident = &input.ident;\n\n    let variants = input.variants.iter().map(|v| &v.ident);\n    let stringified_variants = input.variants.iter().map(|v| v.ident.to_string());\n    let snake_variants: Vec<Ident> = input\n        .variants\n        .iter()\n        .map(|v| Ident::new(&v.ident.to_string().to_snake_case(), v.ident.span()))\n        .collect();\n\n    // copy #[cfg(..)] attributes from the variant and apply them to the\n    // corresponding error in our struct so we don't point to an invalid variant\n    // in certain configurations.\n    let cfg_attrs: Vec<Vec<&Attribute>> = input\n        .variants\n        .iter()\n        .map(|v| v.attrs.iter().filter(|v| v.path.is_ident(\"cfg\")).collect())\n        .collect();\n\n    // generate unbound arg params for each enum variant\n    let variants_args = nested_attrs\n        .iter()\n        .map(|(fields, nested_attr)| match &fields {\n            syn::Fields::Named(_) => {\n                if let Some((field, _)) = nested_attr {\n                    let key = field.ident.as_ref().expect(\"field missing ident\");\n                    quote!({ #key, .. })\n                } else {\n                    quote!({ .. })\n                }\n            }\n            syn::Fields::Unnamed(_) => {\n                let args = fields.iter().map(|field| {\n                    if field.attrs.iter().any(|attr| attr.path.is_ident(\"nested\")) {\n                        quote!(nested)\n                    } else {\n                        quote!(_)\n                    }\n                });\n                quote! {\n                    (#( #args, )*)\n                }\n            }\n            syn::Fields::Unit => quote!(),\n        });\n\n    // generate incr calls for each variant, if a field is marked with `#[nested]`,\n    // the incr is instead delegated there\n    let variant_incr_call =\n        nested_attrs\n            .iter()\n            .zip(snake_variants.iter())\n            .map(|((_, nested_attr), ident)| {\n                if let Some((field, attr)) = nested_attr {\n                    let inner_val_ident = field\n                        .ident\n                        .clone()\n                        .unwrap_or_else(|| Ident::new(\"nested\", attr.bracket_token.span));\n                    quote! {{\n                        self.#ident.incr(#inner_val_ident);\n                    }}\n                } else {\n                    quote!(self.#ident.incr())\n                }\n            });\n\n    let skip_cleared = attrs.skip_cleared;\n    let serializer = nested_attrs.iter().map(|(_, nested_attr)| {\n        if skip_cleared && nested_attr.is_none() {\n            quote!(\"metered::error_variant_serializer_skip_cleared\")\n        } else {\n            quote!(\"metered::error_variant_serializer\")\n        }\n    });\n\n    Ok(quote! {\n        #input\n\n        #[derive(serde::Serialize, Default, Debug)]\n        #[allow(missing_docs)]\n        #vis struct #metrics_ident<C: metered::metric::Counter = metered::atomic::AtomicInt<u64>> {\n            #[serde(skip)]\n            __phantom: std::marker::PhantomData<C>,\n            #(\n                #(#cfg_attrs)*\n                #[serde(rename = #stringified_variants, serialize_with = #serializer)]\n                pub #snake_variants: #metric_type,\n            )*\n        }\n\n        impl<C: metered::metric::Counter> metered::ErrorBreakdownIncr<#ident> for #metrics_ident<C> {\n            fn incr(&self, err: &#ident) {\n                match err {\n                    #( #(#cfg_attrs)* #ident::#variants #variants_args => #variant_incr_call, )*\n                }\n            }\n        }\n\n        impl<C: metered::metric::Counter> metered::clear::Clear for #metrics_ident<C> {\n            fn clear(&self) {\n                #( #(#cfg_attrs)* self.#snake_variants.clear(); )*\n            }\n        }\n\n        impl<T, C: metered::metric::Counter> metered::metric::Metric<Result<T, #ident>> for #metrics_ident<C> {}\n\n        impl<C: metered::metric::Counter> metered::metric::Enter for #metrics_ident<C> {\n            type E = ();\n            fn enter(&self) {}\n        }\n\n        impl<T, C: metered::metric::Counter> metered::metric::OnResult<Result<T, #ident>> for #metrics_ident<C> {\n            fn on_result(&self, (): (), r: &Result<T, #ident>) -> metered::metric::Advice {\n                if let Err(e) = r {\n                    metered::ErrorBreakdownIncr::incr(self, e);\n                }\n                metered::metric::Advice::Return\n            }\n        }\n\n        impl<C: metered::metric::Counter> metered::ErrorBreakdown<C> for #ident {\n            type ErrorCount = #metrics_ident<C>;\n        }\n    }.into())\n}\n\ntype FieldWithNestedAttribute = Option<(Field, Attribute)>;\n\n/// Gets all variants from the given `ItemEnum`, and returns `Some(Field,\n/// Attribute)` along with each variant if one of fields contained a `#[nested]`\n/// attribute.\n///\n/// If a `#[nested]` attribute is found, then the attribute itself removed from\n/// `input` so that we don't get \"unrecognised attribute\" errors.\nfn get_nested_attrs(input: &mut ItemEnum) -> syn::Result<Vec<(Fields, FieldWithNestedAttribute)>> {\n    let attrs = input\n        .variants\n        .iter_mut()\n        .map(|v| {\n            // clone fields before we do any mutation on it so consumers can figure out the\n            // position of #[nested] fields.\n            let fields = v.fields.clone();\n\n            let inner_fields = match &mut v.fields {\n                syn::Fields::Named(v) => &mut v.named,\n                syn::Fields::Unnamed(v) => &mut v.unnamed,\n                _ => return Ok((fields, None)),\n            };\n\n            // field containing the nested attribute, along with the attribute itself\n            let mut nested_attr = None;\n\n            for field in inner_fields {\n                if let Some(pos) = field.attrs.iter().position(|a| a.path.is_ident(\"nested\")) {\n                    let attr = field.attrs.remove(pos);\n\n                    // if we've already found a nested attribute on a field in the current variant,\n                    // throw an error\n                    if nested_attr.is_some() {\n                        return Err(syn::Error::new(\n                            attr.bracket_token.span,\n                            \"Can't declare `#[nested]` on more than one field in a single variant\",\n                        ));\n                    }\n\n                    nested_attr = Some((field.clone(), attr.clone()));\n                }\n            }\n\n            Ok((fields, nested_attr))\n        })\n        .collect::<syn::Result<Vec<_>>>()?;\n\n    Ok(attrs)\n}\n"
  },
  {
    "path": "metered-macro/src/error_count_opts.rs",
    "content": "//! The module supporting `#[error_count]` options\n\nuse syn::{\n    parse::{Parse, ParseStream},\n    Result,\n};\n\nuse synattra::{types::KVOption, *};\n\nuse std::borrow::Cow;\n\npub struct ErrorCountOpts<'a> {\n    pub name_ident: &'a syn::Ident,\n    pub visibility: Cow<'a, syn::Visibility>,\n    pub skip_cleared: bool,\n}\n\npub struct ErrorCountKeyValAttribute {\n    pub values: syn::punctuated::Punctuated<ErrorCountOption, Token![,]>,\n}\n\nimpl ErrorCountKeyValAttribute {\n    fn validate(&self, input: ParseStream<'_>) -> Result<()> {\n        self.values\n            .iter()\n            .filter_map(|opt| {\n                if let ErrorCountOption::Name(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .ok_or_else(|| input.error(\"missing `name` attribute.\"))?;\n\n        let opt_types: std::collections::HashMap<_, _> = self\n            .values\n            .iter()\n            .map(|opt| (std::mem::discriminant(opt), opt.as_str()))\n            .collect();\n\n        for (opt_type, opt_name) in opt_types.iter() {\n            let count = self\n                .values\n                .iter()\n                .filter(|&opt| std::mem::discriminant(opt) == *opt_type)\n                .count();\n            if count > 1 {\n                let error = format!(\"`{}` attribute is defined more than once.\", opt_name);\n                return Err(input.error(error));\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn to_error_count_opts(&self) -> ErrorCountOpts<'_> {\n        let name_ident = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let ErrorCountOption::Name(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .expect(\"There should be a name! This error cannot happen if the structure has been validated first!\");\n\n        let visibility = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let ErrorCountOption::Visibility(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .map(Cow::Borrowed)\n            .unwrap_or_else(|| {\n                Cow::Owned(syn::parse_str::<syn::Visibility>(\"pub(crate)\").unwrap())\n            });\n\n        let skip_cleared = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let ErrorCountOption::SkipCleared(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .map(|value| value.value)\n            .unwrap_or(cfg!(feature = \"error-count-skip-cleared-by-default\"));\n\n        ErrorCountOpts {\n            name_ident,\n            visibility,\n            skip_cleared,\n        }\n    }\n}\n\nimpl Parse for ErrorCountKeyValAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let this = ErrorCountKeyValAttribute {\n            values: input.parse_terminated(ErrorCountOption::parse)?,\n        };\n\n        this.validate(input)?;\n\n        Ok(this)\n    }\n}\n\nmod kw {\n    syn::custom_keyword!(name);\n    syn::custom_keyword!(visibility);\n    syn::custom_keyword!(skip_cleared);\n}\n\npub type ErrorCountNameOption = KVOption<kw::name, syn::Ident>;\n\npub type ErrorCountVisibilityOption = KVOption<kw::visibility, syn::Visibility>;\n\npub type ErrorCountSkipClearedOption = KVOption<kw::skip_cleared, syn::LitBool>;\n\n#[allow(clippy::large_enum_variant)]\npub enum ErrorCountOption {\n    Name(ErrorCountNameOption),\n    Visibility(ErrorCountVisibilityOption),\n    SkipCleared(ErrorCountSkipClearedOption),\n}\n\nimpl ErrorCountOption {\n    pub fn as_str(&self) -> &str {\n        use syn::token::Token;\n        match self {\n            ErrorCountOption::Name(_) => <kw::name>::display(),\n            ErrorCountOption::Visibility(_) => <kw::visibility>::display(),\n            ErrorCountOption::SkipCleared(_) => <kw::skip_cleared>::display(),\n        }\n    }\n}\n\nimpl Parse for ErrorCountOption {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        if ErrorCountNameOption::peek(input) {\n            Ok(input.parse_as(ErrorCountOption::Name)?)\n        } else if ErrorCountVisibilityOption::peek(input) {\n            Ok(input.parse_as(ErrorCountOption::Visibility)?)\n        } else if ErrorCountSkipClearedOption::peek(input) {\n            Ok(input.parse_as(ErrorCountOption::SkipCleared)?)\n        } else {\n            let err = format!(\"invalid error_count option: {}\", input);\n            Err(input.error(err))\n        }\n    }\n}\n"
  },
  {
    "path": "metered-macro/src/lib.rs",
    "content": "//! Procedural macros for Metered, a metric library for Rust.\n//!\n//! Please check the Metered crate for more documentation.\n\n#![deny(warnings)]\n// The `quote!` macro requires deep recursion.\n#![recursion_limit = \"512\"]\n\n#[macro_use]\nextern crate syn;\n#[macro_use]\nextern crate quote;\n\nmod error_count;\nmod error_count_opts;\nmod measure_opts;\nmod metered;\nmod metered_opts;\n\nuse proc_macro::TokenStream;\n\n/// A procedural macro that generates a metric registry for an `impl` block.\n///\n/// ```\n/// use metered::{metered, Throughput, HitCount};\n///\n/// #[derive(Default, Debug)]\n/// pub struct Biz {\n///     metrics: BizMetrics,\n/// }\n///\n/// #[metered::metered(registry = BizMetrics)]\n/// impl Biz {\n///     #[measure([HitCount, Throughput])]\n///     pub fn biz(&self) {        \n///         let delay = std::time::Duration::from_millis(rand::random::<u64>() % 200);\n///         std::thread::sleep(delay);\n///     }   \n/// }\n/// #\n/// # let biz = Biz::default();\n/// # biz.biz();\n/// # assert_eq!(biz.metrics.biz.hit_count.0.get(), 1);\n/// ```\n///\n/// ### The `metered` attribute\n///\n/// `#[metered(registry = YourRegistryName, registry_expr =\n/// self.wrapper.my_registry)]`\n///\n/// `registry` is mandatory and must be a valid Rust ident.\n///\n/// `registry_expr` defaults to `self.metrics`, alternate values must be a valid\n/// Rust expression.\n///\n/// ### The `measure` attribute\n///\n/// Single metric:\n///\n/// `#[measure(path::to::MyMetric<u64>)]`\n///\n/// or:\n///\n/// `#[measure(type = path::to::MyMetric<u64>)]`\n///\n/// Multiple metrics:\n///\n/// `#[measure([path::to::MyMetric<u64>, path::AnotherMetric])]`\n///\n/// or\n///\n/// `#[measure(type = [path::to::MyMetric<u64>, path::AnotherMetric])]`\n///\n/// The `type` keyword is allowed because other keywords are planned for future\n/// extra attributes (e.g, instantation options).\n///\n/// When `measure` attribute is applied to an `impl` block, it applies for every\n/// method that has a `measure` attribute. If a method does not need extra\n/// measure infos, it is possible to annotate it with simply `#[measure]` and\n/// the `impl` block's `measure` configuration will be applied.\n///\n/// The `measure` keyword can be added several times on an `impl` block or\n/// method, which will add to the list of metrics applied. Adding the same\n/// metric several time will lead in a name clash.\n\n#[proc_macro_attribute]\npub fn metered(attrs: TokenStream, item: TokenStream) -> TokenStream {\n    metered::metered(attrs, item).unwrap_or_else(|e| TokenStream::from(e.to_compile_error()))\n}\n\n/// A procedural macro that generates a new metric that measures the amount\n/// of times each variant of an error has been thrown, to be used as\n/// crate-specific replacement for `metered::ErrorCount`.\n///\n/// ```\n/// # use metered_macro::{metered, error_count};\n/// # use thiserror::Error;\n/// #\n/// #[error_count(name = LibErrorCount, visibility = pub)]\n/// #[derive(Debug, Error)]\n/// pub enum LibError {\n/// #   #[error(\"read error\")]\n///     ReadError,\n/// #   #[error(\"init error\")]\n///     InitError,\n/// }\n///\n/// #[error_count(name = ErrorCount, visibility = pub)]\n/// #[derive(Debug, Error)]\n/// pub enum Error {\n/// #   #[error(\"error from lib: {0}\")]\n///     MyLibrary(#[from] #[nested] LibError),\n/// }\n///\n/// #[derive(Default, Debug)]\n/// pub struct Baz {\n///     metrics: BazMetrics,\n/// }\n///\n/// #[metered(registry = BazMetrics)]\n/// impl Baz {\n///     #[measure(ErrorCount)]\n///     pub fn biz(&self) -> Result<(), Error> {        \n///         Err(LibError::InitError.into())\n///     }   \n/// }\n///\n/// let baz = Baz::default();\n/// baz.biz();\n/// assert_eq!(baz.metrics.biz.error_count.my_library.read_error.get(), 0);\n/// assert_eq!(baz.metrics.biz.error_count.my_library.init_error.get(), 1);\n/// ```\n///\n/// - `name` is required and must be a valid Rust ident, this is the name of the\n///   generated struct containing a counter for each enum variant.\n/// - `visibility` specifies to visibility of the generated struct, it defaults\n///   to `pub(crate)`.\n/// - `skip_cleared` allows to make the serializer skip \"cleared\" entries, that\n///   is entries for which the `Clearable::is_cleared` function returns true\n///   (for counters, by default, whether they are 0). It defaults to whether the\n///   feature `error-count-skip-cleared-by-default` is enabled. By default, this\n///   feature is disabled, and no entry will be skipped.\n///\n///\n/// The `error_count` macro may only be applied to any enums that have a\n/// `std::error::Error` impl. The generated struct may then be included\n/// in `measure` attributes to measure the amount of errors returned of\n/// each variant defined in your error enum.\n\n#[proc_macro_attribute]\npub fn error_count(attrs: TokenStream, item: TokenStream) -> TokenStream {\n    error_count::error_count(attrs, item)\n        .unwrap_or_else(|e| TokenStream::from(e.to_compile_error()))\n}\n"
  },
  {
    "path": "metered-macro/src/measure_opts.rs",
    "content": "//! The module supporting `#[measure]` options\n\nuse syn::{\n    parse::{Parse, ParseStream},\n    Result,\n};\n\nuse synattra::{\n    types::{extra::InvokePath, KVOption, MultipleVal},\n    ParseStreamExt,\n};\n\npub struct MeasureRequest<'a> {\n    pub tpe: &'a syn::TypePath,\n    pub field_name: String,\n    pub debug: Option<&'a InvokePath>,\n}\n\nimpl<'a> MeasureRequest<'a> {\n    pub fn ident(&self) -> syn::Ident {\n        syn::Ident::new(&self.field_name, proc_macro2::Span::call_site())\n    }\n\n    pub fn type_path(&self) -> &syn::TypePath {\n        self.tpe\n    }\n}\n\npub enum MeasureRequestAttribute {\n    Empty,\n    NonEmpty(NonEmptyMeasureRequestAttribute),\n}\n\nimpl MeasureRequestAttribute {\n    pub fn to_requests(&self) -> Vec<MeasureRequest<'_>> {\n        match self {\n            MeasureRequestAttribute::Empty => Vec::new(),\n            MeasureRequestAttribute::NonEmpty(req) => req.to_requests(),\n        }\n    }\n}\n\nimpl Parse for MeasureRequestAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        if input.is_empty() {\n            Ok(MeasureRequestAttribute::Empty)\n        } else {\n            Ok(MeasureRequestAttribute::NonEmpty(\n                NonEmptyMeasureRequestAttribute::parse(input)?,\n            ))\n        }\n    }\n}\n\npub struct NonEmptyMeasureRequestAttribute {\n    pub paren_token: syn::token::Paren,\n    pub inner: Option<MeasureRequestAttributeInner>,\n}\n\nimpl NonEmptyMeasureRequestAttribute {\n    pub fn to_requests(&self) -> Vec<MeasureRequest<'_>> {\n        if let Some(ref inner) = self.inner {\n            inner.to_requests()\n        } else {\n            Vec::new()\n        }\n    }\n}\n\nimpl Parse for NonEmptyMeasureRequestAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let content;\n        let paren_token = parenthesized!(content in input);\n\n        let inner = if content.is_empty() {\n            None\n        } else {\n            Some(content.parse()?)\n        };\n\n        let this = NonEmptyMeasureRequestAttribute { paren_token, inner };\n\n        Ok(this)\n    }\n}\n\npub enum MeasureRequestAttributeInner {\n    TypePath(MeasureRequestTypePathAttribute),\n    KeyVal(MeasureRequestKeyValAttribute),\n}\n\nimpl MeasureRequestAttributeInner {\n    pub fn to_requests(&self) -> Vec<MeasureRequest<'_>> {\n        match self {\n            MeasureRequestAttributeInner::TypePath(type_path) => type_path.to_requests(),\n            MeasureRequestAttributeInner::KeyVal(key_val) => key_val.to_requests(),\n        }\n    }\n}\n\nimpl Parse for MeasureRequestAttributeInner {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        input\n            .try_parse_as(MeasureRequestAttributeInner::TypePath)\n            .or_else(|_| input.try_parse_as(MeasureRequestAttributeInner::KeyVal))\n            .map_err(|_| {\n                let err = format!(\"invalid format for measure attribute: {}\", input);\n                input.error(err)\n            })\n    }\n}\n\npub struct MeasureRequestTypePathAttribute {\n    pub type_paths: MultipleVal<syn::TypePath>,\n}\n\nimpl MeasureRequestTypePathAttribute {\n    pub fn to_requests(&self) -> Vec<MeasureRequest<'_>> {\n        let mut v = Vec::new();\n        for type_path in self.type_paths.iter() {\n            let field_name = make_field_name(type_path);\n            v.push(MeasureRequest {\n                tpe: type_path,\n                field_name,\n                debug: None,\n            })\n        }\n        v\n    }\n}\n\nimpl Parse for MeasureRequestTypePathAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        Ok(MeasureRequestTypePathAttribute {\n            type_paths: input.parse()?,\n        })\n    }\n}\n\npub struct MeasureRequestKeyValAttribute {\n    pub values: syn::punctuated::Punctuated<MeasureOptions, Token![,]>,\n}\n\nimpl MeasureRequestKeyValAttribute {\n    fn validate(&self, input: ParseStream<'_>) -> Result<()> {\n        self.values\n            .iter()\n            .filter_map(|opt| {\n                if let MeasureOptions::Type(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .ok_or_else(|| {\n                input.error(\n                    \"missing `type` attribute with a path to a valid metered::Metric struct.\",\n                )\n            })?;\n\n        let opt_types: std::collections::HashMap<_, _> = self\n            .values\n            .iter()\n            .map(|opt| (std::mem::discriminant(opt), opt.as_str()))\n            .collect();\n\n        for (opt_type, opt_name) in opt_types.iter() {\n            let count = self\n                .values\n                .iter()\n                .filter(|&opt| std::mem::discriminant(opt) == *opt_type)\n                .count();\n            if count > 1 {\n                let error = format!(\"`{}` attribute is defined more than once.\", opt_name);\n                return Err(input.error(error));\n            }\n        }\n\n        // self.values.iter().\n\n        Ok(())\n    }\n\n    pub fn to_requests(&self) -> Vec<MeasureRequest<'_>> {\n        let type_paths = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let MeasureOptions::Type(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .expect(\"There should be a type! This error cannot happen if the structure has been validated first!\");\n        let debug = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let MeasureOptions::Debug(dbg) = opt {\n                    Some(&dbg.value)\n                } else {\n                    None\n                }\n            })\n            .next();\n\n        let mut v = Vec::new();\n        for type_path in type_paths.iter() {\n            let field_name = make_field_name(type_path);\n            v.push(MeasureRequest {\n                tpe: type_path,\n                field_name,\n                debug,\n            })\n        }\n        v\n    }\n}\n\nfn make_field_name(type_path: &syn::TypePath) -> String {\n    use heck::ToSnakeCase;\n    type_path\n        .path\n        .segments\n        .last()\n        .unwrap() // never empty\n        .ident\n        .to_string()\n        .to_snake_case()\n}\n\nimpl Parse for MeasureRequestKeyValAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let this = MeasureRequestKeyValAttribute {\n            values: input.parse_terminated(MeasureOptions::parse)?,\n        };\n\n        this.validate(input)?;\n\n        Ok(this)\n    }\n}\n\nmod kw {\n    syn::custom_keyword!(debug);\n}\n\npub type MeasureTypeOption = KVOption<syn::Token![type], MultipleVal<syn::TypePath>>;\npub type MeasureDebugOption = KVOption<kw::debug, InvokePath>;\n\npub enum MeasureOptions {\n    Type(MeasureTypeOption),\n    Debug(MeasureDebugOption),\n}\n\nimpl MeasureOptions {\n    pub fn as_str(&self) -> &str {\n        use syn::token::Token;\n        match self {\n            MeasureOptions::Type(_) => <syn::Token![type]>::display(),\n            MeasureOptions::Debug(_) => <kw::debug>::display(),\n        }\n    }\n}\n\nimpl Parse for MeasureOptions {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        if MeasureTypeOption::peek(input) {\n            Ok(input.parse_as(MeasureOptions::Type)?)\n        } else if MeasureDebugOption::peek(input) {\n            Ok(input.parse_as(MeasureOptions::Debug)?)\n        } else {\n            let err = format!(\"invalid measure option: {}\", input);\n            Err(input.error(err))\n        }\n    }\n}\n"
  },
  {
    "path": "metered-macro/src/metered.rs",
    "content": "//! The module supporting #[metered]\n\nuse proc_macro::TokenStream;\n\nuse crate::{measure_opts::MeasureRequestAttribute, metered_opts::MeteredKeyValAttribute};\n\nuse aspect_weave::*;\nuse std::rc::Rc;\nuse synattra::ParseAttributes;\n\npub fn metered(attrs: TokenStream, item: TokenStream) -> syn::Result<TokenStream> {\n    let woven_impl_block = weave_impl_block::<MeteredWeave>(attrs, item)?;\n\n    let impl_block = &woven_impl_block.woven_block;\n    let metered = &woven_impl_block.main_attributes.to_metered();\n    let measured = &woven_impl_block.woven_fns;\n    let registry_name = &metered.registry_name;\n    let registry_ident = &metered.registry_ident;\n    let visibility = &metered.visibility;\n\n    let mut code = quote! {};\n\n    let mut reg_fields = quote! {};\n    let mut reg_clears = quote! {};\n\n    for (fun_name, _) in measured.iter() {\n        use heck::ToUpperCamelCase;\n        let fun_reg_name = format!(\n            \"{}{}\",\n            registry_name,\n            fun_name.to_string().to_upper_camel_case()\n        );\n        let fun_registry_ident = syn::Ident::new(&fun_reg_name, impl_block.impl_token.span);\n\n        reg_fields = quote! {\n            #reg_fields\n            pub #fun_name : #fun_registry_ident,\n        };\n\n        reg_clears = quote! {\n            #reg_clears\n            self.#fun_name.clear();\n        };\n    }\n\n    code = quote! {\n        #code\n\n        #[derive(Debug, Default, serde::Serialize)]\n        #[allow(missing_docs)]\n        #visibility struct #registry_ident {\n            #reg_fields\n        }\n\n\n        impl metered::clear::Clear for #registry_ident {\n            fn clear(&self) {\n                #reg_clears\n            }\n        }\n    };\n\n    drop(reg_fields);\n\n    for (fun_name, measure_request_attrs) in measured.iter() {\n        use heck::ToUpperCamelCase;\n        let fun_reg_name = format!(\n            \"{}{}\",\n            registry_name,\n            fun_name.to_string().to_upper_camel_case()\n        );\n        let fun_registry_ident = syn::Ident::new(&fun_reg_name, impl_block.impl_token.span);\n\n        let mut fun_reg_fields = quote! {};\n        let mut fun_reg_clears = quote! {};\n\n        for measure_req_attr in measure_request_attrs.iter() {\n            let metric_requests = measure_req_attr.to_requests();\n\n            for metric in metric_requests.iter() {\n                let metric_field = metric.ident();\n                let metric_type = metric.type_path();\n\n                fun_reg_fields = quote! {\n                    #fun_reg_fields\n                    pub #metric_field : #metric_type,\n                };\n\n                fun_reg_clears = quote! {\n                    #fun_reg_clears\n                    self.#metric_field.clear();\n                };\n            }\n        }\n\n        code = quote! {\n            #code\n\n            #[derive(Debug, Default, serde::Serialize)]\n            #[allow(missing_docs)]\n            #visibility struct #fun_registry_ident {\n                #fun_reg_fields\n            }\n\n            impl metered::clear::Clear for #fun_registry_ident {\n                fn clear(&self) {\n                    #fun_reg_clears\n                }\n            }\n        };\n    }\n\n    code = quote! {\n        #impl_block\n\n        #code\n    };\n\n    let result: TokenStream = code.into();\n    // println!(\"Result {}\", result.to_string());\n    Ok(result)\n}\n\nstruct MeteredWeave;\nimpl Weave for MeteredWeave {\n    type MacroAttributes = MeteredKeyValAttribute;\n\n    fn update_fn_block(\n        item_fn: &syn::ImplItemMethod,\n        main_attr: &Self::MacroAttributes,\n        fn_attr: &[Rc<<Self as ParseAttributes>::Type>],\n    ) -> syn::Result<syn::Block> {\n        let metered = main_attr.to_metered();\n        let ident = &item_fn.sig.ident;\n        let block = &item_fn.block;\n        // We must alter the block to capture early returns\n        // using a closure, and handle the async case.\n\n        let outer_block = if item_fn.sig.asyncness.is_some() {\n            // For versions before `.await` stabilization,\n            // We cannot use the `await` keyword in the `quote!` macro\n            // We'd like to simply be able to put this in the `quote!`:\n            //\n            // (move || async move #block)().await`\n\n            let await_fut = syn::parse_str::<syn::Expr>(\"fut.await\")?;\n            quote! {\n                {\n                    let fut = (move || async move #block)();\n                    #await_fut\n                }\n            }\n        } else {\n            quote! {\n                (move || #block)()\n            }\n        };\n\n        let r = measure_list(&metered.registry_expr, ident, fn_attr, outer_block);\n\n        let new_block = syn::parse2::<syn::Block>(r)?;\n        Ok(new_block)\n    }\n}\nimpl ParseAttributes for MeteredWeave {\n    type Type = MeasureRequestAttribute;\n\n    // const\n    fn fn_attr_name() -> &'static str {\n        \"measure\"\n    }\n}\n\nfn measure_list(\n    registry_expr: &syn::Expr,\n    fun_ident: &syn::Ident,\n    measure_request_attrs: &[Rc<MeasureRequestAttribute>],\n    mut inner: proc_macro2::TokenStream,\n) -> proc_macro2::TokenStream {\n    // Recursive macro invocations\n    for measure_req_attr in measure_request_attrs.iter() {\n        let metric_requests = measure_req_attr.to_requests();\n\n        for metric in metric_requests.iter() {\n            let metric_var = metric.ident();\n            inner = quote! {\n                metered::measure! { #metric_var, #inner }\n            };\n        }\n    }\n\n    // Let-bindings to avoid moving issues\n    for measure_req_attr in measure_request_attrs.iter() {\n        let metric_requests = measure_req_attr.to_requests();\n\n        for metric in metric_requests.iter() {\n            let metric_var = syn::Ident::new(&metric.field_name, proc_macro2::Span::call_site());\n\n            inner = quote! {\n                let #metric_var = &#registry_expr.#fun_ident.#metric_var;\n                #inner\n            };\n        }\n\n        // // Use debug routine if enabled!\n        // if let Some(opt) = metric.debug {\n        // }\n    }\n\n    // Add final braces\n    quote! {\n        {\n            #inner\n        }\n    }\n}\n"
  },
  {
    "path": "metered-macro/src/metered_opts.rs",
    "content": "//! The module supporting `#[metered]` options\n\nuse syn::{\n    parse::{Parse, ParseStream},\n    Result,\n};\n\nuse synattra::{types::KVOption, *};\n\nuse std::borrow::Cow;\n\npub struct Metered<'a> {\n    pub registry_ident: &'a syn::Ident,\n    pub registry_name: String,\n    pub registry_expr: Cow<'a, syn::Expr>,\n    pub visibility: Cow<'a, syn::Visibility>,\n}\n\npub struct MeteredKeyValAttribute {\n    pub values: syn::punctuated::Punctuated<MeteredOption, Token![,]>,\n}\n\nimpl MeteredKeyValAttribute {\n    fn validate(&self, input: ParseStream<'_>) -> Result<()> {\n        self.values\n            .iter()\n            .filter_map(|opt| {\n                if let MeteredOption::Registry(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .ok_or_else(|| input.error(\"missing `registry` attribute.\"))?;\n\n        let opt_types: std::collections::HashMap<_, _> = self\n            .values\n            .iter()\n            .map(|opt| (std::mem::discriminant(opt), opt.as_str()))\n            .collect();\n\n        for (opt_type, opt_name) in opt_types.iter() {\n            let count = self\n                .values\n                .iter()\n                .filter(|&opt| std::mem::discriminant(opt) == *opt_type)\n                .count();\n            if count > 1 {\n                let error = format!(\"`{}` attribute is defined more than once.\", opt_name);\n                return Err(input.error(error));\n            }\n        }\n\n        Ok(())\n    }\n\n    pub fn to_metered(&self) -> Metered<'_> {\n        let registry_ident = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let MeteredOption::Registry(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .expect(\"There should be a registry! This error cannot happen if the structure has been validated first!\");\n\n        let registry_name = registry_ident.to_string();\n\n        let registry_expr = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let MeteredOption::RegistryExpr(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .map(Cow::Borrowed)\n            .unwrap_or_else(|| Cow::Owned(syn::parse_str::<syn::Expr>(\"self.metrics\").unwrap()));\n\n        let visibility = self\n            .values\n            .iter()\n            .filter_map(|opt| {\n                if let MeteredOption::Visibility(tpe) = opt {\n                    Some(&tpe.value)\n                } else {\n                    None\n                }\n            })\n            .next()\n            .map(Cow::Borrowed)\n            .unwrap_or_else(|| {\n                Cow::Owned(syn::parse_str::<syn::Visibility>(\"pub(crate)\").unwrap())\n            });\n        Metered {\n            registry_ident,\n            registry_name,\n            registry_expr,\n            visibility,\n        }\n    }\n}\n\nimpl Parse for MeteredKeyValAttribute {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        let this = MeteredKeyValAttribute {\n            values: input.parse_terminated(MeteredOption::parse)?,\n        };\n\n        this.validate(input)?;\n\n        Ok(this)\n    }\n}\n\nmod kw {\n    syn::custom_keyword!(registry);\n    syn::custom_keyword!(registry_expr);\n    syn::custom_keyword!(visibility);\n}\n\npub type MeteredRegistryOption = KVOption<kw::registry, syn::Ident>;\n\npub type MeteredRegistryExprOption = KVOption<kw::registry_expr, syn::Expr>;\n\npub type MeteredVisibilityOption = KVOption<kw::visibility, syn::Visibility>;\n\n#[allow(clippy::large_enum_variant)]\npub enum MeteredOption {\n    Registry(MeteredRegistryOption),\n    RegistryExpr(MeteredRegistryExprOption),\n    Visibility(MeteredVisibilityOption),\n}\n\nimpl MeteredOption {\n    pub fn as_str(&self) -> &str {\n        use syn::token::Token;\n        match self {\n            MeteredOption::Registry(_) => <kw::registry>::display(),\n            MeteredOption::RegistryExpr(_) => <kw::registry_expr>::display(),\n            MeteredOption::Visibility(_) => <kw::visibility>::display(),\n        }\n    }\n}\n\nimpl Parse for MeteredOption {\n    fn parse(input: ParseStream<'_>) -> Result<Self> {\n        if MeteredRegistryOption::peek(input) {\n            Ok(input.parse_as(MeteredOption::Registry)?)\n        } else if MeteredRegistryExprOption::peek(input) {\n            Ok(input.parse_as(MeteredOption::RegistryExpr)?)\n        } else if MeteredVisibilityOption::peek(input) {\n            Ok(input.parse_as(MeteredOption::Visibility)?)\n        } else {\n            let err = format!(\"invalid metered option: {}\", input);\n            Err(input.error(err))\n        }\n    }\n}\n"
  },
  {
    "path": "rustfmt-unstable.toml",
    "content": "edition = \"2018\"\nimports_granularity=\"Crate\"\nnormalize_comments = true\nunstable_features = true\nwrap_comments = true\n\n"
  }
]