## A set of macros to function profiling
Contains some convenient macros to analyze function execution, like `count` to know how many times a function was called, `trace` to log when entering/exiting from a function and what are its arguments, and `cache` for pure functions cache.
## Features
| `count` | Makes available a macro `count!` to get how many times a function was called | None |
| `trace` | Prints when entering/exiting in a tagged function and its arguments | None |
| `cache` | Implements memoization for a tagged function | `once_cell` and `hashbrown` |
| `time` | Prints the elapsed time inside a function | None |
| `visible` | Changes the cache storage and counter visibility | None |
Each feature can be forbided, forced or setted to default (which is setted using features) in the attribute declaration. E.g:
```rust
// `cache`, `visible` will not be implemented
// `count` will obligatory be implemented
// `time` and `trace` will be implemented if the feature `time` is enable
#[moneta_fn::moneta(cache = "forbid", visible = "forbid", count = "force", time = "default")]
fn foo(a: u8) -> u8 {
unimplemented!()
}
```
## Type dependencies
When enabled in a function, `cache` requires that all parameters implement the `Debug` trait and `Clone` for the return type.
## Wait... Why `Debug` for parameters and not `Clone`?
Consider these scenarios:
```rust
#[moneta_fn::moneta]
fn foo<'a, T>(lhs: &'a T, rhs: &'a T) -> T {
unimplemented!()
}
```
It's hard to create cache storage with generic keys and lifetimes, once it can't be parsed in an equivalent format for a global `RwLock`.
Furthermore, it allows some optimizations for liked types:
```rust
#[moneta_fn::moneta]
fn foo<T: AsRef<str> + Debug>(lhs: T, rhs: T) -> T {
unimplemented!()
}
```
## I don't want `trace`/`count`/`cache` in my release builds. How do I disable it?
There isn't ~yet~ a good way to enable/disable specific features in different profiles. You'll need to set `default-features` to `false` and define which features you want. E.g:
```toml
[dependencies]
moneta_fn = { version = "*", default-features = false, features = ["cache", "count", "time"] }
```
Another way to do it, is using a setting a default feature.
```toml
[dependencies]
moneta_fn = { version = "*", default-features = false, features = ["cache", "count", "time"] }
[features]
default = ["debug_mode"]
debug_mode = ["moneta_fn/trace"]
```
And when compiling with a profile relase, use `--no-default-features`
```bash
cargo build --release --no-default-features
```
## How do I enable/disable `trace`/`count`/`cache` for just one function?
Set `trace`/`count`/`cache` as `force`/`forbid`
```rust
#[moneta_fn::moneta(cache = "forbid")] // Will not update cache storage
fn foo(a: u8) -> u8 {
unimplemented!()
}
```
## Macros
There are macros to manage implementation variables:
| `count` | `count` | Return an `usize` containing how many times an function was called |
| `get_counter` | `count` | Return the `std::sync::AtomicUsize` counter for the respective function |
| `reset_count` | `count` | Set the function counting to 0 |
| `get_cache` | `cache` | Return the `once_cell::Lazy<std::sync::RwLock<hashbrown::HashMap<String, T>>>` cache storage, where `T` is the function's return type |
All of these macros requires an argument containing the function's global path. E.g:
```rust
#[moneta_fn::moneta]
fn foo() {
unimplemented!()
}
pub mod bar {
#[moneta_fn:moneta]
pub fn baz() {
unimplemented!()
}
}
assert!(get_cache(foo).read().unwrap().is_empty())
assert_eq!(count!(bar::baz), 0)
```
## Will macro calls break when the outter feature be disabled?
No. The counting or cache will just not be updated.