<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>日志库 on AIDB</title>
    <link>https://aidb.pages.dev/tags/%E6%97%A5%E5%BF%97%E5%BA%93/</link>
    <description>Recent content in 日志库 on AIDB</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>zh-CN</language>
    <managingEditor>s_lisheng@163.com (AIDB)</managingEditor>
    <webMaster>s_lisheng@163.com (AIDB)</webMaster>
    <copyright>© 2026 AIDB</copyright>
    <lastBuildDate>Mon, 22 Jun 2026 19:38:13 +0800</lastBuildDate><atom:link href="https://aidb.pages.dev/tags/%E6%97%A5%E5%BF%97%E5%BA%93/index.xml" rel="self" type="application/rss+xml" />
    
    <item>
      <title>日志库的设计思路</title>
      <link>https://aidb.pages.dev/posts/posts/full-stack/%E6%97%A5%E5%BF%97%E5%BA%93%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/</link>
      <pubDate>Mon, 22 Jun 2026 19:38:13 +0800</pubDate>
      <author>s_lisheng@163.com (AIDB)</author>
      <guid>https://aidb.pages.dev/posts/posts/full-stack/%E6%97%A5%E5%BF%97%E5%BA%93%E7%9A%84%E8%AE%BE%E8%AE%A1%E6%80%9D%E8%B7%AF/</guid>
      <description>&lt;h3 class=&#34;relative group&#34;&gt;一、基本思路&#xA;    &lt;div id=&#34;一基本思路&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#%e4%b8%80%e5%9f%ba%e6%9c%ac%e6%80%9d%e8%b7%af&#34; aria-label=&#34;锚点&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h3&gt;&#xA;&lt;p&gt;日志库的设计，抓住最核心的一条，就是日志从产生到到达最终目的地期间的处理流程。&#xA;一般而言，为了设计一个灵活可扩展，可配置的日志库，可将日志库抽象为4个部分：记录器、过滤器、格式化器、输出器四部分。&lt;/p&gt;&#xA;&lt;table&gt;&#xA;&#x9;&lt;thead&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;组成&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;th&gt;描述&lt;/th&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/thead&gt;&#xA;&#x9;&lt;tbody&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;记录器&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;负责产生日志记录的原始信息，比如（原始信息，日志等级，时间，记录的位置）等信息&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;过滤器&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;负责按指定的过滤条件过滤掉我们不需要的日志（比如按日志等级过滤）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;格式化器&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;负责对原始日志信息按照我们想要的格式去格式化&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&#x9;&#x9;&lt;tr&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;输出器&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&#x9;&#x9;&lt;td&gt;负责将将要进行记录的日志（一般经过过滤器及格式化器的处理后）记录到日志目的地（例如：输出到文件中）&lt;/td&gt;&#xA;&#x9;&#x9;&#x9;&lt;/tr&gt;&#xA;&#x9;&lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;通过将日志库分为4个抽象，使之成了一个较为灵活可扩展的日志库。比如你想实现输出到文件和输出到TCP中这两个功能，你只需分别实现这两个输出器的实例即可。&lt;/p&gt;&#xA;&lt;p&gt;实现了上面的抽象就基本实现日志库的核心功能。在具体实现上，需要设计一个&lt;code&gt;Logger&lt;/code&gt;，将上面的抽象组合起来。另外还有一些其他的工作需要完善，比如读取日志配置文件，根据配置文件中的配置条件去构建相应的代码等等其他工作。&lt;/p&gt;&#xA;&#xA;&lt;h3 class=&#34;relative group&#34;&gt;二、一条日志的生命周期&#xA;    &lt;div id=&#34;二一条日志的生命周期&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#%e4%ba%8c%e4%b8%80%e6%9d%a1%e6%97%a5%e5%bf%97%e7%9a%84%e7%94%9f%e5%91%bd%e5%91%a8%e6%9c%9f&#34; aria-label=&#34;锚点&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h3&gt;&#xA;&lt;p&gt;可能到目前对日志库是怎么工作的还有些模糊，下面以一条日志的生命周期为例来说明日志库是怎么工作的：&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;产生。&lt;code&gt;info!(&amp;quot;log information.&amp;quot;);&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;经过记录器。记录器去获取日志发生的时间，位置，线程信息等等信息，会有一个数据结构去存储你需要的信息（例如：&lt;code&gt;msg:&amp;quot;log information.&amp;quot;,time:2018-3-20 10:00:00,level:info,location:main.rs:3 lines&lt;/code&gt;）&lt;/li&gt;&#xA;&lt;li&gt;经过过滤器。决定是否记录（例如，过滤条件设为&lt;code&gt;info&lt;/code&gt;级以下的过滤掉，这里条日志信息等级是&lt;code&gt;info&lt;/code&gt;，满足条件，继续。）&lt;/li&gt;&#xA;&lt;li&gt;经过格式化器。假设我们想输出为&lt;code&gt;2018-3-22 10:00:00 [info] log information.&lt;/code&gt;&lt;/li&gt;&#xA;&lt;li&gt;到输出器。例如输出到文件中，我们就将这条信息写到文件上（&lt;code&gt;File::write(....);&lt;/code&gt;，文件中会记录&lt;code&gt;2018-3-22 10:00:00 [info] log information.&lt;/code&gt;）.&lt;/li&gt;&#xA;&lt;li&gt;假如你还实现了日志回滚等功能的话，在日志写入文件之后，还要判断是否触发日志回滚操作，如果满足了日志回滚的条件（比如文件&lt;code&gt;Size&lt;/code&gt;超过某一大小），则进行日志回滚操作。&lt;/li&gt;&#xA;&lt;li&gt;这条日志的生命周期结束了。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&#xA;&lt;h3 class=&#34;relative group&#34;&gt;三、伪代码实现：&#xA;    &lt;div id=&#34;三伪代码实现&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#%e4%b8%89%e4%bc%aa%e4%bb%a3%e7%a0%81%e5%ae%9e%e7%8e%b0&#34; aria-label=&#34;锚点&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h3&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;从配置文件中读取配置（可通过序列化或其他方式），生成Config。&lt;/li&gt;&#xA;&lt;li&gt;LoggerBuilder根据Config去构造Logger。&lt;/li&gt;&#xA;&lt;li&gt;由Logger实现日志库的核心功能。&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;div class=&#34;highlight-wrapper&#34;&gt;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-rust&#34; data-lang=&#34;rust&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//配置&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Config&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;level&lt;/span&gt;:&lt;span class=&#34;nc&#34;&gt;Level&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//Logger建造者&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;LoggerBuilder&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;..&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;.&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;c1&#34;&gt;//Logger&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;k&#34;&gt;struct&lt;/span&gt; &lt;span class=&#34;nc&#34;&gt;Logger&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;p&#34;&gt;{&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;record&lt;/span&gt;:&lt;span class=&#34;nc&#34;&gt;Recorder&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;filter&lt;/span&gt;:&lt;span class=&#34;nc&#34;&gt;Filter&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;formater&lt;/span&gt;:&lt;span class=&#34;nc&#34;&gt;Formater&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;&lt;span class=&#34;n&#34;&gt;output&lt;/span&gt;:&lt;span class=&#34;nc&#34;&gt;Output&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;,&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;p&#34;&gt;}&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;o&#34;&gt;......&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;&#xA;&#xA;&lt;h3 class=&#34;relative group&#34;&gt;四、更多功能细节&#xA;    &lt;div id=&#34;四更多功能细节&#34; class=&#34;anchor&#34;&gt;&lt;/div&gt;&#xA;    &#xA;    &lt;span&#xA;        class=&#34;absolute top-0 w-6 transition-opacity opacity-0 -start-6 not-prose group-hover:opacity-100 select-none&#34;&gt;&#xA;        &lt;a class=&#34;text-primary-300 dark:text-neutral-700 !no-underline&#34; href=&#34;#%e5%9b%9b%e6%9b%b4%e5%a4%9a%e5%8a%9f%e8%83%bd%e7%bb%86%e8%8a%82&#34; aria-label=&#34;锚点&#34;&gt;#&lt;/a&gt;&#xA;    &lt;/span&gt;&#xA;    &#xA;&lt;/h3&gt;&#xA;&lt;p&gt;上面是日志库设计的主干，可能我们还需要更多的功能，比如日志回滚、运行时修改配置等&amp;hellip;&amp;hellip;&lt;/p&gt;</description>
      
    </item>
    
  </channel>
</rss>
