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 unikILogger<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 manaTCategoryName
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 bernamaLogMessages
, sehinggastatic
dapat digunakan untuk menentukan metode ekstensi pada jenis .ILogger
- Menghias
LogProductSaleDetails
metode ekstensi denganLoggerMessage
atribut danMessage
templat. - Menyatakan
LogProductSaleDetails
, yang memperluasILogger
dan menerimaquantity
dandescription
.
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: