1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
// Copyright Ⓒ 2019 David Kellum
//
// These _-v_ macros were co-developed with
// https://github.com/rust-lang-nursery/log/pull/316 (by the same author)
//
// All original _log_ source is offered under the same Apache 2.0 or MIT
// licenses, and is:
// Copyright Ⓒ 2015 The Rust Project Developers

/// Log a message at the error level, flush the logger, and then use the same
/// message to panic.
///
/// This will duplicate the message, once via the registered logger, then
/// again via stderr for the panic (default handler). Since this is a fatal
/// and presumably serious condition, potential duplication is of less concern
/// than the risk of missing the message. This will always `panic!`, even if
/// no logger is configured, or if error level messages aren't logged.
///
/// # Example
///
/// ```rust,should_panic
/// # use std::time::{Duration, Instant};
/// use tao_log::fatal;
///
/// # let td = Duration::new(0, 100_000_000);
/// fatal!("shields compromised, core breach in {:?}!", td);
/// // ^1 -- error level message: shields compromised, core breach in 100ms!
/// // ^2 -- panic:               shields compromised, core breach in 100ms!
/// ```
#[macro_export]
macro_rules! fatal {
    (target: $target:expr, $($arg:tt)+) => (
        $crate::__tao_fatal!($target, $($arg)+)
    );
    ($($arg:tt)+) => (
        $crate::__tao_fatal!(module_path!(), $($arg)+)
    );
}

/// Log an expression and its value at any specified level.
///
/// Logs with the optional or default (module path of use) target, specified
/// `Level`, optional prefix, and optional or default (`"{:?}"`) value format
/// string, and a single expression. The expression argument is evaluated
/// exactly once, regardless of if the logging level is enabled, and its
/// value is returned from the macro. This is normally only used through the
/// _-v_ macros like `debugv!` or `tracev!`.
///
/// Note that the value is moved and then returned. If the type does not
/// implement `Copy`, ownership may be retained by borrowing by reference
/// e.g. `debugv!(&expr)`.
///
/// # Examples
///
/// ```rust
/// use tao_log::*;
///
/// #[derive(Debug)]
/// struct Point { x: f32, y: f32 }
///
/// fn circle(center: &Point, radius: f32) { /*...*/ }
///
/// # fn main() {
/// let center = Point { x: 3.234, y: -1.223 };
///
/// circle(logv!(log::Level::Trace, &center), 7.3);
/// //     ^-- trace level message: "&center → Point { x: 3.234, y: -1.223 }"
/// circle(tracev!(&center), 8.0);
/// //     ^-- trace level message: "&center → Point { x: 3.234, y: -1.223 }"
/// # }
/// ```
#[macro_export]
macro_rules! logv {
    (target: $target:expr, $lvl:expr, $($arg:tt)+) => (
        $crate::__tao_logv!($lvl, target: $target, $($arg)+)
    );
    ($lvl:expr, $($arg:tt)+) => (
        $crate::__tao_logv!($lvl, target: module_path!(), $($arg)+)
    );
}

/// Log an expression at the error level, returning its value.
#[macro_export]
macro_rules! errorv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Error, $($arg)+))
}

/// Log an expression at the warn level, returning its value.
#[macro_export]
macro_rules! warnv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Warn, $($arg)+))
}

/// Log an expression at the info level, returning its value.
#[macro_export]
macro_rules! infov {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Info, $($arg)+))
}

/// Log an expression at the debug level, returning its value.
#[macro_export]
macro_rules! debugv {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Debug, $($arg)+))
}

/// Log an expression at the trace level, returning its value.
#[macro_export]
macro_rules! tracev {
    ($($arg:tt)+) => ($crate::__tao_logv!($crate::log::Level::Trace, $($arg)+))
}

// Helper macro for `fatal!`
#[doc(hidden)]
#[macro_export]
macro_rules! __tao_fatal {
    ($target:expr, $($arg:tt)+) => (
        match format_args!($($arg)+) {
            args => {
                $crate::error!(target: $target, "{}", args);
                $crate::log::logger().flush();
                panic!("{}", args);
            }
        }
    );
}

// Helper macro for the -v macros, handling the permutations of optional
// parameters. Note: The required level parameter is first here for
// convenience of internal use with variable-args.
#[doc(hidden)]
#[macro_export]
macro_rules! __tao_logv {
    ($lvl:expr, target: $tgt:expr, $pre:expr, $vfmt:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!($tgt, $lvl, concat!($pre, " {} → ", $vfmt), $exp)
    );
    ($lvl:expr, target: $tgt:expr, $pre:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!($tgt, $lvl, concat!($pre, " {} → {:?}"), $exp)
    );
    ($lvl:expr, target: $tgt:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!($tgt, $lvl, "{} → {:?}", $exp)
    );
    ($lvl:expr, $pre:expr, $vfmt:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, concat!($pre, " {} → ", $vfmt), $exp)
    );
    ($lvl:expr, $pre:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, concat!($pre, " {} → {:?}"), $exp)
    );
    ($lvl:expr, $exp:expr $(,)?) => (
        $crate::__tao_v_eval!(module_path!(), $lvl, "{} → {:?}", $exp)
    );
}

// Inner helper macro for __tao_logv. Evaluates expression exactly once, moves
// value and returns it.
#[doc(hidden)]
#[macro_export]
macro_rules! __tao_v_eval {
    ($tgt:expr, $lvl:expr, $fmt:expr, $exp:expr) => (
        match $exp {
            vt => {
                $crate::log!(target: $tgt, $lvl, $fmt, stringify!($exp), &vt);
                vt
            }
        }
    )
}