rust 一個(gè)日志緩存記錄的通用實(shí)現(xiàn)方法
本文給出了一個(gè)通用的設(shè)計(jì)模式,通過建造者模式實(shí)例化記錄對象,可自定義格式化器將實(shí)例化后的記錄對象寫入到指定的緩存對象中。
定義記錄對象
use chrono::prelude::*; use std::{ cell::RefCell, ffi::OsStr, fmt, io, io::Write, path::Path, rc::Rc, str, time::SystemTime, }; const DATETIME_FORMAT: &str = "%Y-%m-%d %H:%M:%S"; /// 將 SystemTime 格式的時(shí)間轉(zhuǎn)換為指定格式的字符串 fn format_system_time(st: SystemTime) -> String { let local_datetime: DateTime<Local> = st.clone().into(); local_datetime.format(DATETIME_FORMAT).to_string() } /// 定義需要構(gòu)造的協(xié)議 #[derive(Debug, Default, Clone)] struct Record<'a> { event_time: Option<SystemTime>, var_a: Option<String>, var_b: Option<&'a Path>, var_c: Option<i32>, var_d: Option<&'a OsStr>, } /// Record -> RecordBuilder impl<'a> Record<'a> { /// Returns a new builder. #[inline] fn builder() -> RecordBuilder<'a> { RecordBuilder::new() } #[inline] fn event_time(&self) -> Option<SystemTime> { self.event_time } #[inline] fn var_a(&self) -> &Option<String> { &self.var_a } #[inline] fn var_b(&self) -> Option<&'a Path> { self.var_b } #[inline] fn var_c(&self) -> Option<i32> { self.var_c } #[inline] fn var_d(&self) -> Option<&'a OsStr> { self.var_d } }
定義對象的建造者
用于根據(jù)需求創(chuàng)建不同的記錄對象
/// 用于構(gòu)造協(xié)議,通過 Record 和 RecordBuidler 將協(xié)議的讀寫分離 #[derive(Debug)] struct RecordBuilder<'a> { record: Record<'a>, } impl<'a> RecordBuilder<'a> { /// Construct new `RecordBuilder`. #[inline] fn new() -> RecordBuilder<'a> { RecordBuilder { record: Record::default() } } #[inline] fn event_time( &mut self, event_time: Option<SystemTime>, ) -> &mut RecordBuilder<'a> { self.record.event_time = event_time; self } #[inline] fn var_a(&mut self, var_a: Option<String>) -> &mut RecordBuilder<'a> { self.record.var_a = var_a; self } #[inline] fn var_b(&mut self, var_b: Option<&'a Path>) -> &mut RecordBuilder<'a> { self.record.var_b = var_b; self } #[inline] fn var_c(&mut self, var_c: Option<i32>) -> &mut RecordBuilder<'a> { self.record.var_c = var_c; self } #[inline] fn var_d(&mut self, var_d: Option<&'a OsStr>) -> &mut RecordBuilder<'a> { self.record.var_d = var_d; self } /// Invoke the builder and return a `Record` #[inline] fn build(&mut self) -> Record<'a> { // todo 添加業(yè)務(wù)邏輯 self.record.clone() } } impl<'a> Default for RecordBuilder<'a> { fn default() -> Self { Self::new() } }
定義寫緩存對象
指定記錄對象的寫入緩存
/// 定義一個(gè)寫緩存 #[derive(Debug)] struct Buffer(Vec<u8>); impl Buffer { /// 初始化緩存 fn new() -> Self { Self(vec![]) } /// 清空緩存 fn clear(&mut self) { self.0.clear(); } /// 寫緩存 fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.0.extend(buf); Ok(buf.len()) } /// 刷新緩存 fn flush(&mut self) -> io::Result<()> { Ok(()) } /// 獲得緩存的內(nèi)容 fn bytes(&self) -> &[u8] { &self.0 } } impl Default for Buffer { fn default() -> Self { Self::new() } }
定義用于格式化器的寫緩存
不同的格式化器可以使用不同的緩存,這里使用上面定義的一個(gè)簡單的數(shù)組緩存來實(shí)現(xiàn)格式化器需要的緩存。
/// 定義緩存內(nèi)容的格式器 struct FormatterBuffer { buf: Rc<RefCell<Buffer>>, // RefCell可以修改buf,Rc可以避免使用作用域標(biāo)識(shí) } impl FormatterBuffer { fn new(buffer: Rc<RefCell<Buffer>>) -> Self { FormatterBuffer { buf: buffer } } fn clear(&mut self) { self.buf.borrow_mut().clear() } fn buf(&self) -> Rc<RefCell<Buffer>> { self.buf.clone() } } impl io::Write for FormatterBuffer { fn write(&mut self, buf: &[u8]) -> io::Result<usize> { self.buf.borrow_mut().write(buf) } fn flush(&mut self) -> io::Result<()> { self.buf.borrow_mut().flush() } } impl fmt::Debug for FormatterBuffer { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { f.debug_struct("FormatterBuffer").finish() } }
定義格式化器
不同的格式化器將記錄轉(zhuǎn)換為不同的格式,寫入到緩存中。
#[derive(Debug)] /// 格式化器 struct Format<'a> { buf: &'a mut FormatterBuffer, // 數(shù)據(jù)緩存 sep: &'a str, // 分隔符 } impl<'a> Format<'a> { /// 寫數(shù)據(jù)到緩存中 fn write(mut self, record: &Record) -> io::Result<()> { 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(&mut self, record: &Record) -> io::Result<()> { match record.event_time() { Some(event_time) => { let datetime_str = format_system_time(event_time); write!(self.buf, "{}{}", datetime_str, self.sep) } None => { write!(self.buf, "{}", self.sep) } } } fn write_var_a(&mut self, record: &Record) -> io::Result<()> { match record.var_a() { Some(var_a) => { write!(self.buf, "{}{}", var_a, self.sep) } None => write!(self.buf, "{}", self.sep), } } fn write_var_b(&mut self, record: &Record) -> io::Result<()> { match record.var_b() { Some(var_b) => { write!( self.buf, "{}{}", var_b.to_string_lossy(), // 操作系統(tǒng)對路徑處理的差異性可能會(huì)丟失部分?jǐn)?shù)據(jù) self.sep ) } None => write!(self.buf, "{}", self.sep), } } fn write_var_c(&mut self, record: &Record) -> io::Result<()> { match record.var_c() { Some(var_c) => { write!(self.buf, "{}{}", var_c, self.sep) } None => write!(self.buf, "{}", self.sep), } } fn write_var_d(&mut self, record: &Record) -> io::Result<()> { match record.var_d() { Some(var_d) => { write!( self.buf, "{}{}", var_d.to_os_string().to_str().unwrap(), // 操作系統(tǒng)對路徑處理的差異性可能會(huì)panic self.sep ) } None => write!(self.buf, "{}", self.sep), } } }
調(diào)用示例
fn main() { // 創(chuàng)建緩存 let buffer = Rc::new(RefCell::new(Buffer::default())); let mut format_buffer = FormatterBuffer::new(buffer.clone()); format_buffer.clear(); // 創(chuàng)建一個(gè)格式化器 let format = Format { buf: &mut format_buffer, sep: "|" }; // 構(gòu)造事件發(fā)生時(shí)間 let no_timezone = NaiveDateTime::parse_from_str("2024-01-02 03:04:05", DATETIME_FORMAT) .unwrap(); let event_time = Local.from_local_datetime(&no_timezone).unwrap().into(); // 構(gòu)造路徑 let path = Path::new("./foo/bar.txt"); let os_str = OsStr::new("1.png"); // 構(gòu)造記錄 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(&record); // 獲得RefCell對象的內(nèi)部值 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); }
參考
https://github.com/rust-cli/env_logger
到此這篇關(guān)于rust 一個(gè)日志緩存記錄的通用實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)rust日志緩存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
rust?創(chuàng)建多線程web?server的詳細(xì)過程
web?server?中主要的兩個(gè)協(xié)議是?http?和?tcp,tcp?是底層協(xié)議,http?是構(gòu)建在?tcp?之上的,本篇文章重點(diǎn)給大家介紹rust?創(chuàng)建多線程web?server的詳細(xì)過程,感興趣的朋友跟隨小編一起看看吧2023-11-11rust多個(gè)mod文件引用和文件夾mod使用注意事項(xiàng)小結(jié)
在 Rust 項(xiàng)目中,可以使用 mod 關(guān)鍵字將一個(gè)文件夾或一個(gè) rs 文件作為一個(gè)模塊引入到當(dāng)前文件中,本文給大家介紹rust多個(gè)mod文件引用和文件夾mod使用注意事項(xiàng)小結(jié),感興趣的朋友跟隨小編一起看看吧2024-03-03Rust中使用Serde對json數(shù)據(jù)進(jìn)行反序列化
JSON作為目前流行的數(shù)據(jù)格式之一,被大家廣泛使用,在日常的開發(fā)實(shí)踐中,將JSON數(shù)據(jù)反序列化為對應(yīng)的類型具有重要的意義,在Rust中,Serde幾乎成了JSON數(shù)據(jù)解析的事實(shí)標(biāo)準(zhǔn),本文將給大家介紹Rust中使用Serde對json數(shù)據(jù)進(jìn)行反序列化,需要的朋友可以參考下2024-01-01libbpf和Rust開發(fā)ebpf程序?qū)崙?zhàn)示例
這篇文章主要為大家介紹了libbpf和Rust開發(fā)ebpf程序?qū)崙?zhàn)示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-12-12Rust語言之Prometheus系統(tǒng)監(jiān)控工具包的使用詳解
Prometheus?是一個(gè)開源的系統(tǒng)監(jiān)控和警報(bào)工具包,最初是由SoundCloud構(gòu)建的,隨著時(shí)間的發(fā)展,Prometheus已經(jīng)具有適用于各種使用場景的版本,為了開發(fā)者方便開發(fā),更是有各種語言版本的Prometheus的開發(fā)工具包,本文主要介紹Rust版本的Prometheus開發(fā)工具包2023-10-10