玉琳 發表於 2024-4-2 08:49:20

使用Rust实现日志记录功能

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>log 日志库标准</li><ul class="second_class_ul"><li>简单示例</li><li>使用方法</li></ul><li>使用 log4rs</li><ul class="second_class_ul"><li>添加依赖</li><li>配置文件</li><li>运行项目</li></ul></ul></div><p class="maodian"></p><h2>log 日志库标准</h2>
<p>log&nbsp;是 Rust 的日志门面库,由官方积极维护可以放心使用。它是Rust的日志门面,相应的日志 API 已成为事实上的标准被其它日志框架所使用,有了日志门面开发者可以很方便切换自己的日志框架。</p>
<p class="maodian"></p><h3>简单示例</h3>
<p>创建一个名为 log_test 二进制项目:</p>
<div class="jb51code"><pre class="brush:ps;">cargo new log_test
</pre></div>
<p>执行以下命令,引入 log 依赖:</p>
<div class="jb51code"><pre class="brush:ps;">cargo add log
</pre></div>
<p>修改 main.rs 的代码如下:</p>
<div class="jb51code"><pre class="brush:plain;">use log::{info, warn,error,trace};

fn main() {
    // 记录日志
    info!("This is an info message");
    warn!("This is a warning message");
    error!("This is an error message");
    trace!("This is an trace message");
}</pre></div>
<p>运行上面的示例,实际上看不到任何输出。因为&nbsp;<strong>log 仅仅是日志门面库,它并不具备完整的日志库功能</strong>!</p>
<p class="maodian"></p><h3>使用方法</h3>
<p>因为 log 仅仅是日志门面库,对于库和应用的开发者来说使用方法是有区别的,这也是 log 包这么设计的优势所在。</p>
<p><strong>库的开发者</strong></p>
<p>作为库的开发者,你只要在库中使用门面库即可,将具体的日志库交给用户去选择和绑定:</p>
<div class="jb51code"><pre class="brush:plain;">use log::{info, trace, warn};
pub fn deal_with_something() {
    // 开始处理

    // 记录一些日志
    trace!("a trace log");
    info!("a info long: {}", "abc");
    warn!("a warning log: {}, retrying", err);

    // 结束处理
}
</pre></div>
<p>应用开发者</p>
<p>如果是应用开发者,就需要去选择一个具体的日志库了。</p>
<p>目前已经有了不少日志库实现,官方在&nbsp;github&nbsp;上也推荐了一些 ,主要分为以下几类:</p>
<ul><li>简单的最小记录器,如 env_logger 等</li><li>复杂的可配置框架,如 log4rs 等</li><li>其他设施的适配器,如 syslog、db_logger 等</li><li>对于 WebAssembly 二进制文件:<strong>console_log</strong></li><li>对于动态库:需要在日志上构造一个 FFI 安全包装器,以便在库中进行初始化。</li><li>实用程序,如 alterable_logger 等</li></ul>
<p>log 还提供了&nbsp;<strong>set_logger</strong>&nbsp;函数用于设置日志库,<strong>set_max_level</strong>&nbsp;用于设置最大日志级别。但是选用的具体日志库往往会提供更高级的 API,无需手动调用这两个函数。</p>
<p><strong>日志库开发者</strong></p>
<p>对于日志库开发者而言,自然要实现自己的 Log 特征:</p>
<div class="jb51code"><pre class="brush:plain;">use log::{Record, Level, Metadata};
struct SimpleLogger;
impl log::Log for SimpleLogger {
    fn enabled(&amp;self, metadata: &amp;Metadata) -&gt; bool {
      metadata.level() &lt;= Level::Info
    }
    fn log(&amp;self, record: &amp;Record) {
      if self.enabled(record.metadata()) {
            println!("{} - {}", record.level(), record.args());
      }
    }
    fn flush(&amp;self) {}
}
</pre></div>
<p>除此之外,还需要包装下 set_logger 和 set_max_level:</p>
<div class="jb51code"><pre class="brush:plain;">use log::{SetLoggerError, LevelFilter};
static LOGGER: SimpleLogger = SimpleLogger;
pub fn init() -&gt; Result&lt;(), SetLoggerError&gt; {
    log::set_logger(&amp;LOGGER)
      .map(|()| log::set_max_level(LevelFilter::Info))
}
</pre></div>
<p>然后再main函数里面设置全局记录器:</p>
<div class="jb51code"><pre class="brush:plain;">use log::{info, warn,error,trace};

