Rust过程宏库sc-tracing-proc-macro的使用,基于proc-macro2的高效日志追踪与代码注入工具
Rust过程宏库sc-tracing-proc-macro的使用,基于proc-macro2的高效日志追踪与代码注入工具
安装
在项目目录中运行以下Cargo命令:
cargo add sc-tracing-proc-macro
或者在Cargo.toml中添加以下行:
sc-tracing-proc-macro = "11.1.0"
基本使用示例
sc-tracing-proc-macro是一个基于proc-macro2的高效日志追踪与代码注入工具,主要用于Substrate区块链开发框架中。以下是基本使用示例:
// 引入必要的依赖
use sc_tracing_proc_macro::instrument;
#[instrument(name = "example", skip_all)] // 使用instrument宏自动添加日志追踪
fn example_function(param: u32) -> u32 {
// 函数体将自动被日志跟踪代码包裹
param * 2
}
fn main() {
let result = example_function(5);
println!("Result: {}", result);
}
完整示例Demo
下面是一个更完整的示例,展示了sc-tracing_proc_macro的主要功能:
// 在Cargo.toml中确保有以下依赖:
// [dependencies]
// sc-tracing-proc-macro = "11.1.0"
// tracing = "0.1"
use sc_tracing_proc_macro::instrument;
use tracing::{info, Level};
use tracing_subscriber::FmtSubscriber;
// 使用instrument宏的完整示例
#[instrument(
name = "complex_calculation", // 自定义span名称
level = Level::DEBUG, // 设置日志级别
target = "my_target", // 自定义目标
skip(param2), // 跳过某些参数的日志记录
fields(param1, param3 = %param3) // 自定义字段记录方式
)]
fn complex_calculation(param1: u32, param2: String, param3: f64) -> f64 {
info!("Starting complex calculation");
let intermediate = param1 as f64 * param3;
info!(intermediate, "Intermediate result");
intermediate / 2.0
}
fn main() {
// 初始化tracing订阅器
let subscriber = FmtSubscriber::builder()
.with_max_level(Level::TRACE)
.finish();
tracing::subscriber::set_global_default(subscriber)
.expect("setting default subscriber failed");
// 调用被instrument宏修饰的函数
let result = complex_calculation(10, "secret".to_string(), 3.14);
println!("Final result: {}", result);
}
主要功能
- 自动日志追踪:通过
#[instrument]
宏自动为函数添加日志追踪能力 - 灵活配置:可以自定义日志级别、span名称、目标等参数
- 字段控制:可以选择跳过某些参数的日志记录或自定义字段的显示方式
- 高性能:基于proc-macro2实现,编译时展开,运行时开销极小
这个库特别适合需要精细日志追踪的Substrate区块链开发项目,能够帮助开发者轻松实现函数级别的调用追踪和性能监控。
1 回复
Rust过程宏库sc-tracing-proc-macro使用指南
概述
sc-tracing-proc-macro是一个基于proc-macro2的高效日志追踪与代码注入工具,专为Rust设计。它提供了过程宏来简化日志记录和代码注入操作,特别适合需要细粒度追踪和调试的复杂应用场景。
主要特性
- 高效的过程宏实现
- 灵活的日志追踪功能
- 代码注入能力
- 与标准日志框架兼容
- 低运行时开销
安装
在Cargo.toml中添加依赖:
[dependencies]
sc-tracing-proc-macro = "0.1"
使用示例
基本日志追踪
use sc_tracing_proc_macro::trace;
#[trace]
fn calculate_sum(a: i32, b: i32) -> i32 {
a + b
}
fn main() {
let result = calculate_sum(5, 7);
println!("Result: {}", result);
}
执行时会自动记录函数调用和返回值。
自定义日志级别
use sc_tracing_proc_macro::{trace, Level};
#[trace(level = Level::Debug)]
fn complex_operation(input: String) -> usize {
input.len()
}
代码注入
use sc_tracing_proc_macro::inject;
#[inject(
pre = "println!(\"Before execution, input: {}\", input);",
post = "println!(\"After execution, result: {}\", result);"
)]
fn process_data(input: String) -> String {
input.to_uppercase()
}
方法追踪
use sc_tracing_proc_macro::trace;
struct Calculator;
impl Calculator {
#[trace]
fn multiply(&self, x: i32, y: i32) -> i32 {
x * y
}
}
高级用法
条件追踪
use sc_tracing_proc_macro::trace;
#[trace(condition = "cfg!(debug_assertions)")]
fn sensitive_operation(data: Vec<u8>) {
// 仅在debug模式下记录日志
}
自定义日志格式
use sc_tracing_proc_macro::trace;
#[trace(format = "Function {fn_name} called with args: {args:?}")]
fn example(a: i32, b: &str) {
// 函数体
}
完整示例代码
// 导入必要的宏
use sc_tracing_proc_macro::{trace, inject, Level};
// 基本日志追踪示例
#[trace]
fn add(a: i32, b: i32) -> i32 {
a + b
}
// 自定义日志级别
#[trace(level = Level::Warn)]
fn divide(a: i32, b: i32) -> i32 {
a / b
}
// 代码注入示例
#[inject(
pre = "println!(\"准备处理数据: {}\", data);",
post = "println!(\"数据处理完成,结果长度: {}\", result.len());"
)]
fn process_string(data: String) -> String {
data.trim().to_string()
}
// 结构体方法追踪
struct MathOps;
impl MathOps {
#[trace]
fn factorial(&self, n: u32) -> u32 {
if n <= 1 { 1 } else { n * self.factorial(n-1) }
}
}
// 条件追踪
#[trace(condition = "cfg!(feature = \"debug\")")]
fn sensitive_function() {
println!("执行敏感操作");
}
// 自定义日志格式
#[trace(format = "调用函数 {fn_name},参数1: {a}, 参数2: {b}")]
fn custom_format(a: i32, b: &str) -> String {
format!("{}-{}", a, b)
}
fn main() {
// 基本日志追踪
println!("5 + 3 = {}", add(5, 3));
// 除法运算会输出警告级别日志
println!("10 / 2 = {}", divide(10, 2));
// 代码注入测试
let processed = process_string(" hello world ".to_string());
println!("处理后的字符串: '{}'", processed);
// 方法追踪
let math = MathOps;
println!("5的阶乘: {}", math.factorial(5));
// 条件追踪
sensitive_function();
// 自定义格式
println!("自定义格式结果: {}", custom_format(42, "answer"));
}
性能建议
- 在生产环境中使用条件编译限制追踪范围
- 对性能关键路径谨慎使用
- 考虑使用更高级别的日志级别减少输出
注意事项
- 过程宏会影响编译时间
- 大量使用可能导致日志输出过多
- 确保注入的代码是安全的,不会引入漏洞
这个库特别适合需要详细调试信息但又不想手动添加大量日志语句的项目,能显著提高开发效率和运行时诊断能力。