簡體   English   中英

有沒有辦法用 Serilog 提供自定義屬性格式?

[英]Is there a way to provide custom property formatting with Serilog?

我有一個BackgroundTask類,我將它設置為在事情發生時記錄事件,例如任務完成時。 例如,對於Success案例,我調用Log.Verbose("{Task} completed successfully", this); 我的默認ToString()包括進度,但對於已完成的任務,我們知道它是 100%,所以我想忽略它。 我知道對於數字類型,您可以傳入自定義格式說明符字符串(例如"{IntProperty:p5}" ,這會將我的 int 呈現為帶有 5 個小數位的百分比),並且我希望能夠執行相同的操作,例如Log.Information("{Task:Name}", this) ,它會將"Name"傳遞到我的ToString()方法中。

我嘗試添加許多不同的方法,例如添加ToString()的(不接受任何內容、字符串、字符串和IFormatProvider )、實現IFormattable 、強制字符串化等,但似乎沒有任何效果。 我可以看到 Serilog 正確解析了我的格式字符串:( PropertyBinder.csConstructNamedProperties()第 111 行) Serilog 代碼的調試視圖

這調用了ConstructProperty() ,它只是忽略了令牌的Format屬性,這解釋了為什么它被忽略了,但我想知道是否有一種我沒有想到的方法可以工作。

PS是的,我知道我可以做幾個選擇,但我寧願不做這些:

  1. 使用自定義解構器或自己手動將屬性提取為匿名類型 - 這實質上破壞了原始對象,這正是我不想要的(我仍然希望將原始值存儲為屬性)。 例如Log.Information("{Task}", new {Name = this.Name, Id = this.Id});
  2. 使用我自己的格式字符串手動調用ToString() - 與 (1) 相同,這會破壞原始文件,並意味着它不會與所有信息一起存儲。 例如Log.Information("{Task}", this.ToString("Custom Format"));
  3. 在將它傳遞到 Serilog 之前,在我的對象上創建一個屬性,例如ToStringFormat - 這似乎是不好的做法,只會增加額外的混亂,更不用說並發問題了。 例如this.Format = "Custom FOrmat"; Log.Information("{Task}", this); this.Format = "Custom FOrmat"; Log.Information("{Task}", this);

這是由於 Serilog 管道中的捕獲格式化之間的分離。

為了在渲染到接收器時處理像:X這樣的格式字符串,實現IFormattable的原始對象需要可用。

但是,因為接收器通常異步處理事件,Serilog 不能確定任何給定的記錄對象是線程安全的,因此在使用ToString()記錄的時間/站點捕獲任何未知類型。

為了解決這個問題,你需要告訴 Serilog 你的Point類是一個(基本上不可變的)值類型:

    .Destructure.AsScalar(typeof(Point))

當記錄器被配置時。 然后,您可以在Point上實現IFormattable並在模板中使用{Point:X}等。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM