Skip to content

fast/logcall

Repository files navigation

Logcall

Crates.io Downloads Documentation CI Status License

Logcall provides a #[logcall] attribute that logs function inputs and return values through the log facade. It keeps boilerplate low while making debugging and observability easy.

This is a reimplementation of log-derive with async functions, async-trait, Result, and Option support.

Installation

Logcall emits through log, so applications also need a logger. This example uses logforth:

[dependencies]
log = "0.4"
logcall = "0.2.0"
logforth = { version = "0.30", features = ["starter-log"] }

Quick Start

Annotate functions with #[logcall] and configure logging with logforth:

use logcall::logcall;
use logforth::record::LevelFilter;

/// Logs the function call at the default `debug` level.
#[logcall]
fn add(a: i32, b: i32) -> i32 {
    a + b
}

/// Logs the function call at the `info` level.
#[logcall("info")]
fn multiply(a: i32, b: i32) -> i32 {
    a * b
}

/// Logs `Ok` results at the `info` level and `Err` results at the `error` level.
#[logcall(ok = "info", err = "error")]
fn divide(a: i32, b: i32) -> Result<i32, String> {
    if b == 0 {
        Err("Division by zero".to_string())
    } else {
        Ok(a / b)
    }
}

/// Logs errors at the `error` level. No log output for `Ok` variant.
#[logcall(err = "error")]
fn divide2(a: usize, b: usize) -> Result<usize, String> {
    a.checked_div(b).ok_or("divide by zero".into())
}

/// Logs `Some` values at the `info` level and `None` values at the `warn` level.
#[logcall(some = "info", none = "warn")]
fn find_even(value: i32) -> Option<i32> {
    (value % 2 == 0).then_some(value)
}

/// Logs the function call with custom input logging format.
#[logcall(input = "a = {a:?}, ..")]
fn subtract(a: i32, b: i32) -> i32 {
    a - b
}

/// Logs the function call with custom output logging format.
#[logcall(output = ": {:?}")]
fn negate(a: i32) -> i32 {
    -a
}

/// Omits the return value from the log output.
#[logcall(output = "")]
fn ping(a: i32) -> i32 {
    a
}

fn main() {
    logforth::starter_log::stdout()
        .filter(LevelFilter::All)
        .apply();

    add(2, 3);
    multiply(2, 3);
    divide(2, 0).ok();
    divide2(2, 0).ok();
    find_even(4);
    find_even(3);
    subtract(3, 2);
    negate(5);
    ping(42);
}

Example Run

cargo run --example main

Sample output:

2026-06-12T18:18:14.935453+08:00  DEBUG main: main.rs:5 main::add(a = 2, b = 3) => 5
2026-06-12T18:18:14.935505+08:00   INFO main: main.rs:11 main::multiply(a = 2, b = 3) => 6
2026-06-12T18:18:14.935514+08:00  ERROR main: main.rs:17 main::divide(a = 2, b = 0) => Err("Division by zero")
2026-06-12T18:18:14.935520+08:00  ERROR main: main.rs:27 main::divide2(a = 2, b = 0) => Err("divide by zero")
2026-06-12T18:18:14.935525+08:00   INFO main: main.rs:33 main::find_even(value = 4) => Some(4)
2026-06-12T18:18:14.935529+08:00   WARN main: main.rs:33 main::find_even(value = 3) => None
2026-06-12T18:18:14.935533+08:00  DEBUG main: main.rs:39 main::subtract(a = 3, ..) => 1
2026-06-12T18:18:14.935537+08:00  DEBUG main: main.rs:45 main::negate(a = 5): -5
2026-06-12T18:18:14.935542+08:00  DEBUG main: main.rs:51 main::ping(a = 42)

Attribute Arguments

Generated input and output formatting uses Debug by default. Supported log levels are error, warn, info, debug, and trace.

  • #[logcall] logs every call at the debug level.
  • #[logcall("info")] logs every call at the selected level.
  • #[logcall(ok = "info", err = "error")] logs Result variants independently. Omit ok or err to skip that variant.
  • #[logcall(some = "info", none = "warn")] logs Option variants independently. Omit some or none to skip that variant.
  • #[logcall(input = "...")] replaces the argument portion of the message. The format string can reference arguments by name.
  • #[logcall(output = "...")] replaces the return value portion of the message. Use output = "" to log only the call.

The macro supports sync functions, async functions, and async functions generated by async-trait.

Minimum Supported Rust Version (MSRV)

This crate's minimum supported rustc version is 1.91.0.

The minimum Rust version can increase in minor releases. Patch releases keep the same minimum Rust version.

Contributing

Contributions are welcome! Please submit pull requests or open issues to improve the crate.

License

This project is licensed under the MIT License. See the LICENSE file for details.

About

An attribute macro that logs the function return value

Resources

License

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages