[][src]Crate logging_timer

Provides a couple of simple timers that output messages indicating the elapsed time via the log crate when they are dropped.

Timers have names, and the log messages are constructed in such a way that they contain the module, filename and line number of the place where the timer was constructed.

Timers are usually created using the timer! or stimer! macros. The difference is that timer! returns a timer that logs a message only when it is dropped, while stimer! returns a timer that logs a started message as soon as it is created, and a finished message when it is dropped.

Example - "Find Files" is the name of the timer:

use logging_timer::{timer};

fn find_files(dir: PathBuf) -> List<PathBuf> {
    let _tmr = timer!("Find Files");
    let files = vec![];

    // expensive operation here

    return files;
} // _tmr is dropped here and a 'TimerFinished' message is logged

You can replace timer! with stimer! to get a timer that logs a starting message as well, giving you a pair of 'bracketing' log messages.

In addition, both timer macros accept format_args! style parameters, allowing you to include extra information in the log messages.

let tmr = timer!("Find Files", "Directory = {}", dir);

Outputting Intermediate Messages

The executing! macro allows you to make the timer produce a message before it is dropped. You can call it as many times as you want. A pseudocode example:

use logging_timer::{timer, executing};

fn find_files(dir: PathBuf) -> List<PathBuf> {
    let tmr = timer!("Find Files");
    let files = vec![];

    for dir in sub_dirs(dir) {
        // expensive operation
        executing!(tmr, "Processed {}", dir);
    }

    return files;
} // tmr is dropped here and a 'TimerFinished' message is logged

Controlling the Final Message

Finally, the finish! macro also makes the timer log a message, but it also has the side effect of suppressing the normal drop message. finish! is useful when you want the final message to include some information that you did not have access to until the calculation had finished.

use logging_timer::{timer, executing, finish};

fn find_files(dir: PathBuf) -> List<PathBuf> {
    let tmr = timer!("Find Files");
    let files = vec![];

    finish!(tmr, "Found {} files", files.len());
    return files;
} // tmr is dropped here but no message is produced.

Example of Timer Output

The overall format will depend on how you customize the output format of the log crate, but as an illustrative example:

2019-05-30T21:41:41.847982550Z DEBUG [TimerStarting] [dnscan/src/main.rs/63] Directory Analysis
2019-05-30T21:41:41.868690703Z INFO [dnlib::configuration] [dnlib/src/configuration.rs/116] Loaded configuration from "/home/phil/.dnscan/.dnscan.json"
2019-05-30T21:41:41.897609281Z DEBUG [TimerFinished] [dnlib/src/io.rs/67] Elapsed=28.835275ms, Find Files, Dir="/home/phil/mydotnetprojects", NumSolutions=1 NumCsproj=45, NumOtherFiles=12
2019-05-30T21:41:41.955140835Z DEBUG [TimerFinished] [dnlib/src/analysis.rs/93] Elapsed=57.451736ms, Load And Analyze Solution files
2019-05-30T21:41:42.136762196Z DEBUG [TimerFinished] [dnlib/src/analysis.rs/108] Elapsed=181.563223ms, Load And Analyze Project files, Found 43 linked projects and 2 orphaned projects
2019-05-30T21:41:42.136998556Z DEBUG [TimerStarting] [dnscan/src/main.rs/87] Calculate project graphs and redundant projects
2019-05-30T21:41:42.143072972Z DEBUG [TimerExecuting] [dnscan/src/main.rs/87] Elapsed=6.075205ms, Calculate project graphs and redundant projects, Individual graphs done
2019-05-30T21:41:42.149218039Z DEBUG [TimerFinished] [dnscan/src/main.rs/87] Elapsed=12.219438ms, Calculate project graphs and redundant projects, Found 19 redundant project relationships
2019-05-30T21:41:42.165724712Z DEBUG [TimerFinished] [dnscan/src/main.rs/108] Elapsed=16.459312ms, Write output files
2019-05-30T21:41:42.166445Z INFO [TimerFinished] [dnscan/src/main.rs/63] Elapsed=318.48581ms, Directory Analysis

Here the [Timer*] blocks are the target field from log's Record struct and [dnscan/src/main.rs/63] is the filename and number from Record - this captures the place where the timer was instantiated. The module is also set, but is not shown in these examples. Note how the timer named 'Directory Analysis' is the only one to log both a starting and ending message.

By default messages are output at DEBUG level, you can control this using the level() builder method:

let _tmr = timer!("Directory Analysis").level(Level::Info);

(There is a bug, this does not work for stimer! yet, only timer!)

Macros

executing

Makes an existing timer output an 'executing' mesasge. Can be called multiple times.

finish

Makes an existing timer output a 'finished' mesasge and suppresses the normal drop message. Only the first call has any effect, subsequent calls will be ignored.

stimer

Creates a timer that logs a starting mesage and a finished message.

timer

Creates a timer that does not log a starting message, only a finished one.

Structs

LoggingTimer

When this struct is dropped, it logs a message stating its name and how long the execution time was. Can be used to time functions or other critical areas.