Bagikan melalui


Panduan pengelogan untuk penulis pustaka .NET

Sebagai pengembang pustaka, menyediakan fitur log adalah cara yang bagus untuk memberi konsumen wawasan tentang cara kerja internal 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.

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 perpustakaan perangkat lunak atau konstruktor publik dari tipe 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 yang umum dari hal ini adalah konstruktor untuk kelas yang dibuat melalui 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 menggunakan generator sumber pencatatan untuk menentukan metode pencatatan bertipe kuat. 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:

  • Mendefinisikan sebuah partial class yang bernama LogMessages, yang merupakan static sehingga dapat digunakan untuk menentukan metode ekstensi pada tipe ILogger.
  • Mendekorasi metode tambahan LogProductSaleDetails dengan atribut LoggerMessage dan templat Message.
  • Menyatakan LogProductSaleDetails, yang merupakan perpanjangan dari ILogger dan menerima quantity dan description.

Petunjuk / Saran

Anda dapat mengakses kode yang dihasilkan oleh sumber selama debugging, karena adalah bagian dari assembly yang sama dengan kode yang memanggilnya.

Gunakan IsEnabled untuk menghindari evaluasi parameter yang mahal

Mungkin ada situasi di mana evaluasi parameter berbiaya tinggi. Mengembangkan contoh sebelumnya, bayangkan parameter description adalah string yang mahal untuk dikomputasi. Mungkin produk yang dijual mendapatkan deskripsi produk yang menarik dan bergantung pada kueri database atau dengan membaca dari file. Dalam situasi ini, Anda dapat menginstruksikan generator sumber untuk melewati IsEnabled penjaga dan menambahkan IsEnabled penjaga secara manual di lokasi pemanggilan. 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 kode 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);
}

Ketika metode ekstensi LogProductSaleDetails dipanggil, penjaga IsEnabled diaktifkan secara manual dan evaluasi parameter yang membutuhkan banyak sumber daya dilakukan hanya saat diperlukan. Pertimbangkan kode 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 pencatatan dapat menimbulkan masalah performa, karena string dievaluasi bahkan jika LogLevel yang bersangkutan tidak diaktifkan. Alih-alih interpolasi string, gunakan templat pesan log, pemformatan, dan daftar argumen. Untuk informasi selengkapnya, lihat Logging di .NET: Templat pesan log.

Gunakan pengaturan standar pengelogan no-op

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

Pengguna pustaka dapat menggunakan pengelogan null jika tidak ada ILoggerFactory yang disediakan. Penggunaan null logging berbeda dari menentukan jenis sebagai nullable, karena jenisnya non-null. Jenis berbasis kemudahan ini tidak mencatat apa pun dan pada dasarnya tidak melakukan operasi apapun. Pertimbangkan untuk menggunakan salah satu jenis abstraksi yang tersedia jika berlaku: