I'm testing a Recorder implementation and getting cross-test contamination because the recorder is shared across all threads and registered globally. I've had a look at how the crate tests its recorders and noticed how it uses Debugging::per_thread for thread-local metrics, and clear_recorder to test the entire recorder implementation in the same test, setting the recorder each time after clearing it. However, I don't think these ingredients suffice to test the same recorder implementation across different tests running in parallel in the same process.
I was wondering whether it's possible to introduce recorders that live within a scope, much like how tracing::dispatcher allows to set a scoped subscriber:
let recorder = MyRecorder::new();
let dispatcher = metrics::dispatch::Dispatcher::new(recorder);
// no default recorder
metrics::dispatcher::with_default(&dispatcher, || {
// `recorder` will handle metrics emitted within this scope.
});
// no default recorder again
This has definitely come up before and is likely something I'll tackle in the future since, as you note, it makes actually testing any code that uses metrics much more complex/finnicky.
I'm testing a
Recorder
implementation and getting cross-test contamination because the recorder is shared across all threads and registered globally. I've had a look at how the crate tests its recorders and noticed how it usesDebugging::per_thread
for thread-local metrics, andclear_recorder
to test the entire recorder implementation in the same test, setting the recorder each time after clearing it. However, I don't think these ingredients suffice to test the same recorder implementation across different tests running in parallel in the same process.I was wondering whether it's possible to introduce recorders that live within a scope, much like how
tracing::dispatcher
allows to set a scoped subscriber: