各种语言的宏技巧 日志追踪

Develon / 2023-06-04 / 原文

C / C++

日志追踪

编译器内置 FILE_NAMELINEfuncFUNCTION 等宏,可追踪打印日志的代码。

#include <android/log.h>
#define R(x) #x
#define STR(x) R(x)
#define LOG(...) __android_log_print(ANDROID_LOG_DEBUG, __FILE_NAME__ ":" STR(__LINE__), ##__VA_ARGS__)
#define TLOG(tag, fmt, ...) __android_log_print(ANDROID_LOG_DEBUG, __FILE_NAME__ ":" STR(__LINE__), "%s -> " fmt, tag, ##__VA_ARGS__)
#define FLOG(fmt, ...) TLOG(__func__, fmt, ##__VA_ARGS__)


LOG("The value of 1 + 1 is %d", 1+1);
输出:

2023-05-27 19:03:22.609 12721-12721/app.xxx D/native-lib.cpp:27: The value of 1 + 1 is 2

Rust

日志追踪

Rust 有内置的 file!(), line!() 宏,可以追踪日志。目前没有函数名追踪的方法。

#[macro_export]
macro_rules! log {
    ($type: expr, $($arg: tt)+) => {{
        let level: log::Level = $type;
        let str = format!($($arg)+);
        match level {
            log::Level::ERROR => {
                eprintln!("{}:{} -> {}\0", file!(), line!(), str);
            },
            _ => {
                println!("{}:{} -> {}\0", file!(), line!(), str);
            },
        }
    }}
}

Kotlin

日志追踪

通过栈进行追踪。

package lib.log

val log = Logger()

class Logger(private val name: String = "Logger") {
	fun d(vararg _msg: Any?) {
        val msg = _msg.joinToString(separator = " ") {
			it ?.toString() ?: "[null]"
		}

		val trace: Array<StackTraceElement>?  = Thread.currentThread().stackTrace

		if (trace == null || trace.size < 3) return println("Logger@$name $msg")

		val caller = trace[2]

		with (caller) {
			val output = "Logger@$name ~ $fileName($lineNumber) ~ $className # $methodName() ${ Thread.currentThread().name }: $msg"
			println(output)
		}
	}
}