LogRingFile

Struct LogRingFile 

Source
pub struct LogRingFile {
    pub file_path: Box<Path>,
    pub level: Level,
    pub format: LogFormat,
    pub buf_size: i32,
}
Available on crate feature ringfile only.
Expand description

The LogRingFile sink is a way to minimize the cost of logging, for debugging deadlock or race condition, when the problem cannot be reproduce with ordinary log (because disk I/O will slow down the execution and prevent the bug to occur).

§Usage

Enable feature ringfile in your Cargo.toml.

Replace the log setup with the following recipe::ring_file() in your test case:

(Set the level to Info or higher, to turn off other debugging logs.)

use captains_log::*;
// the recipe already register signal and dynamic=true, do not use test(),
// because test() will clear the signal.
recipe::ring_file("/tmp/ring.log", 512*1024*1024, Level::Info,
    signal_consts::SIGHUP).build().expect("log setup");

§Debugging deadlocks

Then add some high-level log to critical path in the code, try to reproduce the problem, and reduce the amount of log if the bug not occur.

On start-up, it will create a limited-size ring-buffer-like memory. The log content will be held within memory but not written to disk, old logs will be overwritten by new ones. Until specified signal arrives, the last part of log message will be dumped to the file, in time order.

Once your program hangs up completely, find your process PID and send a signal to it.

kill -SIGHUP <pid>

There will be messages printed to stdout:

RingFile: start dumping
RingFile: dump complete

Then you can inspect your log content on disk (for this example /tmp/ring.log).

A real-life debugging story can be found on https://github.com/frostyplanet/crossfire-rs/issues/24.

§Debugging assertions

When you debugging the reason of some unexpected assertions, it will automatically trigger the dump in our panic hook. If you want an explicit dump, you can call:

   log::logger().flush();

§NOTE

The backend is provided by RingFile crate. To ensure low latency, the buffer is protected by a spinlock instead of a mutex. After the program hangs, because no more messages will be written to the buffer, log content can be safely copied from the buffer area to disk.

Be aware that it did not use mlock to prevent memory from being swapping. (Swapping might make the code slow to prevent bug reproduction). When your memory is not enough, use a smaller buf_size and turn off the swap with swapoff -a.

Fields§

§file_path: Box<Path>§level: Level§format: LogFormat§buf_size: i32

0 < buf_size < i32::MAX

Implementations§

Source§

impl LogRingFile

Source

pub fn new<P: Into<PathBuf>>( file_path: P, buf_size: i32, max_level: Level, format: LogFormat, ) -> Self

Trait Implementations§

Source§

impl Hash for LogRingFile

Source§

fn hash<__H: Hasher>(&self, state: &mut __H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl SinkConfigTrait for LogRingFile

Source§

fn get_level(&self) -> Level

get max log level of the sink
Source§

fn get_file_path(&self) -> Option<Box<Path>>

Only file sink has path
Source§

fn write_hash(&self, hasher: &mut Box<dyn Hasher>)

Calculate hash for config comparison

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> Pointable for T

Source§

const ALIGN: usize

The alignment of pointer.
Source§

type Init = T

The type for initializers.
Source§

unsafe fn init(init: <T as Pointable>::Init) -> usize

Initializes a with the given initializer. Read more
Source§

unsafe fn deref<'a>(ptr: usize) -> &'a T

Dereferences the given pointer. Read more
Source§

unsafe fn deref_mut<'a>(ptr: usize) -> &'a mut T

Mutably dereferences the given pointer. Read more
Source§

unsafe fn drop(ptr: usize)

Drops the object pointed to by the given pointer. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

Source§

fn vzip(self) -> V