<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Serilog 日志庫的簡(jiǎn)介

      〇、前言

      相較于 log4net,Serilog 則是新項(xiàng)目的首選,現(xiàn)代化、高性能、易用,是 .NET 日志的未來方向。如需了解 log4net 詳見往期博文:http://www.rzrgm.cn/hnzhengfy/p/19121607/log4net

      log4net 雖然是一個(gè)廣泛使用的、功能強(qiáng)大的日志記錄庫,而且專為 .NET 平臺(tái)設(shè)計(jì),但由于她是較老的日志框架,其生態(tài)在 .NET Core/.NET 5+ 環(huán)境中支持有限,因此還是要慎重考慮。

      方面 log4net Serilog
      日志模型 文本日志:日志是純字符串,信息混在一起。
      例如:"用戶 alice 從 192.168.1.1 登錄"
      結(jié)構(gòu)化日志:日志是帶屬性的數(shù)據(jù)事件。
      例如:"用戶 {UserName} 從 {IP} 登錄",UserName="alice", IP="192.168.1.1"
      配置方式 主要靠 XML 文件,復(fù)雜且不易讀。 支持代碼和 appsettings.json,更現(xiàn)代、簡(jiǎn)潔。
      API 使用 需為每個(gè)類創(chuàng)建 logger 實(shí)例,較繁瑣。 提供靜態(tài) Log 類,一行代碼即可記錄,更簡(jiǎn)單。
      生態(tài)系統(tǒng) 老牌庫,Appenders 豐富但更新慢。 Sinks 生態(tài)活躍,原生支持 Elasticsearch、Seq、云平臺(tái)等。
      .NET 集成 在 ASP.NET Core 中集成較麻煩。 與 ASP.NET Core 深度集成,自動(dòng)記錄請(qǐng)求上下文。
      維護(hù)狀態(tài) 活躍維護(hù),持續(xù)更新,最新版 3.2.0(20250823)。 活躍維護(hù),持續(xù)更新,支持最新 .NET 版本。

      經(jīng)過對(duì)比,當(dāng)然還是 Serilog 更有優(yōu)勢(shì),那么本文將就概念方面來詳細(xì)介紹下,后續(xù)會(huì)繼續(xù)更新相關(guān)用法實(shí)踐,有興趣可持續(xù)關(guān)注。

      一、Serilog 簡(jiǎn)介

      Serilog 是一個(gè)為 .NET 應(yīng)用程序設(shè)計(jì)的強(qiáng)大的診斷日志庫,以易于設(shè)置、簡(jiǎn)潔的 API 和跨所有最新 .NET 平臺(tái)的兼容性而著稱。

      它是 .NET 平臺(tái)中非常流行且強(qiáng)大的結(jié)構(gòu)化日志庫,其最大特點(diǎn)是結(jié)構(gòu)化日志記錄(Structured Logging)

      1.1 核心特點(diǎn):結(jié)構(gòu)化日志記錄(Structured Logging)

      日志不是簡(jiǎn)單的字符串,而是包含命名屬性的結(jié)構(gòu)化事件。

      // 例如記錄用戶登錄事件
      string username = "bob";
      string clientIp = "10.0.0.5";
      int userId = 789;
      Log.Information("用戶 {UserName} (ID: {UserId}) 從 {ClientIP} 登錄", 
                      username, userId, clientIp);
      // 生成的結(jié)構(gòu)化數(shù)據(jù)(以 JSON 形式表示):
      {
        "Timestamp": "2025-03-28T14:30:00Z",
        "Level": "Information",
        "MessageTemplate": "用戶 {UserName} (ID: {UserId}) 從 {ClientIP} 登錄",
        "RenderedMessage": "用戶 bob (ID: 789) 從 10.0.0.5 登錄",
        "Properties": {
          "UserName": "bob",
          "UserId": 789,
          "ClientIP": "10.0.0.5"
        }
      }
      // 可以直接在 Seq 或 Elasticsearch 中搜索,例如:UserName = 'bob'

      這樣便于和另外的日志接收系統(tǒng)對(duì)接,針對(duì)日志量較大的場(chǎng)景比較友好。

      1.2 核心特點(diǎn):強(qiáng)大的 Sink 生態(tài)系統(tǒng)

      Serilog 通過 Sinks(接收器)將日志事件發(fā)送到各種目的地。這種“即插即用”的架構(gòu)是 Serilog 強(qiáng)大和流行的關(guān)鍵。

      官方 Sinks:Serilog.Sinks.Console(控制臺(tái))、Serilog.Sinks.File(文件)、Serilog.Sinks.Seq(Seq 服務(wù)器)、Serilog.Sinks.Elasticsearch(Elasticsearch)等。

      第三方 Sinks:支持 Splunk、DataDog、Graylog、Kafka、RabbitMQ、AWS CloudWatch 等

      優(yōu)勢(shì):可以同時(shí)配置多個(gè) Sinks,將同一日志事件發(fā)送到不同地方

      工作原理:

      日志事件生成:業(yè)務(wù)端代碼調(diào)用 Log.Information("..."),Serilog 創(chuàng)建一個(gè) LogEvent 對(duì)象。
      事件處理:該事件可能經(jīng)過過濾、豐富(Enrichment)等處理。
      分發(fā)到 Sinks:Serilog 核心引擎將處理后的 LogEvent 分發(fā)給所有配置的 Sinks。
      Sink 執(zhí)行寫入:每個(gè) Sink 根據(jù)自己的邏輯,將 LogEvent 轉(zhuǎn)換為適合目標(biāo)系統(tǒng)的格式(如 JSON、文本行),并通過相應(yīng)協(xié)議(如 HTTP、文件 I/O)發(fā)送出去。

      1.3 核心特點(diǎn):簡(jiǎn)潔易用的 API

      使用靜態(tài) Log 類,無需依賴注入即可在任何地方記錄日志。

      它極大地簡(jiǎn)化了日志記錄的開發(fā)體驗(yàn),讓開發(fā)者能夠以最少的代碼、最直觀的方式完成強(qiáng)大的日志功能。

      // Serilog:全局靜態(tài) Log 類,任何地方直接調(diào)用
      Log.[Level](string messageTemplate, params object[] propertyValues); // 格式
      Log.Verbose("調(diào)試信息: {Detail}", detail); // 示例
      Log.Debug("進(jìn)入方法: {MethodName}", "ProcessOrder");
      Log.Information("訂單 {OrderId} 已創(chuàng)建", orderId);
      Log.Warning("庫存不足,商品 {ProductId}", productId);
      Log.Error(exception, "處理支付失敗,用戶 {UserId}", userId);
      Log.Fatal("應(yīng)用程序即將退出");
      // 對(duì)比傳統(tǒng)日志庫 log4net 的方式:
      // 每個(gè)類都需要聲明一個(gè) logger 實(shí)例,代碼重復(fù),不夠優(yōu)雅
      private static readonly ILog log = LogManager.GetLogger(typeof(MyClass));
      public void DoSomething()
      {
          log.Info("用戶登錄");
      }

      支持所有標(biāo)準(zhǔn)日志級(jí)別:Verbose,Debug,Information,Warning,Error,F(xiàn)atal。

      使用 {PropertyName} 占位符,清晰表達(dá)意圖。
      自動(dòng)提取屬性值,生成結(jié)構(gòu)化數(shù)據(jù)。
      支持格式化說明符,如 {LoginTime:HH:mm}。
      即使沒有提供參數(shù),也不會(huì)拋出異常(會(huì)原樣輸出占位符)。

      // 異常處理的優(yōu)雅支持
      // 記錄異常是常見需求,Serilog 提供了專門的重載,讓異常日志既簡(jiǎn)潔又完整
      try
      {
          // ...
      }
      catch (Exception ex)
      {
          Log.Error(ex, "處理訂單 {OrderId} 失敗", orderId);
      }
      // 第一個(gè)參數(shù)是 Exception 對(duì)象,Serilog 會(huì)自動(dòng)捕獲堆棧跟蹤。
      // 后續(xù)參數(shù)用于填充消息模板中的屬性。
      // 生成的日志事件同時(shí)包含異常詳情和業(yè)務(wù)上下文。
      特性 如何體現(xiàn)“簡(jiǎn)潔易用”
      靜態(tài) Log 類 全局可用,無需實(shí)例化,減少樣板代碼
      統(tǒng)一方法簽名 所有日志級(jí)別使用相同模式,降低記憶負(fù)擔(dān)
      消息模板 結(jié)構(gòu)化日志 + 直觀語法,代碼可讀性強(qiáng)
      異常支持 一行代碼記錄異常和上下文
      異步/批量 通過 .Async() 包裝器輕松實(shí)現(xiàn),無需手動(dòng)線程管理
      豐富 Sink 配置簡(jiǎn)單,更換輸出目標(biāo)只需修改幾行代碼

      1.4 核心特點(diǎn):異步日志記錄

      Serilog 通過將日志寫入操作從應(yīng)用程序的主要執(zhí)行線程中分離出來,顯著提升了應(yīng)用程序的性能和響應(yīng)能力。

      異步非由 Serilog 核心庫直接實(shí)現(xiàn),而是通過 Serilog.Sinks.Async 這個(gè)專門的包來完成。特別適合高并發(fā)、高吞吐量的場(chǎng)景。

      在傳統(tǒng)的同步日志中,當(dāng)代碼執(zhí)行到Log.Information("...")時(shí),當(dāng)前線程必須等待日志被完全寫入目標(biāo)(如文件、數(shù)據(jù)庫、網(wǎng)絡(luò)等)后才能繼續(xù)執(zhí)行。如果日志目標(biāo)響應(yīng)慢(如網(wǎng)絡(luò)延遲、磁盤I/O瓶頸),這會(huì)直接阻塞業(yè)務(wù)線程,導(dǎo)致應(yīng)用性能下降。

      Serilog.Sinks.Async 在日志管道中引入了一個(gè)異步代理(Asynchronous Sink)。當(dāng)調(diào)用 Log.Information("...") 時(shí),日志事件(Log Event)會(huì)被快速地放入一個(gè)內(nèi)存中的隊(duì)列(通常是 BlockingCollection),然后調(diào)用線程立即返回,繼續(xù)執(zhí)行后續(xù)業(yè)務(wù)代碼。一個(gè)或多個(gè)后臺(tái)工作線程會(huì)從這個(gè)隊(duì)列中取出日志事件,并在后臺(tái)安全地將它們寫入最終的日志接收器(Sinks)。

      異步執(zhí)行帶來的好處:

      • 提升應(yīng)用性能與響應(yīng)速度

      減少主線程阻塞:這是最直接的好處。業(yè)務(wù)邏輯不再需要等待緩慢的I/O操作,大大縮短了請(qǐng)求處理時(shí)間,尤其是在高并發(fā)場(chǎng)景下效果顯著。

      平滑性能波動(dòng):即使日志目標(biāo)出現(xiàn)暫時(shí)性延遲,也不會(huì)立刻影響到應(yīng)用程序的響應(yīng)時(shí)間,因?yàn)槿罩臼录呀?jīng)“脫手”進(jìn)入隊(duì)列。

      • 配置簡(jiǎn)單,透明集成

      使用 Serilog.Sinks.Async 非常簡(jiǎn)單。只需在配置日志管道時(shí),將任何現(xiàn)有的 Sink(如 WriteTo.File(...))包裝在WriteTo.Async(...)中即可。例如:

      Log.Logger = new LoggerConfiguration()
          .WriteTo.Async(a => a.File("logs/myapp.txt")) // 將文件Sink包裝在Async中
          .CreateLogger();

      業(yè)務(wù)代碼中調(diào)用 Log.Information(...) 的方式完全不變,異步化對(duì)業(yè)務(wù)層是透明的。

      • 基于隊(duì)列的緩沖機(jī)制

      Serilog.Sinks.Async 內(nèi)部使用一個(gè)線程安全的隊(duì)列來暫存日志事件。

      這個(gè)隊(duì)列充當(dāng)了生產(chǎn)者-消費(fèi)者模型中的緩沖區(qū)。應(yīng)用程序線程是“生產(chǎn)者”,后臺(tái)線程是“消費(fèi)者”。

      隊(duì)列的大小可以配置(通過 AsyncOptions),允許用戶在內(nèi)存使用和日志丟失風(fēng)險(xiǎn)之間進(jìn)行權(quán)衡。

      • 可配置的背壓處理(Backpressure Handling)

      采用隊(duì)列的方式就會(huì)有一個(gè)隱患,當(dāng)日志產(chǎn)生速度遠(yuǎn)超后臺(tái)線程處理速度時(shí),隊(duì)列會(huì)不斷增長,可能導(dǎo)致內(nèi)存耗盡。

      然而,Serilog.Sinks.Async 提供了多種策略來應(yīng)對(duì)這種情況(通過 AsyncOptions 配置):

      Blocking(默認(rèn)):當(dāng)隊(duì)列滿時(shí),Log.Information() 調(diào)用會(huì)阻塞,直到隊(duì)列有空間。這保證了日志不丟失,但可能影響性能。
      DropWrite:當(dāng)隊(duì)列滿時(shí),新產(chǎn)生的日志事件會(huì)被直接丟棄。這保證了應(yīng)用性能,但犧牲了日志的完整性。
      OverflowAction:更高級(jí)的選項(xiàng),允許你定義更復(fù)雜的策略,如丟棄舊日志或觸發(fā)警報(bào)

      • 優(yōu)雅關(guān)閉與日志完整性

      當(dāng)應(yīng)用程序關(guān)閉時(shí),正確地處理異步日志至關(guān)重要,以確保隊(duì)列中所有待處理的日志都能被寫入。

      必須在程序退出前調(diào)用 Log.CloseAndFlush()。它會(huì)停止接收新日志,然后等待后臺(tái)線程將隊(duì)列中剩余的所有日志事件處理完畢,最后才返回。

      忽略此步驟是導(dǎo)致日志丟失的最常見原因。

      • 與結(jié)構(gòu)化日志的完美結(jié)合

      Serilog 的核心是結(jié)構(gòu)化日志(Structured Logging),即日志以帶有屬性的結(jié)構(gòu)化數(shù)據(jù)形式記錄,而非純文本。

      異步記錄與結(jié)構(gòu)化日志相得益彰。結(jié)構(gòu)化日志的序列化(如序列化為JSON)可能消耗CPU,異步化可以將這部分開銷也移出主線程。

      總的來說,Serilog 是構(gòu)建高性能、高響應(yīng)性 .NET 應(yīng)用程序日志方案的關(guān)鍵組件,尤其適用于Web API、高并發(fā)服務(wù)等對(duì)延遲敏感的場(chǎng)景。但對(duì)于日志量不大,對(duì)延遲不太敏感的場(chǎng)景,還是更推薦同步的,因?yàn)楫惒綗o法避免的會(huì)占用更多資源。

      1.5 核心特點(diǎn):豐富的配置方式

      Serilog 允許開發(fā)者根據(jù)項(xiàng)目類型、環(huán)境需求和團(tuán)隊(duì)習(xí)慣,選擇最適合的方式來設(shè)置日志管道(Logger Pipeline)。這種靈活性極大地提升了可維護(hù)性和適應(yīng)性。

      • 代碼配置(Code-based Configuration)

      這是最基礎(chǔ)、最靈活、也是最推薦的方式,通過 C# 代碼直接構(gòu)建 LoggerConfiguration 對(duì)象。

      特點(diǎn):

      完全控制:提供對(duì)日志配置的完全編程控制,可以執(zhí)行復(fù)雜的邏輯(如條件判斷、循環(huán)、讀取環(huán)境變量等)。
      編譯時(shí)檢查:得益于強(qiáng)類型,配置錯(cuò)誤通常能在編譯時(shí)被發(fā)現(xiàn)。
      易于調(diào)試:可以在配置代碼中設(shè)置斷點(diǎn),逐步檢查配置過程。
      動(dòng)態(tài)性:可以根據(jù)運(yùn)行時(shí)條件(如環(huán)境變量、命令行參數(shù))動(dòng)態(tài)調(diào)整配置。

      核心 API:

      LoggerConfiguration():創(chuàng)建配置構(gòu)建器。
      .MinimumLevel.*():設(shè)置全局或特定來源的最低日志級(jí)別(如 .MinimumLevel.Debug())。
      .WriteTo.*():添加日志接收器(Sinks),指定日志輸出目標(biāo)(如文件、控制臺(tái)、數(shù)據(jù)庫)。
      .Filter.*():添加過濾器,決定哪些日志事件應(yīng)被處理或丟棄。
      .Enrich.*():添加“豐富器”(Enrichers),為日志事件自動(dòng)添加上下文信息(如機(jī)器名、進(jìn)程ID、線程ID、請(qǐng)求ID)。
      .Destructure.*():配置對(duì)象解構(gòu)策略,控制復(fù)雜對(duì)象如何被序列化到日志中。
      .CreateLogger():最終生成 ILogger 實(shí)例并賦值給 Log.Logger。

      如下示例詳解:

      Log.Logger = new LoggerConfiguration()
          .MinimumLevel.Debug() // 全局設(shè)置日志的最低輸出級(jí)別為 Debug
          .MinimumLevel.Override("Microsoft", LogEventLevel.Information) // Microsoft.* 相關(guān)的日志只有 Information 及以上才會(huì)輸出
          .Enrich.FromLogContext() // 添加 Serilog 的結(jié)構(gòu)化上下文,允許在特定作用域內(nèi)添加結(jié)構(gòu)化數(shù)據(jù)(比如用戶ID、請(qǐng)求ID)
          .Enrich.WithMachineName() // 自動(dòng)添加當(dāng)前機(jī)器名(Environment.MachineName)
          .Enrich.WithThreadId() // 添加當(dāng)前線程 ID,便于多線程/異步調(diào)試時(shí)追蹤日志來源
          .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}") // 將日志寫入控制臺(tái)(stdout)示例:[14:23:01 INF] User 'alice' logged in successfully.
          .WriteTo.File("logs/myapp.txt", rollingInterval: RollingInterval.Day) // 每天生成一個(gè)新的日志文件,這需要引用 Serilog.Sinks.File 和 Serilog.Sinks.RollingFile 包
          .WriteTo.Async(a => a.Elasticsearch(new ElasticsearchSinkOptions(new Uri("http://localhost:9200"))
          { // 使用 .WriteTo.Async() 包裝 Elasticsearch 輸出,使其異步寫入,避免阻塞主線程
              AutoRegisterTemplate = true
          }))
          // 使用 Filter.ByExcluding 排除某些日志事件
          // Matching.FromSource("Microsoft.AspNetCore.StaticFiles"):匹配來自 Microsoft.AspNetCore.StaticFiles 命名空間的日志源
          .Filter.ByExcluding(Matching.FromSource("Microsoft.AspNetCore.StaticFiles"))
          .CreateLogger();
      • JSON 配置(JSON Configuration)

      Serilog 支持從標(biāo)準(zhǔn)的 .NET 配置文件(如 appsettings.json)中讀取配置。這對(duì)于希望將配置與代碼分離的項(xiàng)目非常有用。

      特點(diǎn):

      配置與代碼分離:配置信息獨(dú)立于代碼,便于非開發(fā)人員(如運(yùn)維)修改。
      環(huán)境友好:可以利用 appsettings.Development.json、appsettings.Production.json 等文件實(shí)現(xiàn)環(huán)境差異化配置。
      易于部署:部署時(shí)只需替換配置文件即可調(diào)整日志行為,無需重新編譯。

      如何實(shí)現(xiàn)?

      首先安裝 Serilog.Settings.Configuration NuGet 包;
      在 appsettings.json 中定義 Serilog 配置節(jié)點(diǎn);
      在程序啟動(dòng)時(shí),使用 ReadFrom.Configuration(IConfiguration) 方法讀取。

      配置示例:

      {
        "Serilog": {
          "Using": [ "Serilog.Sinks.Console", "Serilog.Sinks.File" ], // 指定使用的Sinks包
          "MinimumLevel": "Debug",
          "Override": {
            "Microsoft": "Information",
            "System": "Warning"
          },
          "WriteTo": [
            {
              "Name": "Console",
              "Args": {
                "outputTemplate": "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}"
              }
            },
            {
              "Name": "File",
              "Args": {
                "path": "logs/myapp.txt",
                "rollingInterval": "Day"
              }
            }
          ],
          "Enrich": [ "FromLogContext", "WithMachineName", "WithThreadId" ],
          "Destructure": [
            {
              "Name": "ToMaximumDepth",
              "Args": { "maximumDestructuringDepth": 4 }
            }
          ]
        }
      }
      var configuration = new ConfigurationBuilder()
          .AddJsonFile("appsettings.json")
          .Build();
      
      Log.Logger = new LoggerConfiguration()
          .ReadFrom.Configuration(configuration) // 從 IConfiguration 讀取 Serilog 配置
          .CreateLogger();
      • App.config / Web.config(XML Configuration)

      對(duì)于傳統(tǒng)的 .NET Framework 應(yīng)用程序(非 .NET Core),Serilog 也支持通過 app.config 或 web.config 文件進(jìn)行配置。類似于 JSON 配置,但使用 XML 語法。

      配置方法就是,安裝 Serilog.Settings.AppSettings NuGet 包。在 .config 文件的 <appSettings> 節(jié)點(diǎn)中添加以 serilog: 為前綴的鍵值對(duì)。

      配置示例:

      <configuration>
        <appSettings>
          <add key="serilog:minimum-level" value="Debug" />
          <add key="serilog:write-to:Console" />
          <add key="serilog:write-to:File.path" value="logs\myapp.txt" />
          <add key="serilog:enrich:WithMachineName" />
        </appSettings>
      </configuration>
      Log.Logger = new LoggerConfiguration()
          .ReadFrom.AppSettings() // 從AppSettings讀取
          .CreateLogger();
      • 環(huán)境變量配置

      Serilog 可以直接從環(huán)境變量中讀取配置,這在容器化(Docker, Kubernetes)和云原生環(huán)境中非常實(shí)用

      特點(diǎn):

      云原生友好:容器和云平臺(tái)(如 Azure, AWS)通常通過環(huán)境變量傳遞配置。
      動(dòng)態(tài)注入:無需修改代碼或配置文件,通過部署腳本或平臺(tái)設(shè)置即可改變?nèi)罩拘袨椤?br>與 appsettings.json 結(jié)合:環(huán)境變量可以覆蓋 appsettings.json 中的值。

      實(shí)現(xiàn)方式:

      使用 Serilog.Settings.Configuration 包時(shí),IConfiguration 本身支持從環(huán)境變量讀取。
      環(huán)境變量的名稱需要遵循特定的格式來映射到 JSON 結(jié)構(gòu)。例如,要覆蓋 appsettings.json 中的 Serilog:MinimumLevel,可以設(shè)置環(huán)境變量 Serilog__MinimumLevel=Warning(雙下劃線 __ 表示層級(jí))。

      • 組合與優(yōu)先級(jí)

      Serilog 允許組合多種配置方式,通常遵循一定的優(yōu)先級(jí)。

      代碼配置:最高優(yōu)先級(jí),直接在代碼中設(shè)置的值會(huì)覆蓋其他來源。
      環(huán)境變量:通常優(yōu)先級(jí)高于配置文件中的靜態(tài)值。
      JSON / XML 配置文件:基礎(chǔ)配置來源。
      默認(rèn)值:如果以上都沒有設(shè)置,則使用 Serilog 的內(nèi)置默認(rèn)值

      推薦配置方式:

      // 1. 構(gòu)建 IConfiguration,從多個(gè)來源讀取(包括環(huán)境變量)
      var configuration = new ConfigurationBuilder()
          .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) // 作為基礎(chǔ)配置 reloadOnChange:?jiǎn)⒂门渲脽嶂剌d
          .AddJsonFile($"appsettings.{environment}.json", optional: true) // optional: true 允許特定環(huán)境文件不存在,此時(shí)將回退到基礎(chǔ)配置
          .AddEnvironmentVariables() // 允許環(huán)境變量覆蓋,在 Docker、Kubernetes、Azure App Service 等云平臺(tái)中,環(huán)境變量是傳遞配置的首選方式
          .Build();
      
      Log.Logger = new LoggerConfiguration()
          .ReadFrom.Configuration(configuration) // 從配置文件和環(huán)境變量加載基礎(chǔ)配置
          .MinimumLevel.Override("MyApp.Sensitive", LogEventLevel.Verbose) // 允許在代碼中強(qiáng)制覆蓋某些關(guān)鍵部分的日志行為,即“安全護(hù)欄”,防止因配置錯(cuò)誤導(dǎo)致的嚴(yán)重后果
          .CreateLogger();

      關(guān)于 .AddEnvironmentVariables() 配置:

      云原生友好:在 Docker、Kubernetes、Azure App Service 等云平臺(tái)中,環(huán)境變量是傳遞配置的首選方式。它安全(避免將敏感信息寫入代碼或配置文件)、靈活(通過部署腳本或平臺(tái)界面即可修改)且與代碼解耦。

      最高優(yōu)先級(jí)覆蓋:在配置提供程序的加載順序中,AddEnvironmentVariables() 通常在最后,因此它的值優(yōu)先級(jí)最高,可以覆蓋 appsettings.json 中的任何設(shè)置。

      示例場(chǎng)景:

      基礎(chǔ)配置 appsettings.json 中設(shè)置 Serilog:MinimumLevel=Information。
      運(yùn)維人員在生產(chǎn)環(huán)境中發(fā)現(xiàn)一個(gè)偶發(fā)問題,需要臨時(shí)開啟 Debug 日志。
      無需修改任何代碼或配置文件,只需在服務(wù)器或容器中設(shè)置環(huán)境變量 Serilog__MinimumLevel=Debug。
      應(yīng)用重啟后(或配合熱重載),日志級(jí)別立即生效,問題排查完畢后,移除環(huán)境變量即可恢復(fù)原狀。零代碼變更,快速響應(yīng)。 

      1.6 核心特點(diǎn):日志豐富(Enrichment)

      日志豐富是 Serilog 區(qū)別于許多其他 .NET 日志框架(如內(nèi)置的 ILogger)的一個(gè)關(guān)鍵優(yōu)勢(shì)。

      它允許在不修改代碼或日志語句的情況下,為日志事件自動(dòng)添加上下文信息。這極大地提升了日志的可讀性、可追溯性和診斷能力。

      簡(jiǎn)單來說,Enrichment 就是“給日志事件自動(dòng)添加額外的、有價(jià)值的上下文信息”

      Serilog 的 LoggerConfiguration 允許通過 .Enrich.With(...) 方法注冊(cè)一個(gè)或多個(gè)豐富器(Enricher)

      一個(gè)豐富器是一個(gè)實(shí)現(xiàn)了 ILogEventEnricher 接口的對(duì)象,它有一個(gè) Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory) 方法。Serilog 會(huì)在每條日志事件被處理時(shí)調(diào)用所有注冊(cè)的豐富器。

      Serilog 內(nèi)置的豐富器(Built-in Enrichers)如下:

      Enrich.WithProperty()
      // 為所有日志事件添加一個(gè)靜態(tài)的、固定的屬性。
      // 場(chǎng)景:添加應(yīng)用名稱、版本號(hào)、環(huán)境(Development/Production)等。
      // 例如:.Enrich.WithProperty("Application", "MyWebApp") // 每條日志都會(huì)自動(dòng)包含 "Application": "MyWebApp"
      
      Enrich.WithMachineName() (Serilog.Enrichers.Environment)
      // 功能:添加運(yùn)行應(yīng)用的機(jī)器名稱。
      // 場(chǎng)景:在多服務(wù)器部署中,快速定位日志來源機(jī)器。
      
      Enrich.WithEnvironmentUserName() / Enrich.WithEnvironmentName() (Serilog.Enrichers.Environment)
      // 功能:添加當(dāng)前操作系統(tǒng)用戶名和環(huán)境變量(如 ASPNETCORE_ENVIRONMENT)。
      // 場(chǎng)景:了解運(yùn)行環(huán)境和用戶。
      
      Enrich.WithThreadId() / Enrich.WithThreadName() (Serilog.Enrichers.Thread)
      // 功能:添加當(dāng)前線程 ID 或名稱。
      // 場(chǎng)景:在多線程應(yīng)用中追蹤日志的執(zhí)行線程。
      
      Enrich.WithProcessId() / Enrich.WithProcessName() (Serilog.Enrichers.Process)
      // 功能:添加進(jìn)程 ID 和進(jìn)程名稱。
      // 場(chǎng)景:區(qū)分同一機(jī)器上運(yùn)行的多個(gè)實(shí)例。
      
      Enrich.WithDemystifiedStackTraces() (Serilog.Exceptions)
      // 功能:當(dāng)記錄異常時(shí),提供更清晰、去除了編譯器生成代碼的堆棧跟蹤(“去神秘化”)。
      // 場(chǎng)景:讓異常堆棧更易讀。
      
      Enrich.WithClientIp() / Enrich.WithClientAgent() (Serilog.AspNetCore)
      // 功能:在 ASP.NET Core 應(yīng)用中,自動(dòng)從 HTTP 上下文中提取客戶端 IP 地址和 User-Agent。
      // 場(chǎng)景:Web 應(yīng)用必備,用于安全審計(jì)和用戶行為分析。
      
      Enrich.WithRequestHeader() / Enrich.WithRequestProperty() (Serilog.AspNetCore)
      // 功能:從 HTTP 請(qǐng)求頭或?qū)傩灾刑崛√囟ㄖ底鳛槿罩緦傩浴?// 例如
      .Enrich.WithRequestHeader("X-Correlation-ID") // 提取關(guān)聯(lián)ID
      .Enrich.WithRequestProperty("TenantId")      // 提取路由或中間件設(shè)置的屬性
      
      Enrich.FromLogContext() (極其重要!)
      // 功能:這是 Serilog 最強(qiáng)大的豐富器之一。它允許你在代碼的特定作用域內(nèi)動(dòng)態(tài)地添加上下文信息。
      // 機(jī)制:使用 LogContext.PushProperty("PropertyName", value)。
      // 作用域:通過 using 語句創(chuàng)建一個(gè)作用域,該作用域內(nèi)的所有日志都會(huì)自動(dòng)包含 PushProperty 添加的屬性。
      // 例如:
      using (LogContext.PushProperty("TransactionId", transactionId))
      using (LogContext.PushProperty("UserId", userId))
      {
          Log.Information("開始處理交易");
          // ... 更多操作 ...
          Log.Information("交易處理完成");
          // 這兩條日志都自動(dòng)包含 TransactionId 和 UserId
      }
      // 作用域結(jié)束后,這些屬性自動(dòng)移除
      // 場(chǎng)景:處理用戶請(qǐng)求、數(shù)據(jù)庫事務(wù)、消息處理等需要貫穿整個(gè)操作流程的上下文。

      如何試下自定義豐富器?

      實(shí)現(xiàn) ILogEventEnricher 接口。然后在 Enrich 方法中,使用 propertyFactory 創(chuàng)建 LogEventProperty,最后并添加到 logEvent.Properties 中。

      如下示例:

      public class UtcTimestampEnricher : ILogEventEnricher
      {
          public void Enrich(LogEvent logEvent, ILogEventPropertyFactory propertyFactory)
          {
              var utcNow = DateTimeOffset.UtcNow;
              var property = propertyFactory.CreateProperty("UtcTimestamp", utcNow);
              logEvent.AddPropertyIfAbsent(property);
          }
      }
      
      // 使用
      Log.Logger = new LoggerConfiguration()
          .Enrich.With<UtcTimestampEnricher>()
          .WriteTo.Console()
          .CreateLogger();

      Enrichment 帶來的優(yōu)勢(shì)可以概括為:

      減少代碼重復(fù):無需在每個(gè)日志語句中手動(dòng)添加通用信息。
      提高日志質(zhì)量:確保關(guān)鍵上下文(如 RequestId、UserId)不會(huì)被遺漏。
      非侵入性:業(yè)務(wù)代碼更干凈,日志語句更簡(jiǎn)潔。
      動(dòng)態(tài)上下文:通過 LogContext 支持基于作用域的動(dòng)態(tài)豐富。
      易于擴(kuò)展:可以輕松添加新的豐富器或自定義邏輯。
      強(qiáng)大的診斷能力:豐富的上下文信息使得在海量日志中追蹤問題、分析用戶行為變得非常高效。

      1.7 核心特點(diǎn):對(duì)象解構(gòu)(Destructuring)

      簡(jiǎn)單來說,對(duì)象解構(gòu)是指 Serilog 在記錄日志時(shí),能夠深入分析(introspect)你傳遞給日志方法的復(fù)雜對(duì)象(如自定義類、集合、匿名對(duì)象等),并將它們的內(nèi)部屬性和值提取出來,以結(jié)構(gòu)化的方式(通常是 JSON 格式)記錄到日志中,而不是僅僅記錄對(duì)象的類型名稱或 ToString() 的結(jié)果。

      幾個(gè)主要特點(diǎn)如下:

      • 深度屬性提取(Deep Property Extraction)

      Serilog 不僅能解構(gòu)對(duì)象的直接屬性,還能遞歸地解構(gòu)嵌套對(duì)象。

      例如,如果 User 類中有一個(gè) Address 屬性(也是一個(gè)復(fù)雜對(duì)象),解構(gòu)后 Address 的屬性(如 Street, City)也會(huì)被完整記錄。

      public class Address { public string Street { get; set; } public string City { get; set; } }
      public class User { public int Id { get; set; } public string Name { get; set; } public Address HomeAddress { get; set; } }
      
      var user = new User {
          Id = 123,
          Name = "Alice",
          HomeAddress = new Address { Street = "123 Main St", City = "Wonderland" }
      };
      logger.LogInformation("User created: {User}", user);
      
      // 解構(gòu)后的 JSON 片段:
      // "User": {
      //   "Id": 123,
      //   "Name": "Alice",
      //   "HomeAddress": {
      //     "Street": "123 Main St",
      //     "City": "Wonderland"
      //   }
      // }
      • 集合解構(gòu)(Collection Destructuring)

      數(shù)組、列表、字典等集合類型也會(huì)被解構(gòu)。
      數(shù)組和列表會(huì)被轉(zhuǎn)換為 JSON 數(shù)組。
      字典會(huì)被轉(zhuǎn)換為 JSON 對(duì)象,其鍵值對(duì)成為對(duì)象的屬性。

      var tags = new List<string> { "urgent", "bug", "frontend" };
      var metadata = new Dictionary<string, object> { { "Priority", 1 }, { "AssignedTo", "Bob" } };
      logger.LogInformation("Task updated with tags: {Tags} and metadata: {Metadata}", tags, metadata);
      
      // 解構(gòu)后的 JSON 片段:
      // "Tags": ["urgent", "bug", "frontend"],
      // "Metadata": { "Priority": 1, "AssignedTo": "Bob" }
      • 匿名對(duì)象支持(Anonymous Object Support)

      可以直接傳入匿名對(duì)象,Serilog 會(huì)完美地將其解構(gòu)并作為日志的一部分。

      logger.LogInformation("Operation completed", new { DurationMs = 45, RecordsProcessed = 100 });
      // "DurationMs": 45, "RecordsProcessed": 100
      • 性能考量與控制(Performance and Control)

      潛在開銷:深度解構(gòu)一個(gè)非常龐大或深層嵌套的對(duì)象可能會(huì)帶來性能開銷(CPU、內(nèi)存、日志大小)。

      解構(gòu)策略(Destructuring Policies):Serilog 允許你通過 Destructure 配置來精細(xì)化控制解構(gòu)行為:

      ??ByTransforming<T>(...):為特定類型 T 定義自定義的解構(gòu)邏輯。例如,你可能只想記錄 User 對(duì)象的 Id 和 Name,而忽略敏感的 PasswordHash。.Destructure.ByTransforming<User>(user => new { user.Id, user.Name })
      ??ByIgnoringPropertiesOfType<T>():忽略特定類型的屬性(例如,忽略所有 byte[] 或 Stream 類型的屬性,因?yàn)樗鼈儾贿m合日志)。
      ??ByIgnoringMembers(...):忽略特定成員(屬性或字段)。
      ??MaximumDepth(int depth):設(shè)置解構(gòu)的最大遞歸深度,防止無限遞歸或過深的結(jié)構(gòu)。
      ??MaximumStringLength(int length):限制字符串屬性的最大長度,防止超長日志條目。

      @ 符號(hào)(The @ Operator):這是一個(gè)非常強(qiáng)大的內(nèi)聯(lián)控制語法在日志消息的占位符前加上 @,可以強(qiáng)制對(duì)該位置的對(duì)象進(jìn)行解構(gòu),即使它是一個(gè)簡(jiǎn)單的值類型或字符串。

      更重要的是,@ 是解構(gòu)的“開關(guān)”。如果你不希望某個(gè)復(fù)雜對(duì)象被解構(gòu),可以使用 $ 符號(hào)(但 Serilog 實(shí)際上是用 @ 來 啟用 解構(gòu),不加 @ 則可能只記錄 ToString())。

      在 Serilog 中,想要確保對(duì)象被解構(gòu),在占位符前使用 @ 就可以了。

      var user = new User { ... };
      
      // 推薦寫法,明確要求解構(gòu)
      logger.LogInformation("User action: {@User}", user);
      
      // 如果不加 @,且 User 類沒有重寫 ToString(),可能只記錄類型名
      logger.LogInformation("User action: {User}", user); // 可能不是你想要的!
      
      // 使用 @ 也可以解構(gòu)集合或值類型(雖然對(duì)值類型意義不大)
      logger.LogInformation("Scores: {@Scores}", new[] { 95, 87, 92 });
      • 與結(jié)構(gòu)化日志的協(xié)同(Synergy with Structured Logging)

      對(duì)象解構(gòu)是 Serilog 實(shí)現(xiàn)真正結(jié)構(gòu)化日志的核心支柱。

      解構(gòu)后的數(shù)據(jù)是結(jié)構(gòu)化的 JSON 對(duì)象,而不是難以解析的文本。這使得日志可以被現(xiàn)代日志聚合和分析工具(如 Seq, Elasticsearch, Splunk, Datadog)高效地索引、搜索、過濾和可視化。

      這樣就可以輕松地根據(jù) User.Name 條件,來查詢 Alice,其中 Status 為 Failed 的日志,這在純文本日志中是幾乎不可能高效完成的。

      Serilog 的對(duì)象解構(gòu)功能將日志記錄從簡(jiǎn)單的文本記錄提升到了結(jié)構(gòu)化數(shù)據(jù)記錄的新高度。它通過自動(dòng)、深度地分析和提取復(fù)雜對(duì)象的內(nèi)部結(jié)構(gòu),生成富含上下文的 JSON 數(shù)據(jù),使得日志不再是難以解讀的“黑盒”,而是可以被程序高效處理和分析的寶貴資產(chǎn)。熟練掌握 @ 操作符和 Destructure 配置策略,是發(fā)揮 Serilog 強(qiáng)大威力的關(guān)鍵。

      1.8 幾個(gè)適用場(chǎng)景

      • 微服務(wù)架構(gòu)

      每個(gè)微服務(wù)獨(dú)立記錄日志,通過集中式日志系統(tǒng)(如 Seq、Elasticsearch)進(jìn)行聚合,便于跨服務(wù)的請(qǐng)求追蹤和問題排查。

      • 云原生應(yīng)用

      與 Kubernetes、Docker 等容器化平臺(tái)無縫集成,通過 WriteTo.Console() 將日志輸出到標(biāo)準(zhǔn)輸出,被容器編排平臺(tái)自動(dòng)捕獲

      • 需要復(fù)雜日志分析的系統(tǒng)

      需要對(duì)日志進(jìn)行聚合、分析和可視化(如使用 Seq 的查詢語言),適合需要從日志中提取結(jié)構(gòu)化數(shù)據(jù)進(jìn)行業(yè)務(wù)分析的場(chǎng)景。

      • 高性能要求的應(yīng)用

      異步日志記錄機(jī)制確保日志不會(huì)成為性能瓶頸,特別適合高并發(fā)、高吞吐量的系統(tǒng)。

      • 與現(xiàn)代監(jiān)控系統(tǒng)集成

      與 Seq、Elasticsearch、Splunk、DataDog 等監(jiān)控平臺(tái)無縫集成,便于構(gòu)建完整的可觀測(cè)性系統(tǒng)。

      二、簡(jiǎn)單列一下有哪些 Serilog Sink 類型

      文件系統(tǒng) Sink、控制臺(tái)與調(diào)試 Sinks、集中式日志與分析平臺(tái) Sinks、消息隊(duì)列 Sinks、數(shù)據(jù)庫 Sinks、其他 Sinks 等等。

      Serilog的強(qiáng)大之處在于其Sink的靈活性和可組合性,一個(gè)典型的生產(chǎn)環(huán)境配置可能會(huì)結(jié)合多種分類的Sink。

      后續(xù)博主將繼續(xù)以 Sink 的各個(gè)類型為基礎(chǔ),進(jìn)行實(shí)踐并輸出實(shí)踐記錄,有興趣可持續(xù)關(guān)注。

      posted @ 2025-10-26 22:02  橙子家  閱讀(519)  評(píng)論(6)    收藏  舉報(bào)
      主站蜘蛛池模板: 天堂mv在线mv免费mv香蕉| 亚洲无线观看国产精品| 国产成人综合网亚洲第一| 亚洲日韩AV秘 无码一区二区| 2021亚洲va在线va天堂va国产 | 欧美精品videosbestsex日本 | AV最新高清无码专区| 动漫AV纯肉无码AV电影网| 免费全部高h视频无码| 国产av一区二区三区综合| 国内精品久久久久影院网站| 91久久天天躁狠狠躁夜夜| 国产对白老熟女正在播放| jizzjizz少妇亚洲水多| 国产视频最新| 国产极品美女网站在线观看| 国产成人午夜在线视频极速观看| 边添小泬边狠狠躁视频| 国产成人啪精品午夜网站| 午夜无码免费福利视频网址| 亚洲天堂激情av在线| 亚洲av无码精品蜜桃| 亚洲精品国产第一区二区| 亚洲无av码一区二区三区| 99久热在线精品视频| 久久国产自偷自免费一区| 久久精品国产亚洲av麻| 国产日韩综合av在线| 临沂市| 一区二区三区黄色一级片| 国产精品中文一区二区| 日韩一区二区三区日韩精品| 亚洲精品国产综合久久一线| 网友自拍视频一区二区三区| 国产婷婷综合在线视频| 日韩精品一区二区三区在| 国产精品一码二码三码| 人妻少妇邻居少妇好多水在线| 中文字幕99国产精品| 野花香视频在线观看免费高清版| 国产男女黄视频在线观看|