You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
structWrapper<E>{e:E,}#[metered::metered(registry = BizMetrics)]implBiz{#[measure([WrappedMetric<ErrorCount>])]pubfnbiz(&self,foo:bool) -> Result<(),Wrapper<Error>>{let e = if foo {Error::Foo}else{Error::Bar};Err(Wrapper{ e })}}
I did manage to write WrappedMetric, but had to require that T implements default. The full code is:
use metered::{
clear::Clear,
error_count,
metric::{Advice, OnResult, OnResultMut},
Enter, Metric,
};
use serde::Serialize;
use std::mem;
#[error_count(name = ErrorCount)]
enum Error {
Foo,
Bar,
}
struct Wrapper<E> {
e: E,
}
#[derive(Serialize, Default, Debug)]
struct WrappedMetric<EC>(EC);
impl<EC: Clear> Clear for WrappedMetric<EC> {
fn clear(&self) {
self.0.clear();
}
}
impl<EC: Enter> Enter for WrappedMetric<EC> {
type E = EC::E;
fn enter(&self) -> EC::E {
self.0.enter()
}
}
impl<T: Default, E, EC: Serialize + Default + Clear + Enter + OnResult<Result<T, E>>>
Metric<Result<T, Wrapper<E>>> for WrappedMetric<EC>
{
}
impl<T: Default, E, EC: Enter + OnResult<Result<T, E>>> OnResultMut<Result<T, Wrapper<E>>>
for WrappedMetric<EC>
{
fn on_result(&self, enter: EC::E, result: &mut Result<T, Wrapper<E>>) -> Advice {
// Many errors don't implement clone, so this only works if T implements default.
let orig = mem::replace(result, Ok(Default::default()));
let unwrapped = orig.map_err(|e| e.e);
let ret = OnResult::on_result(&self.0, enter, &unwrapped);
let recreated = unwrapped.map_err(|e| Wrapper { e });
let _ = mem::replace(result, recreated);
ret
}
}
#[derive(Default, Debug)]
struct Biz {
metrics: BizMetrics,
}
#[metered::metered(registry = BizMetrics)]
impl Biz {
#[measure([WrappedMetric<ErrorCount>])]
pub fn biz(&self, foo: bool) -> Result<(), Wrapper<Error>> {
let e = if foo { Error::Foo } else { Error::Bar };
Err(Wrapper { e })
}
}
fn main() {
let b = Biz {
metrics: Default::default(),
};
b.biz(false).unwrap_err();
b.biz(false).unwrap_err();
b.biz(true).unwrap_err();
let m = b.metrics.biz.wrapped_metric.0;
println!("{:?} {:?}", m.foo, m.bar);
}
The text was updated successfully, but these errors were encountered:
Cool. One simplification I found is that in order to get Metered, it is sufficient to implement OnResultMut, so we can leave the interface of OnResult unchanged. A complication is that we want to support any R, not just a Result<T, E>, so we cannot assume as_ref().
With the above what I did was change OnResultMut to take an R by value and return a new one. The changes are pretty small. I will open PRs.
If you have
It is hard to use it with a function like:
I did manage to write
WrappedMetric
, but had to require that T implements default. The full code is:The text was updated successfully, but these errors were encountered: