Bagikan melalui


Panduan pengelogan untuk penulis pustaka .NET

Sebagai penulis pustaka, mengekspos pengelogan adalah cara yang bagus untuk memberi konsumen wawasan tentang pekerjaan dalam pustaka Anda. Panduan ini membantu Anda mengekspos pengelogan dengan cara yang konsisten dengan pustaka dan kerangka kerja .NET lainnya. Ini juga membantu Anda menghindari hambatan performa umum yang mungkin tidak jelas.

Kapan menggunakan ILoggerFactory antarmuka

Saat menulis pustaka yang memancarkan log, Anda memerlukan ILogger objek untuk merekam log. Untuk mendapatkan objek tersebut, API Anda dapat menerima ILogger<TCategoryName> parameter, atau dapat menerima ILoggerFactory setelah itu Anda memanggil ILoggerFactory.CreateLogger. Pendekatan mana yang harus disukai?

  • Ketika Anda memerlukan objek pengelogan yang dapat diteruskan ke beberapa kelas sehingga semuanya dapat memancarkan log, gunakan ILoggerFactory. Disarankan agar setiap kelas membuat log dengan kategori terpisah, bernama sama dengan kelas . Untuk melakukan ini, Anda memerlukan pabrik untuk membuat objek unik ILogger<TCategoryName> untuk setiap kelas yang memancarkan log. Contoh umum termasuk API titik masuk publik untuk pustaka atau konstruktor publik jenis yang mungkin membuat kelas pembantu secara internal.

  • Ketika Anda memerlukan objek pengelogan yang hanya digunakan di dalam satu kelas dan tidak pernah dibagikan, gunakan ILogger<TCategoryName>, di mana TCategoryName adalah jenis yang menghasilkan log. Contoh umum dari ini adalah konstruktor untuk kelas yang dibuat oleh injeksi dependensi.

Jika Anda merancang API publik yang harus tetap stabil dari waktu ke waktu, perlu diingat bahwa Anda mungkin ingin merefaktor implementasi internal Anda di masa mendatang. Bahkan jika kelas tidak membuat jenis pembantu internal pada awalnya, itu mungkin berubah seiring berkembangnya kode. Menggunakan ILoggerFactory akomodir membuat objek baru ILogger<TCategoryName> untuk kelas baru apa pun tanpa mengubah API publik.

Untuk informasi selengkapnya, lihat Bagaimana aturan pemfilteran diterapkan.

Lebih suka pengelogan yang dihasilkan sumber

ILogger API mendukung dua pendekatan untuk menggunakan API. Anda dapat memanggil metode seperti LoggerExtensions.LogError dan LoggerExtensions.LogInformation, atau Anda dapat menggunakan generator sumber pengelogan untuk menentukan metode pengelogan yang sangat ditik. Untuk sebagian besar situasi, generator sumber direkomendasikan karena menawarkan performa yang unggul dan pengetikan yang lebih kuat. Ini juga mengisolasi masalah khusus pengelogan seperti templat pesan, ID, dan tingkat log dari kode panggilan. Pendekatan yang dihasilkan non-sumber terutama berguna untuk skenario di mana Anda bersedia menyerahkan keuntungan tersebut untuk membuat kode lebih ringkas.

using Microsoft.Extensions.Logging;

namespace Logging.LibraryAuthors;

internal static partial class LogMessages
{
    [LoggerMessage(
        Message = "Sold {Quantity} of {Description}",
        Level = LogLevel.Information)]
    internal static partial void LogProductSaleDetails(
        this ILogger logger,
        int quantity,
        string description);
}

Kode sebelumnya:

  • partial class Mendefinisikan bernama LogMessages, sehingga static dapat digunakan untuk menentukan metode ekstensi pada jenis .ILogger
  • Menghias LogProductSaleDetails metode ekstensi dengan LoggerMessage atribut dan Message templat.
  • Menyatakan LogProductSaleDetails, yang memperluas ILogger dan menerima quantity dan description.

Tip

Anda dapat melangkah ke kode yang dihasilkan sumber selama penelusuran kesalahan, karena merupakan bagian dari rakitan yang sama dengan kode yang memanggilnya.

Gunakan IsEnabled untuk menghindari evaluasi parameter yang mahal

Mungkin ada situasi di mana mengevaluasi parameter mahal. Memperluas pada contoh sebelumnya, bayangkan description parameter adalah string yang mahal untuk dihitung. Mungkin produk yang dijual mendapatkan deskripsi produk yang ramah dan bergantung pada kueri database, atau membaca dari file. Dalam situasi ini, Anda dapat menginstruksikan generator sumber untuk melewati IsEnabled penjaga dan menambahkan IsEnabled penjaga secara manual di situs panggilan. Ini memungkinkan pengguna untuk menentukan di mana penjaga dipanggil dan memastikan bahwa parameter yang mungkin mahal untuk komputasi hanya dievaluasi ketika benar-benar diperlukan. Pertimbangkan gambar berikut:

using Microsoft.Extensions.Logging;

namespace Logging.LibraryAuthors;

internal static partial class LogMessages
{
    [LoggerMessage(
        Message = "Sold {Quantity} of {Description}",
        Level = LogLevel.Information,
        SkipEnabledCheck = true)]
    internal static partial void LogProductSaleDetails(
        this ILogger logger,
        int quantity,
        string description);
}

LogProductSaleDetails Ketika metode ekstensi dipanggil, IsEnabled penjaga dipanggil secara manual dan evaluasi parameter yang mahal terbatas pada saat diperlukan. Pertimbangkan gambar berikut:

if (_logger.IsEnabled(LogLevel.Information))
{
    // Expensive parameter evaluation
    var description = product.GetFriendlyProductDescription();

    _logger.LogProductSaleDetails(
        quantity,
        description);
}

Untuk informasi selengkapnya, lihat Pembuatan sumber pengelogan waktu kompilasi dan Pengelogan berkinerja tinggi di .NET.

Hindari interpolasi string dalam pengelogan

Kesalahan umumnya adalah menggunakan interpolasi string untuk membangun pesan log. Interpolasi string dalam pengelogan bermasalah untuk performa, karena string dievaluasi bahkan jika yang sesuai LogLevel tidak diaktifkan. Alih-alih interpolasi string, gunakan templat pesan log, pemformatan, dan daftar argumen. Untuk informasi selengkapnya, lihat Pengelogan di .NET: Templat pesan log.

Gunakan default pengelogan no-op

Mungkin ada kalanya, saat menggunakan pustaka yang mengekspos API pengelogan yang mengharapkan ILogger atau ILoggerFactory, yang tidak ingin Anda sediakan pencatatnya. Dalam kasus ini, paket NuGet Microsoft.Extensions.Logging.Abstractions menyediakan default pengelogan tanpa operasi.

Konsumen pustaka dapat secara default ke pengelogan null jika tidak ILoggerFactory disediakan. Penggunaan pengelogan null berbeda dari menentukan jenis sebagai nullable (ILoggerFactory?), karena jenisnya non-null. Jenis berbasis kenyamanan ini tidak mencatat apa pun dan pada dasarnya tidak ada operasi. Pertimbangkan untuk menggunakan salah satu jenis abstraksi yang tersedia jika berlaku: