27. 乾貨系列從零用Rust編寫正反向代理,Rust中日誌庫的應用基礎準備

来源:https://www.cnblogs.com/wmproxy/archive/2023/11/15/wmproxy27.html
-Advertisement-
Play Games

日誌在程式中的重要性非常的重要,當系統發生故障時,我們要隨時能排查出相關的日誌,細數日誌在Rust中的定義依賴及其實現。 ...


wmproxy

wmproxy已用Rust實現http/https代理, socks5代理, 反向代理, 靜態文件伺服器,四層TCP/UDP轉發,內網穿透,後續將實現websocket代理等,會將實現過程分享出來,感興趣的可以一起造個輪子

項目地址

國內: https://gitee.com/tickbh/wmproxy

github: https://github.com/tickbh/wmproxy

日誌

日誌在程式中的重要性非常的重要,當系統發生故障時,我們要隨時能排查出相關的日誌,所以通常有了日誌分級的概念(如錯誤error,警告warn,信息info,調試debug,追蹤trace),如果系統出了嚴重的Bug,那我們此時應該排查warn及error看是否有相應的錯誤信息。如果是程式流程上的問題,可能會很瑣碎,那我們可能需要排查trace的消息。

相對來說,trace的日誌數據量極大,當然也最瑣碎,排查起來會極難排查,要根據相關的關鍵字來定位相關日誌,通常一個類型的日誌會定義相同的關鍵字,在Java中類似Tag這種,在Rust庫中日誌會根據庫自動顯示出來,我們可以輕鬆的根據庫名定位同一個庫的問題。同一個庫內可根據關鍵字來定位。

日誌分類

標準輸出

程式中存在標準輸出(stdout)及錯誤輸出(stderr),通常程式的運行中會將標準輸出的內容顯示在控制臺上,我們就可以根據輸出的內容來判定程式是否正常執行。在Rust中,最常用的是巨集println!()

文件輸出

如果是服務類型的程式,常常會將數據輸出到文件中,因為它運行時間通常按天或者月甚至是年來計算。產生的日誌量也極為龐大,通常要按天來切割日誌,且單文件可能上GB大小,在後臺運行時,通過也會通過重定向將控制台的內容輸出到文件上。
後臺執行command命令,並將內容輸出到myout.log,且將stderr重定向到stdout。如:

nohup command > myout.log 2>&1 &

Rust中的日誌庫

通常在Rust中有日誌庫基本上都是基於log庫去做實現,他定義了日誌的等級,總共5個級別

pub enum Level {
    Error = 1,
    Warn,
    Info,
    Debug,
    Trace,
}

通常用巨集來進行輸出,下麵來看下輸出巨集的定義:

#[macro_export]
macro_rules! info {
    (target: $target:expr, $($arg:tt)+) => ($crate::log!(target: $target, $crate::Level::Info, $($arg)+));

    ($($arg:tt)+) => ($crate::log!($crate::Level::Info, $($arg)+))
}

他分為兩種情況,一種是有目標target,一種是預設target為root

在wmproxy中,我們通過服務的類型,找到日誌輸出的不同target,就可以控制輸出目錄一致或者不一致的控制,如:

log::info!(target: "access", "{}", String::from_utf8_lossy(&buf[..]));

此外設定日誌的等級,如果設定為等級為Level::Info那麼log::trace!log::debug!的日誌將不會做任何輸出。

以下是我用過的兩個日誌庫:

  1. env_logger
    這是一個根據環境變數來控制日誌等級,並可以自由設置target輸出的日誌庫,我們需要手動調用初始化:
env_logger::init();

  以下是如何啟動控制最簡單版:

RUST_LOG=debug cargo run

# windows
$env:RUST_LOG="debug"
cargo run

此外還可以設定特定庫的日誌等級:

當前庫預設的日誌等級是info,但是wenmeng及webparse庫的日誌等級為warn,可以有效的過濾第三方庫日誌信息又不影響自身的信息

RUST_LOG="info,wenmeng=warn,webparse=warn" cargo run
  1. log4rs
    這是一個根據配置文件來控制日誌輸出到控制台或者輸出到文件及文件是否壓縮是否切割等數據,也可以同時輸出到控制台及文件中。
    他通常通過配置文件來載入配置,以下是他的配置內容
# 每隔30秒檢查當前文件
refresh_rate: 30 seconds

appenders:
  # 標準輸出的類型設置為控制台
  stdout:
    kind: console

  # 請求數據放置在log/requests.log文件中
  requests:
    kind: file
    path: "log/requests.log"
    encoder:
      # 輸出格式d為日期,m為內容,n為換行符
      pattern: "{d} - {m}{n}"

root:
  # 預設的日誌等級為warn
  level: warn
  # 標準輸出只輸到stdout的配置,即上面配置的控制台
  appenders:
    - stdout

loggers:
  app::backend::db:
    level: info

  app::requests:
    level: info
    appenders:
      - requests
    # 是否追加到root里,如果配置為true他將同時輸出兩個
    additive: false

然後調用初始化:

log4rs::init_file("log4rs.yml", Default::default()).unwrap();

log4rs規則

應用程式獲取日誌記錄並將其記錄到某個地方,例如,將其記錄到文件、控制台或系統日誌中。

實現格式:

  • console: 控制台輸出,需要console_appender特征
  • file: 文件輸出,需要file_appender特征
  • rolling_file: 滾動文件輸出,需要rolling_file_appender特征且必須配置compound_policy
    • compound: 如何觸發文件切割
      • Rollers
        • delete: 觸發時刪除舊數據
        • fixed_window: 將舊數據如何進行存儲配置
      • Triggers
        • size: 觸發大小的限制

