知情识趣 發表於 2024-4-2 10:20:33

rust 一个日志缓存记录的通用实现方法

<div id="navCategory"><h5 class="catalogue">目录</h5><ul class="first_class_ul"><li>定义记录对象</li><li>定义对象的建造者</li><li>定义写缓存对象</li><li>定义用于格式化器的写缓存</li><li>定义格式化器</li><li>调用示例</li><li>参考</li></ul></div><p>本文给出了一个通用的设计模式,通过建造者模式实例化记录对象,可自定义格式化器将实例化后的记录对象写入到指定的缓存对象中。</p>
<p class="maodian"></p><h2>定义记录对象</h2>
<div class="jb51code"><pre class="brush:plain;">use chrono::prelude::*;
use std::{
    cell::RefCell, ffi::OsStr, fmt, io, io::Write, path::Path, rc::Rc, str,
    time::SystemTime,
};
const DATETIME_FORMAT: &amp;str = "%Y-%m-%d %H:%M:%S";
/// 将 SystemTime 格式的时间转换为指定格式的字符串
fn format_system_time(st: SystemTime) -&gt; String {
    let local_datetime: DateTime&lt;Local&gt; = st.clone().into();
    local_datetime.format(DATETIME_FORMAT).to_string()
}
/// 定义需要构造的协议
#
struct Record&lt;'a&gt; {
    event_time: Option&lt;SystemTime&gt;,
    var_a: Option&lt;String&gt;,
    var_b: Option&lt;&amp;'a Path&gt;,
    var_c: Option&lt;i32&gt;,
    var_d: Option&lt;&amp;'a OsStr&gt;,
}
/// Record -&gt; RecordBuilder
impl&lt;'a&gt; Record&lt;'a&gt; {
    /// Returns a new builder.
    #
    fn builder() -&gt; RecordBuilder&lt;'a&gt; {
      RecordBuilder::new()
    }
    #
    fn event_time(&amp;self) -&gt; Option&lt;SystemTime&gt; {
      self.event_time
    }
    #
    fn var_a(&amp;self) -&gt; &amp;Option&lt;String&gt; {
      &amp;self.var_a
    }
    #
    fn var_b(&amp;self) -&gt; Option&lt;&amp;'a Path&gt; {
      self.var_b
    }
    #
    fn var_c(&amp;self) -&gt; Option&lt;i32&gt; {
      self.var_c
    }
    #
    fn var_d(&amp;self) -&gt; Option&lt;&amp;'a OsStr&gt; {
      self.var_d
    }
}</pre></div>
<p class="maodian"></p><h2>定义对象的建造者</h2>
<p>用于根据需求创建不同的记录对象</p>
<div class="jb51code"><pre class="brush:plain;">/// 用于构造协议,通过 Record 和 RecordBuidler 将协议的读写分离
#
struct RecordBuilder&lt;'a&gt; {
    record: Record&lt;'a&gt;,
}
impl&lt;'a&gt; RecordBuilder&lt;'a&gt; {
    /// Construct new `RecordBuilder`.
    #
    fn new() -&gt; RecordBuilder&lt;'a&gt; {
      RecordBuilder { record: Record::default() }
    }
    #
    fn event_time(
      &amp;mut self,
      event_time: Option&lt;SystemTime&gt;,
    ) -&gt; &amp;mut RecordBuilder&lt;'a&gt; {
      self.record.event_time = event_time;
      self
    }
    #
    fn var_a(&amp;mut self, var_a: Option&lt;String&gt;) -&gt; &amp;mut RecordBuilder&lt;'a&gt; {
      self.record.var_a = var_a;
      self
    }
    #
    fn var_b(&amp;mut self, var_b: Option&lt;&amp;'a Path&gt;) -&gt; &amp;mut RecordBuilder&lt;'a&gt; {
      self.record.var_b = var_b;
      self
    }
    #
    fn var_c(&amp;mut self, var_c: Option&lt;i32&gt;) -&gt; &amp;mut RecordBuilder&lt;'a&gt; {
      self.record.var_c = var_c;
      self
    }
    #
    fn var_d(&amp;mut self, var_d: Option&lt;&amp;'a OsStr&gt;) -&gt; &amp;mut RecordBuilder&lt;'a&gt; {
      self.record.var_d = var_d;
      self
    }
    /// Invoke the builder and return a `Record`
    #
    fn build(&amp;mut self) -&gt; Record&lt;'a&gt; {
      // todo 添加业务逻辑
      self.record.clone()
    }
}
impl&lt;'a&gt; Default for RecordBuilder&lt;'a&gt; {
    fn default() -&gt; Self {
      Self::new()
    }
}</pre></div>
<p class="maodian"></p><h2>定义写缓存对象</h2>
<p>指定记录对象的写入缓存</p>
<div class="jb51code"><pre class="brush:plain;">/// 定义一个写缓存
#
struct Buffer(Vec&lt;u8&gt;);
impl Buffer {
    /// 初始化缓存
    fn new() -&gt; Self {
      Self(vec![])
    }
    /// 清空缓存
    fn clear(&amp;mut self) {
      self.0.clear();
    }
    /// 写缓存
    fn write(&amp;mut self, buf: &amp;) -&gt; io::Result&lt;usize&gt; {
      self.0.extend(buf);
      Ok(buf.len())
    }
    /// 刷新缓存
    fn flush(&amp;mut self) -&gt; io::Result&lt;()&gt; {
      Ok(())
    }
    /// 获得缓存的内容
    fn bytes(&amp;self) -&gt; &amp; {
      &amp;self.0
    }
}
impl Default for Buffer {
    fn default() -&gt; Self {
      Self::new()
    }
}</pre></div>
<p class="maodian"></p><h2>定义用于格式化器的写缓存</h2>
<p>不同的格式化器可以使用不同的缓存,这里使用上面定义的一个简单的数组缓存来实现格式化器需要的缓存。</p>
<div class="jb51code"><pre class="brush:plain;">/// 定义缓存内容的格式器
struct FormatterBuffer {
    buf: Rc&lt;RefCell&lt;Buffer&gt;&gt;, // RefCell可以修改buf,Rc可以避免使用作用域标识
}
impl FormatterBuffer {
    fn new(buffer: Rc&lt;RefCell&lt;Buffer&gt;&gt;) -&gt; Self {
      FormatterBuffer { buf: buffer }
    }
    fn clear(&amp;mut self) {
      self.buf.borrow_mut().clear()
    }
    fn buf(&amp;self) -&gt; Rc&lt;RefCell&lt;Buffer&gt;&gt; {
      self.buf.clone()
    }
}
impl io::Write for FormatterBuffer {
    fn write(&amp;mut self, buf: &amp;) -&gt; io::Result&lt;usize&gt; {
      self.buf.borrow_mut().write(buf)
    }
    fn flush(&amp;mut self) -&gt; io::Result&lt;()&gt; {
      self.buf.borrow_mut().flush()
    }
}
impl fmt::Debug for FormatterBuffer {
    fn fmt(&amp;self, f: &amp;mut fmt::Formatter) -&gt; fmt::Result {
      f.debug_struct("FormatterBuffer").finish()
    }
}</pre></div>
<p class="maodian"></p><h2>定义格式化器</h2>
<p>不同的格式化器将记录转换为不同的格式,写入到缓存中。</p>
<div class="jb51code"><pre class="brush:plain;">#
/// 格式化器
struct Format&lt;'a&gt; {
    buf: &amp;'a mut FormatterBuffer, // 数据缓存
    sep: &amp;'a str,               // 分隔符
}
impl&lt;'a&gt; Format&lt;'a&gt; {
    /// 写数据到缓存中
    fn write(mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      let _ = self.write_event_time(record);
      let _ = self.write_var_a(record);
      let _ = self.write_var_b(record);
      let _ = self.write_var_c(record);
      let _ = self.write_var_d(record);
      Ok(())
    }
    fn write_event_time(&amp;mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      match record.event_time() {
            Some(event_time) =&gt; {
                let datetime_str = format_system_time(event_time);
                write!(self.buf, "{}{}", datetime_str, self.sep)
            }
            None =&gt; {
                write!(self.buf, "{}", self.sep)
            }
      }
    }
    fn write_var_a(&amp;mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      match record.var_a() {
            Some(var_a) =&gt; {
                write!(self.buf, "{}{}", var_a, self.sep)
            }
            None =&gt; write!(self.buf, "{}", self.sep),
      }
    }
    fn write_var_b(&amp;mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      match record.var_b() {
            Some(var_b) =&gt; {
                write!(
                  self.buf,
                  "{}{}",
                  var_b.to_string_lossy(), // 操作系统对路径处理的差异性可能会丢失部分数据
                  self.sep
                )
            }
            None =&gt; write!(self.buf, "{}", self.sep),
      }
    }
    fn write_var_c(&amp;mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      match record.var_c() {
            Some(var_c) =&gt; {
                write!(self.buf, "{}{}", var_c, self.sep)
            }
            None =&gt; write!(self.buf, "{}", self.sep),
      }
    }
    fn write_var_d(&amp;mut self, record: &amp;Record) -&gt; io::Result&lt;()&gt; {
      match record.var_d() {
            Some(var_d) =&gt; {
                write!(
                  self.buf,
                  "{}{}",
                  var_d.to_os_string().to_str().unwrap(), // 操作系统对路径处理的差异性可能会panic
                  self.sep
                )
            }
            None =&gt; write!(self.buf, "{}", self.sep),
      }
    }
}</pre></div>
<p class="maodian"></p><h2>调用示例</h2>
<div class="jb51code"><pre class="brush:plain;">
fn main() {
    // 创建缓存
    let buffer = Rc::new(RefCell::new(Buffer::default()));
    let mut format_buffer = FormatterBuffer::new(buffer.clone());
    format_buffer.clear();

    // 创建一个格式化器
    let format = Format { buf: &amp;mut format_buffer, sep: "|" };

    // 构造事件发生时间
    let no_timezone =
      NaiveDateTime::parse_from_str("2024-01-02 03:04:05", DATETIME_FORMAT)
            .unwrap();
    let event_time = Local.from_local_datetime(&amp;no_timezone).unwrap().into();
    // 构造路径
    let path = Path::new("./foo/bar.txt");
    let os_str = OsStr::new("1.png");
    // 构造记录
    let record = Record::builder()
      .event_time(Some(event_time))
      .var_a(Some("hello world".to_string()))
      .var_b(Some(path))
      .var_c(Some(999))
      .var_d(Some(os_str))
      .build();

    // 写记录到缓存
    let _ = format.write(&amp;record);

    // 获得RefCell对象的内部值
    let ref_cell_inner_value = buffer.borrow();
    let actual = str::from_utf8(ref_cell_inner_value.bytes()).unwrap();

    let expect = "2024-01-02 03:04:05|hello world|./foo/bar.txt|999|1.png|";
    assert_eq!(actual, expect);
}

</pre></div>
<p class="maodian"></p><h2>参考</h2>
<p>https://github.com/rust-cli/env_logger</p>
<p>到此这篇关于rust 一个日志缓存记录的通用实现的文章就介绍到这了,更多相关rust日志缓存内容请搜索琼殿技术社区以前的文章或继续浏览下面的相关文章希望大家以后多多支持琼殿技术社区!</p>
                           
                            <div class="art_xg">
                              <b>您可能感兴趣的文章:</b><ul><li>rust的nutyp验证和validator验证数据的方法示例详解</li><li>Rust&nbsp;累计时间长度的操作方法</li><li>rust使用Atomic创建全局变量和使用操作方法</li><li>Rust捕获全局panic并记录进程退出日志的方法</li><li>RUST语言函数的定义与调用方法</li><li>Rust中的方法与关联函数使用解读</li></ul>
                            </div>

                        </div>
                        <!--endmain-->
頁: [1]
查看完整版本: rust 一个日志缓存记录的通用实现方法