fn main() {
    //设置日志
    init();
    // 记录日志
    info!("This is an info message");
    warn!("This is a warning message");
    error!("This is an error message");
    trace!("This is an trace message");
}
</pre></div>
<p>运行后终端输出如下,因为设置日志等级为Info,所以没有输出Trace等级日志:</p>
<blockquote><p>INFO - This is an info message<br />WARN - This is a warning message<br />ERROR - This is an error message</p></blockquote>
<p class="maodian"></p><h2>使用 log4rs</h2>
<p>log4rs&nbsp;是一个高度可配置的日志框架,以 Java 的 Logback 和 log4j 库为模型。</p>
<p class="maodian"></p><h3>添加依赖</h3>
<p>为项目添加&nbsp;<strong>log4rs</strong>&nbsp;依赖:</p>
<div class="jb51code"><pre class="brush:ps;">cargo add log4rs
</pre></div>
<p class="maodian"></p><h3>配置文件</h3>
<p>在项目根目录下,创建一个&nbsp;<strong>log4rs.yaml</strong>&nbsp;配置文件,并添加以下内容:</p>
<div class="jb51code"><pre class="brush:yaml;">refresh_rate: 30 seconds

appenders:
stdout:
    kind: console
    encoder:
      pattern: "{d(%Y-%m-%d %H:%M:%S.%f)} [{l}] {t} - {m}{n}"

rolling_file:
    kind: rolling_file
    path: logs/test.log
    append: true
    encoder:
      pattern: "{d(%Y-%m-%d %H:%M:%S.%f)} [{l}] {t} - {m}{n}"
    policy:
      kind: compound
      trigger:
      kind: size
      limit: 10 mb
      roller:      
      kind: fixed_window
      pattern: logs/test.{}.log
      base: 1
      count: 5
      
root:
level: info
appenders:
    - stdout
    - rolling_file
</pre></div>
<p>上面配置文件设定<strong>日志输出到控制台、文件,文件按10 mb大小滚动,只保留最近五个文件</strong>。各个配置字段的具体含义可以参考配置:</p>
<ul><li><strong>refresh_rate</strong>:用于确定 log4rs 扫描配置文件以查找更改的频率,如果发现更改,记录器将自动重新配置</li><li><strong>appender</strong>: 负责将日志收集到文件、控制台或系统日志, 可配置多个</li><li><strong>stdout、rolling_file</strong>:追加器的唯一标识字符串,自己随便定义,它的 kind 字段只支持console、file、rolling_file&nbsp;三种实现</li><li><strong>encoder</strong>: 负责将 log 信息转换为合适的格式, 如固定格式的平文本或<strong>json</strong></li><li><strong>pattern</strong>:编码模板,格式可配置,具体格式详见pattern</li><li><strong>policy</strong>:策略字段,策略必须具有 kind 字段,<strong>默认(且仅受支持)策略为 kind: compound</strong></li><li><strong>trigger</strong>:触发器字段用于指示何时滚动日志文件,支持&nbsp;<strong>size</strong>&nbsp;和&nbsp;<strong>time</strong>&nbsp;两种类型,这里使用的是按大小</li></ul>
<p class="maodian"></p><h3>运行项目</h3>
<p>修改main.rs内容如下:</p>
<div class="jb51code"><pre class="brush:plain;">use log::*;
use log4rs;

fn main() {
    log4rs::init_file("log4rs.yaml", Default::default()).unwrap();

    for i in 1..=1000 {
      info!("This is loop iteration {}", i);
    }
}
</pre></div>
<p>运行结果:</p>
<blockquote><p>2024-04-01 15:43:28.596832500 hello_world - This is loop iteration 1</p></blockquote>
<p>到此这篇关于使用Rust实现日志记录功能的文章就介绍到这了,更多相关Rust日志记录内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>Rust使用lettre实现邮件发送功能</li><li>Rust&nbsp;文档注释功能示例代码</li><li>使用Rust采集天气预报信息并实现实时更新数据功能</li><li>Rust&nbsp;连接&nbsp;SQLite&nbsp;数据库的过程解析</li><li>Rust 中的文件操作示例详解</li><li>Rust常用功能实例代码汇总</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: 使用Rust实现日志记录功能