以下是只保留10m大小的日誌,多餘數據全部刪除的配置:

kind: rolling_file

path: log/foo.log

append: true

encoder:
  kind: pattern

policy:
  kind: compound

  trigger:
    kind: size
    limit: 10 mb

  roller:
    kind: delete

如果要保留舊數據,可以修改roller的配置:

kind: fixed_window

pattern: archive/foo.{}.log

count: 5

base: 1

舊文件將會保持archive/foo.0.logarchive/foo.1.log……archive/foo.4.log
如果配置的尾碼名稱為.gz且開始了gzip的特征,那麼目標文件將會被自動壓縮成gz格式,如archive/foo.{}.log.gz。如:

log4rs = { version ="1.0.0", features = ["gzip"] }

匹配模型:

這是log4rs的簡單模型輸出,以{}裡面包含目標數據及可能攜帶的參數:

  • d, date - 當前的日期格式.
    一個自定義的格式,依賴於chrono,獲取的日誌的寫入的當前時間,第一個參數為時間的自定為格式,第二個參數 是utc或者為local。以下參數
    • {d} - 2022-11-15T14:22:20.644420340-08:00
    • {d(%Y-%m-%d %H:%M:%S)} - 2022-11-15 14:22:20
    • {d(%Y-%m-%d %H:%M:%S %Z)(utc)} - 2022-11-15 22:22:20 UTC
  • f, file - 當前列印的源文件,如果沒有顯示???
  • h, highlight - 高亮當前日誌,如果有錯誤顯示紅色,藍色顯示info等
    • {h(the level is {l})} -
      <code style="color: red; font-weight: bold">the level is ERROR</code>
  • l, level - 當前日誌等級.
  • L, line - 當前列印的源文件的行數,如果沒有顯示???
  • m, message - 當前的消息詳情.
  • M, module - 當前列印的源模塊,如果沒有顯示???
  • P, pid - 當前的進程id.
  • i, tid - 當前的線程id.
  • n - 換行符.
  • t, target - 目標輸出的target.
  • T, thread - 當前的線程名稱.
  • I, thread_id - pthread的線程id.

結語

log4rs提供了自定義的一些功能,可以友好的設置一些日誌的功能,下一篇將講解如何自定義實現access_logerror_log的功能。

點擊 [關註][在看][點贊] 是對作者最大的支持


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 概述 Java 中的引用類似 C 語言中的指針,指向一個對象,比如: // person 就是指向 Person 實例“張三”的引用 Person person = new Person("張三"); 在 JDK1.2 以前,Java 里的引用是很傳統的定義:如果 reference 類型的數據中存 ...
  • 1 前言 如果你正在準備軟體工程師或軟體開發人員的面試,那麼你可能知道由於其開放性質和廣泛性,準備系統設計是多麼困難,但同時你也不能忽略它。在軟體工程界,如果你正在申請高級工程師/主管/架構師或更高級別的角色,系統設計是最受追捧的技能,也是整個過程中最重要的環節之一。如果你搞砸了這個,其他的都不重要 ...
  • 關於Node.js的開發者來說,在開發機器上管理多個不同版本的Node.js是一個常見痛點。之前在開發者安全大全專欄中,提到過解決方法:使用nvm,如果對於nvm還不瞭解的話,可以前往瞭解。 對於TJ來說,因為習慣敲命令了,所以nvm其實已經夠用了。但是,有的小伙伴還是更喜歡可視化的管理工具。所以, ...
  • 我希望在職業生涯早期就開始做的事情和我希望以不同的方式做的事情。 大家好,我已經做了八年半的軟體工程師。這篇文章來源於我最近對自己在職業生涯中希望早點開始做的事情以及希望以不同方式做的事情的自我反思。 我在這裡分享的對任何希望提高和進步到高級甚至更高職位的初級至中級開發者都很有用。 0 大綱 我的職 ...
  • 資料庫事務是什麼?事務的四大特性是什麼? 1.資料庫事務 事務是一組原子性的 SQL 語句,或者說一個獨立的工作單元。如果資料庫引擎能夠成功地對資料庫應用該組操作的全部語句,那麼就執行該組查詢。如果其中任何一條語句因為崩潰或其他原因無法執行,那麼所有的語句都不會執行。也就是說,事務內的語句,要麼全部 ...
  • 學習視頻:【孫哥說Spring5:從設計模式到基本應用到應用級底層分析,一次深入淺出的Spring全探索。學不會Spring?只因你未遇見孫哥】 第四章、註入(Injection) 1.什麼是註入 通過Spring工廠及配置文件,為所創建對象的成員變數賦值 1.1為什麼需要註入 “通過編碼的方式,為 ...
  • 公眾號「架構成長指南」,專註於生產實踐、雲原生、分散式系統、大數據技術分享。 在本文中,我們將討論一些重要且常見的 Java Lambda 表達式面試問題和解答 1.什麼是 Lambda 表達式? lambda表達式只是一個沒有任何名稱的函數,它甚至可以用作函數中的參數,Lambda 表達式有利於函 ...
  • 目錄abstract class 和 interface 有什麼區別1.抽象類1.1抽象類的格式1.2抽象類註意事項2.介面2.1介面的格式2.2介面可以多繼承2.3介面的實現(implements)3.異同 abstract class 和 interface 有什麼區別 1.抽象類 抽象類:聲明 ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...