metrics-rs / metrics

A metrics ecosystem for Rust.
MIT License
1.13k stars 157 forks source link

feat(util): new helper type for recovering recorder after installing it #362

Closed tobz closed 1 year ago

tobz commented 1 year ago

Context

In cases like #308, there can be a desire to ensure that a recorder flushes itself on process exit. As we install the recorder globally, such that it is leaked to provide the ability to acquire a static reference to it, recorders cannot normally participate in the typical Drop logic as objects are cleaned up before process exit.

Solution

This PR introduces a generic helper -- RecoverableRecorder<R> -- that allows for installing a wrapped version of the recorder, and acts as a drop guard to allow either manually "recovering" the recorder, or recovering it on drop such that the recorder's drop logic can also be called.

We wrap the recorder in an Arc<T>, and install a custom recorder wrapper that holds a Weak<T> reference. This allows the global recorder to provide access to the inner recorder without taking ownership of it.

When the caller manually seeks to recover the recorder, they call RecoverableRecorder::into_inner which attempts to unwrap the Arc<T> until there are no active references other than from the drop guard, which gives back the original recorder. If the drop guard is simply dropped, the original recorder too is dropped as soon as all active references to it have dropped, following the normal behavior of Arc<T>.

This does come with a small performance overhead, as every call through the weakly-held Recorder implementation must clone the Arc<T> before proxying the given method call, but it should be fairly minimal in practice. If performance is a huge concern, a recorder should implement its own drop guard for controlling flushing on process exit, but this is simply meant to be a generic solution when the application has no control over the recorder implementation.

Additionally, I've stripped out all of the atomic_cas and set_recorder_racy bits, as all illusions of metrics being no_std/embedded-compatible have sort of faded at this point, and it was just an opportune time to strip out the last vestiges.

tobz commented 1 year ago

Released in metrics-util@v0.15.1.