| Crates.io | firewood-macros |
| lib.rs | firewood-macros |
| version | 0.0.12 |
| created_at | 2025-06-30 02:54:24.996945+00 |
| updated_at | 2025-08-26 17:59:30.931175+00 |
| description | Proc macros for Firewood metrics |
| homepage | https://avalabs.org |
| repository | https://github.com/ava-labs/firewood |
| max_upload_size | |
| id | 1731363 |
| size | 36,196 |
A Rust procedural macro crate providing zero-allocation metrics instrumentation for the Firewood database.
This crate provides the #[metrics] attribute macro that automatically instruments functions with performance metrics collection. The macro is designed for high-performance applications where allocation overhead during metrics collection is unacceptable.
Result return valuesResult<T, E> typesAdd the dependency to your Cargo.toml:
[dependencies]
firewood-macros.workspace = true
metrics = "0.24"
coarsetime = "0.1"
use firewood_macros::metrics;
#[metrics("firewood.example")]
fn example() -> Result<Vec<Data>, DatabaseError> {
// Your function implementation
Ok(vec![])
}
#[metrics("firewood.example", "example operation")]
fn example(user: User) -> Result<(), DatabaseError> {
// Your function implementation
Ok(())
}
For each instrumented function, the macro generates two metrics:
Both metrics include a success label:
success="true" for Ok(_) resultssuccess="false" for Err(_) resultsFor #[metrics("firewood.query", "data retrieval")]:
firewood.example{success="true"} - Count of successful queriesfirewood.example{success="false"} - Count of failed queriesfirewood.example_ms{success="true"} - Timing of successful queriesfirewood.example_ms{success="false"} - Timing of failed queriesResult<T, E> typemetrics and coarsetime crates must be available in scopeis_some_and method)The macro generates code that avoids all runtime allocations:
// Static label arrays (no allocation)
static __METRICS_LABELS_SUCCESS: &[(&str, &str)] = &[("success", "true")];
static __METRICS_LABELS_ERROR: &[(&str, &str)] = &[("success", "false")];
// Compile-time string concatenation (no allocation)
metrics::counter!(concat!("my.metric", "_ms"), labels)
Result::is_err()The macro transforms this:
#[metrics("my.operation")]
fn my_function() -> Result<String, Error> {
Ok("result".to_string())
}
Into approximately this:
fn my_function() -> Result<String, Error> {
// Register metrics (once per process)
static __METRICS_REGISTERED: std::sync::Once = std::sync::Once::new();
__METRICS_REGISTERED.call_once(|| {
metrics::describe_counter!("my.operation", "Operation counter");
metrics::describe_counter!(concat!("my.operation", "_ms"), "Operation timing");
});
// Start timing
let __metrics_start = coarsetime::Instant::now();
// Execute original function
let __metrics_result = (|| {
Ok("result".to_string())
})();
// Record metrics
static __METRICS_LABELS_SUCCESS: &[(&str, &str)] = &[("success", "true")];
static __METRICS_LABELS_ERROR: &[(&str, &str)] = &[("success", "false")];
let __metrics_labels = if __metrics_result.is_err() {
__METRICS_LABELS_ERROR
} else {
__METRICS_LABELS_SUCCESS
};
metrics::counter!("my.operation", __metrics_labels).increment(1);
metrics::counter!(concat!("my.operation", "_ms"), __metrics_labels)
.increment(__metrics_start.elapsed().as_millis());
__metrics_result
}
The crate includes comprehensive tests:
cargo test -p firewood-macros
This crate is part of the Firewood project and follows the same licensing terms. See LICENSE.md at the top level for details.