使用記錄器新增自訂記錄訊息

已完成

.NET 提供可用來記錄自訂遙測資料的 API。 OpenTelemetry 可以匯出該資料。

在本單元中,您將了解如何撰寫將事件傳送至結構化記錄的有效程式碼。

ILogger 物件

當您根據範本建立專案,或將現有的專案新增至 .NET Aspire 協調流程時,.NET Aspire 工具會自動設定 OpenTelemetry API。 當您想要記錄遙測時,您不需要建立自己的記錄、計量或追蹤物件。 相反地,您可以在微服務中使用相依性插入來擷取它們。

例如,在下列 BasketService 類別中,類別宣告中包含 ILogger 物件。 您可以在類別中的任何位置使用該記錄器來寫入事件:

public class BasketService(
    IBasketRepository repository,
    ILogger<BasketService> logger) : Basket.BasketBase
{
    [AllowAnonymous]
    public override async Task<CustomerBasketResponse> GetBasket(
	    GetBasketRequest request, ServerCallContext context)
    {
        var userId = context.GetUserIdentity();

        // Use the logger to write events
        if (logger.IsEnabled(LogLevel.Debug))
        {
            logger.LogDebug("Begin GetBasketById call from method {Method} for basket id {userId}", context.Method, userId);
        }

        var data = await repository.GetBasketAsync(userId);

        return new();
    }
}

有效率的記錄

記錄有助於讓您的微服務可觀察。 當應用程式經過測試、暫存並部署至生產環境時,完整的記錄程式碼可以快速診斷錯誤或瓶頸。 因此,人們會想記錄所有内容。 不過,儘管記錄速度很快,但仍需成本,所以您應該留意以有效率地進行記錄。

廠商通常會根據其內嵌的資料量來計費應用程式效能管理 (APM) 系統。 為您的訊息選取適當的記錄層級和預設集合層級,可能對每月的帳單產生重大的影響。 記錄收集層級可以根據每個提供者設定,這通常是 ILogger<T> 中使用的類型名稱。

每次記錄時,請使用下列技術:

  • 檢查您要使用的記錄層級已啟用。 可用的層級包括資訊、警告、錯誤和危急。 系統管理員可以在測試、暫存和部署至生產環境時啟用不同的層級。 記錄輸出是透過 IConfiguration 來控制,通常是使用 appsettings.json 或環境變數。
  • 請避免記錄訊息中的字串內插補點。 差補字串是以 $ 符號定義,即使您選擇的記錄層級未啟用,也會進行評估。 請改用記錄方法,例如 LogInformation()LogDebug(),並在引數清單中傳遞參數。
  • 使用編譯時間來源產生來進一步最佳化記錄效能,並為每個記錄訊息建立唯一識別碼,這在查詢 APM 中的記錄訊息時很有用。

編譯時間記錄來源產生

使用 ILogger 物件編譯時間來源產生,由於只會執行一次字串分析,而不是在每個記錄要求上執行,因此可以降低記錄成本。 它也包含每種記錄訊息類型的識別碼。 若要使用這項技術,請使用記錄參數定義部分記錄方法,並將 LoggerMessageAttribute 套用至它們。 .NET 會在編譯程式碼時自動產生完整的記錄方法。

請記住,在 .NET Aspire 中,您不需要建立 ILogger,而是可以從相依性插入取得它:

public partial class BasketService(
    IBasketRepository repository,
    ILogger<BasketService> logger) : Basket.BasketBase
{
    [LoggerMessage(
        EventId = 0,
        Level = LogLevel.Information,
        Message = "Obtaining a basket from method {Method} for basket {basketId}")]
    public partial void LogGetBasket(string Method, int basketId);
}

深入了解