那些年我們用過的組件-結構化日誌組件 Serilog

来源:https://www.cnblogs.com/newton/archive/2023/01/05/17026903.html
-Advertisement-
Play Games

什麼是結構化日誌 我們記錄日誌慣常使用 log4j2、NLog 等日誌組件,這些組件提供了輸出到多種終端的能力,但是大部分時候我們選擇將日誌輸出到操作系統的文件系統中,為什麼呢?至少有一部分原因是記錄的每條日誌為字元串格式,且按時間由遠往進順序記錄,打開文件可以直接人肉檢索;如果這些日誌記錄到其它終 ...


什麼是結構化日誌

我們記錄日誌慣常使用 log4j2NLog 等日誌組件,這些組件提供了輸出到多種終端的能力,但是大部分時候我們選擇將日誌輸出到操作系統的文件系統中,為什麼呢?至少有一部分原因是記錄的每條日誌為字元串格式,且按時間由遠往進順序記錄,打開文件可以直接人肉檢索;如果這些日誌記錄到其它終端比如資料庫中,由於是字元串格式,無法依靠資料庫的機制提高檢索效率,反而日誌的頻繁寫入和數據量的持續增大,對資料庫造成很大壓力,還需要花時間調優資料庫結構。

但 22 世紀都快到了,還在用古老的人肉檢索實在說不過去,於是出現了流行一時的 EFKELK框架,它們是幾個組件的集合。大致流程如下:

  1. 首先是日誌採集組件比如 filebeats,定時從配置好的路徑中採集增量日誌;
  2. 上傳到消息隊列比如 kafka,緩解日誌過多時的傳輸壓力;
  3. 然後送達日誌處理組件比如 logstash, logstash 使用 filter 對日誌進行拆分、映射、過濾等,抽取關鍵內容並形成符合目標資料庫特性的格式。註意此處出來的就是結構化日誌;
  4. 將結構化日誌存儲到特定的資料庫比如 elasticsearch 中;
  5. 通過用戶界面如 Kibana 進行日誌檢索。

上述流程在不同場景下有一些變種,不再贅述。 它們的主要目的就是使得傳統的文件日誌可以被電腦高效檢索。

那麼有沒有一種可能,跳過文件存儲,直接將日誌按特定格式寫入到目標存儲容器,可能是 elasticsearch,也可能是 mysql,甚至是文件系統。同樣代碼,輸出不同的格式到不同的終端,同時滿足 human-friendly and machine-readable

在 .NET 世界中, 本文的主角 Serilog 就可以幫我們省去那些彎彎繞繞,依靠它,記錄與查詢日誌顯得簡單而純粹。

Serilog

以官方例子說明:

var position = new { Latitude = 25, Longitude = 134 };
var elapsedMs = 34;

log.Information("Processed {@Position} in {Elapsed} ms", position, elapsedMs);

按字面意思,最終會輸出:

09:14:22 [INF] Processed {"Latitude": 25, "Longitude": 134} in 34 ms.

當 Serilog 將日誌直接輸出到文件系統或命令行時,結果是這樣沒錯,其它日誌組件也能做到(廢話)。

當輸出到 MongoDB 時,結果就不一樣了:

{ "Position": { "Latitude": 25, "Longitude": 134 }, "Elapsed": 34 }

Sink

Serilog 將輸出目標稱之為 sink,不同的 sink 可以有各自的格式要求。其實原理很簡單,輸出到特定 sink 時,日誌對象會先格式化處理(註意不是先生成字元串再格式化)。Serilog.Formatting.Compact 就是格式化為 json 的類庫,輸出到 elasticsearch 還需要 Serilog.Formatting.Elasticsearch。不過除非自定義 sink,這些我們都不用關心,使用時只要引入需要的 sink 類庫即可。

使用

下麵介紹在 .NET6 中使用 Serilog。

先引入 Serilog 類庫和需要的 Sink 庫比如這裡的 Serilog.Sinks.File

<PackageReference Include="Serilog" Version="2.12.0" />
<PackageReference Include="Serilog.Sinks.File" Version="5.0.0" />

以通用宿主程式為例:

IHost host = Host.CreateDefaultBuilder(args).Build();

// 配置並創建 logger 實例
var log = new LoggerConfiguration()
    .MinimumLevel.Warning()
    .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 10485760, rollOnFileSizeLimit: true, retainedFileCountLimit: 100, buffered: true)
    .CreateLogger();

log.Information("Hello, Serilog!"); // 直接使用(可以創建多個實例使用)

Log.Logger = log;   // Serilog 並沒有實例狀態需要線程間維護,所以為了方便我們可以使用單例模式,將實例賦給全局靜態屬性
Log.Information("The global logger has been configured");   // 項目內任意其它地方均可使用

await host.RunAsync().ContinueWith(_=> Log.CloseAndFlush());    // app 退出時釋放 logger 占用資源

如果想以 .NET 內置的方式調用 Serilog,對於通用宿主程式,須引入 Serilog.Extensions.Hosting,其扮演適配器的角色,將 Serilog 自己的介面 Serilog.ILogger 轉換為 Microsoft.Extensions.Logging.ILogger 使用。如果是 web 項目的話,引入的是 Serilog.AspNetCore.NET Core 1.0, 1.1 等版本需要引入的是 Serilog.Extensions.Logging

更改後的版本如下:

IHost host = Host
    .CreateDefaultBuilder(args)
    .UseSerilog()   // 新增該行
    .Build();

// ... 其餘代碼同上

另外,上述代碼是直接硬編碼配置 logger,更好的方式是通過 appsettings.json 配置 logger。首先引入 Serilog.Settings.Configuration,然後在 appsettings.json 中移除預設的 Logging 配置節,替換為 Serilog 配置節如下:

{
  "Serilog": {
    "Using": [ "Serilog.Sinks.File" ],
    "MinimumLevel": "Warning",
    "WriteTo": [
      {
        "Name": "File",
        "Args": {
          "path": "Logs/log.txt",
          "rollingInterval": "Day",
          "fileSizeLimitBytes": 10485760,
          "rollOnFileSizeLimit": true,
          "retainedFileCountLimit": 100,
          "buffered": true
        }
      }
    ]
  }
}

代碼更改如下:

IHost host = Host
    .CreateDefaultBuilder(args)
    .UseSerilog((ctx, config) => config
        .ReadFrom.Configuration(ctx.Configuration))
    .Build();

//以下註釋
//var log = new LoggerConfiguration()
//    .MinimumLevel.Warning()
//    .WriteTo.File("log.txt", rollingInterval: RollingInterval.Day, fileSizeLimitBytes: 10485760, rollOnFileSizeLimit: true, retainedFileCountLimit: 100, shared: true, buffered: true)
//    .CreateLogger();
//Log.Logger = log;

await host.RunAsync(); //註釋.ContinueWith(_ => Log.CloseAndFlush());

採用這種方式,Log.Logger 會隱式賦值,併在系統退出時自動釋放資源。

參考資料

Docker+EFK 快速搭建日誌收集系統
Message Templates
.NET Worker Service 添加 Serilog 日誌記錄


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

-Advertisement-
Play Games
更多相關文章
  • RESTfulL是一種網路應用程式的設計風格和開發方式,即介面請求方式和路徑的一種風格。 普通風格: localhost:8080/add?a=1&b=2 RestFul風格: localhost:8080/add/1/2 GET 獲取: localhost:8080/item/1 POST 新增: ...
  • 1、粘包與半包 啥也不說了,直接上代碼是不是有點不太友好,我所謂了,都快過年了,還要啥自行車 我上來就是一段代碼猛如虎 1.1 伺服器代碼 public class StudyServer { static final Logger log = LoggerFactory.getLogger(Stu ...
  • 我的客服系統有一些介面是專門給內部調用的,只允許其他內部系統來調用,不允許隨意訪問,可以使用IP白名單機制 使用 Gin 框架實現 IP 白名單機制可以使用中間件的方式實現。你可以編寫一個中間件函數,在每個請求到來時檢查它的 IP 地址是否在白名單中,如果不在,則返回錯誤信息。 例如,你可以這樣編寫 ...
  • JetBrains Clion 是一款專為 C/C++ 開發所設計的跨平臺 IDE。本文適用 JetBrains CLion v2019.3/3.1/3.2/3.3 永久激活,附破解補丁和激活碼,可以永久激活 Windows、MAC、Linux 下的 CLion!!!網上有激活碼的激活方式(更改 h ...
  • go build 命令好處 我開發了一套線上客服系統源碼,使用了go build進行編譯 在我的線上客服系統使用 go build 命令的主要好處是,它可以將 Go 程式編譯成可執行文件,這樣就可以將程式部署到生產環境中。 在生產環境中運行的程式通常是編譯後的可執行文件,因為這樣可以提高程式的執行效 ...
  • 可迭代對象通過iter(),轉化為迭代器對象,迭代器可以使用next()訪問,可迭代對象不能直接使用next(); 迭代器是一個可以記住遍歷的位置的對象,所以可以方便的使用next()。 可迭代對象(iterable):凡是具有__iter__的方法的類,都是可迭代的類。可迭代類創建的對象實現了__ ...
  • ​ 最近的資料庫課程要求將MySQL資料庫部署在伺服器上,參考了大佬們的博客後,總結一下。 先放上參考的大佬們的博客。 【原創經驗分享】JQuery(Ajax)調用WCF服務 - 南宮蕭塵 - 博客園 (cnblogs.com) WinForm+WCF+mysql+http實現簡單的用戶登錄註冊_小 ...
  • 在ERP系統中,採集一線的生產數據是重要工作之一,而稱重計量是企業的核心資產數據,人工計重費時費力,還容易出錯,重量數據是否正確,直接影響企業的採購或銷售額。基於此,由系統對接電子秤實現自動抓取數據是企業管理的第一步。 電子秤,一般由重量感測器、砝碼、底座、儀錶等組成。儀錶與感測器相連,儀錶一般具有 ...
一周排行
    -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.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...