Pelatihan
Modul
Memformat data alfanumerik untuk presentasi dalam C# - Training
Jelajahi metode dasar dalam C# untuk memformat data alfanumerik.
Browser ini sudah tidak didukung.
Mutakhirkan ke Microsoft Edge untuk memanfaatkan fitur, pembaruan keamanan, dan dukungan teknis terkini.
.NET mendukung pengelogan terstruktur berkinerja tinggi melalui ILogger API untuk membantu memantau perilaku aplikasi dan mendiagnosis masalah. Log dapat ditulis ke tujuan yang berbeda dengan mengonfigurasi penyedia pengelogan yang berbeda. Penyedia pengelogan dasar juga bawaan dan ada banyak penyedia pihak ketiga yang tersedia.
Contoh pertama ini menunjukkan dasar-dasarnya, tetapi hanya cocok untuk aplikasi konsol sepele. Aplikasi konsol sampel ini bergantung pada paket NuGet berikut:
Di bagian berikutnya, Anda akan melihat cara meningkatkan kode dengan mempertimbangkan skala, performa, konfigurasi, dan pola pemrograman umum.
using Microsoft.Extensions.Logging;
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Contoh sebelumnya:
ILoggerFactory
semua konfigurasi yang menentukan tempat pesan log dikirim. Dalam hal ini, Anda mengonfigurasi penyedia pengelogan konsol sehingga pesan log ditulis ke konsol.string
yang terkait dengan setiap pesan yang dicatat oleh ILogger
objek. Ini digunakan untuk mengelompokkan pesan log dari kelas (atau kategori) yang sama bersama-sama saat mencari atau memfilter log.Information
. Tingkat log menunjukkan tingkat keparahan peristiwa yang dicatat dan digunakan untuk memfilter pesan log yang kurang penting. Entri log juga menyertakan templat "Hello World! Logging is {Description}."
pesan dan pasangan Description = fun
kunci-nilai . Nama kunci (atau tempat penampung) berasal dari kata di dalam kurung kurawal dalam templat dan nilai berasal dari argumen metode yang tersisa.File proyek untuk contoh ini mencakup dua paket NuGet:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging" Version="9.0.0" />
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="9.0.0" />
</ItemGroup>
</Project>
Tip
Semua contoh pengelogan kode sumber tersedia di Browser Sampel untuk diunduh. Untuk informasi selengkapnya, lihat Menelusuri sampel kode: Pengelogan di .NET.
Ada beberapa perubahan yang harus Anda pertimbangkan untuk membuat contoh sebelumnya saat pengelogan dalam skenario yang kurang sepele:
Jika aplikasi Anda menggunakan Dependency Injection (DI) atau host seperti ASP. WebApplication NET atau Host Generik maka Anda harus menggunakan ILoggerFactory
objek dan ILogger
dari kontainer DI masing-masing daripada membuatnya secara langsung. Untuk informasi selengkapnya, lihat Integrasi dengan DI dan Host.
Pembuatan sumber waktu kompilasi pengelogan biasanya merupakan alternatif yang lebih baik untuk ILogger
metode ekstensi seperti LogInformation
. Pembuatan sumber pengelogan menawarkan performa yang lebih baik, pengetikan yang lebih kuat, dan menghindari penyebaran string
konstanta di seluruh metode Anda. Tradeoff adalah bahwa menggunakan teknik ini membutuhkan sedikit lebih banyak kode.
using Microsoft.Extensions.Logging;
internal partial class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger("Program");
LogStartupMessage(logger, "fun");
}
[LoggerMessage(Level = LogLevel.Information, Message = "Hello World! Logging is {Description}.")]
static partial void LogStartupMessage(ILogger logger, string description);
}
Type
menerima untuk membuat penamaan ini mudah dilakukan.using Microsoft.Extensions.Logging;
internal class Program
{
static void Main(string[] args)
{
using ILoggerFactory factory = LoggerFactory.Create(builder => builder.AddConsole());
ILogger logger = factory.CreateLogger<Program>();
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
}
}
using Microsoft.Extensions.Logging;
using OpenTelemetry.Logs;
using ILoggerFactory factory = LoggerFactory.Create(builder =>
{
builder.AddOpenTelemetry(logging =>
{
logging.AddOtlpExporter();
});
});
ILogger logger = factory.CreateLogger("Program");
logger.LogInformation("Hello World! Logging is {Description}.", "fun");
Jika aplikasi Anda menggunakan Dependency Injection (DI) atau host seperti ASP. WebApplication NET atau Host Generik maka Anda harus menggunakan ILoggerFactory
objek dan ILogger
dari kontainer DI daripada membuatnya secara langsung.
Contoh ini mendapatkan objek ILogger di aplikasi yang dihosting menggunakan API Minimal ASP.NET:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
var handler = app.Services.GetRequiredService<ExampleHandler>();
app.MapGet("/", handler.HandleRequest);
app.Run();
partial class ExampleHandler(ILogger<ExampleHandler> logger)
{
public string HandleRequest()
{
LogHandleRequest(logger);
return "Hello World";
}
[LoggerMessage(LogLevel.Information, "ExampleHandler.HandleRequest was called")]
public static partial void LogHandleRequest(ILogger logger);
}
Contoh sebelumnya:
ExampleHandler
dan memetakan permintaan web masuk untuk menjalankan ExampleHandler.HandleRequest
fungsi.ILogger<ExampleHandler>
. ILogger<TCategoryName> berasal dari ILogger dan menunjukkan kategori ILogger
mana yang dimiliki objek. Kontainer DI menemukan dengan kategori yang ILogger
benar dan menyediakannya sebagai argumen konstruktor. Jika belum ada ILogger
dengan kategori tersebut, kontainer DI secara otomatis membuatnya dari ILoggerFactory
penyedia layanan.logger
yang diterima dalam konstruktor digunakan untuk pengelogan HandleRequest
dalam fungsi.Penyusun host menginisialisasi konfigurasi default, lalu menambahkan objek yang dikonfigurasi ILoggerFactory
ke kontainer DI host saat host dibuat. Sebelum host dibuat, Anda dapat menyesuaikan konfigurasi pengelogan melalui HostApplicationBuilder.Logging, , WebApplicationBuilder.Loggingatau API serupa di host lain. Host juga menerapkan konfigurasi pengelogan dari sumber konfigurasi default sebagai variabel appsettings.json dan lingkungan. Untuk informasi selengkapnya, lihat Konfigurasi di .NET.
Contoh ini diperluas pada yang sebelumnya untuk menyesuaikan yang ILoggerFactory
disediakan oleh WebApplicationBuilder
. Ini menambahkan OpenTelemetry sebagai penyedia pengelogan yang mengirimkan log melalui OTLP (protokol OpenTelemetry):
var builder = WebApplication.CreateBuilder(args);
builder.Logging.AddOpenTelemetry(logging => logging.AddOtlpExporter());
builder.Services.AddSingleton<ExampleHandler>();
var app = builder.Build();
Jika Anda menggunakan kontainer DI tanpa host, gunakan AddLogging untuk mengonfigurasi dan menambahkan ILoggerFactory
ke kontainer.
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
// Add services to the container including logging
var services = new ServiceCollection();
services.AddLogging(builder => builder.AddConsole());
services.AddSingleton<ExampleService>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
// Get the ExampleService object from the container
ExampleService service = serviceProvider.GetRequiredService<ExampleService>();
// Do some pretend work
service.DoSomeWork(10, 20);
class ExampleService(ILogger<ExampleService> logger)
{
public void DoSomeWork(int x, int y)
{
logger.LogInformation("DoSomeWork was called. x={X}, y={Y}", x, y);
}
}
Contoh sebelumnya:
ILoggerFactory
untuk menulis ke konsolExampleService
ke kontainerExampleService
kontainer DI yang juga secara otomatis membuat ILogger<ExampleService>
untuk digunakan sebagai argumen konstruktor.ExampleService.DoSomeWork
yang menggunakan ILogger<ExampleService>
untuk mencatat pesan ke konsol.Konfigurasi pengelogan diatur dalam kode atau melalui sumber eksternal, seperti, file konfigurasi dan variabel lingkungan. Menggunakan konfigurasi eksternal bermanfaat jika memungkinkan karena dapat diubah tanpa membangun kembali aplikasi. Namun, beberapa tugas, seperti mengatur penyedia pengelogan, hanya dapat dikonfigurasi dari kode.
Untuk aplikasi yang menggunakan host, konfigurasi pengelogan umumnya disediakan oleh "Logging"
bagian appsettings.{Environment}
.json file. Untuk aplikasi yang tidak menggunakan host, sumber konfigurasi eksternal disiapkan secara eksplisit atau dikonfigurasi dalam kode sebagai gantinya.
Appsetting berikut . file Development.json dihasilkan oleh templat layanan .NET Worker:
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
}
}
Dalam JSON sebelumnya:
"Default"
tingkat log , "Microsoft"
, dan "Microsoft.Hosting.Lifetime"
ditentukan."Default"
diterapkan ke semua kategori yang tidak ditentukan lain, secara efektif membuat semua nilai default untuk semua kategori "Information"
. Anda dapat mengambil alih perilaku ini dengan menentukan nilai untuk kategori."Microsoft"
berlaku untuk semua kategori yang dimulai dengan "Microsoft"
."Microsoft"
mencatat pada tingkat Warning
log dan yang lebih tinggi."Microsoft.Hosting.Lifetime"
ini lebih spesifik daripada "Microsoft"
kategori, sehingga "Microsoft.Hosting.Lifetime"
log kategori pada tingkat "Information"
log dan lebih tinggi.LogLevel
berlaku untuk semua penyedia pengelogan yang diaktifkan kecuali untuk Windows EventLog.Properti Logging
dapat memiliki LogLevel dan properti penyedia log. LogLevel
menentukan tingkat minimum yang akan dicatat untuk kategori yang dipilih. Di JSON sebelumnya, Information
dan Warning
tingkat log ditentukan. LogLevel
menunjukkan tingkat keparahan log dan memiliki rentang 0 hingga 6:
Trace
= 0, Debug
= 1, Information
= 2, Warning
= 3, Error
= 4, Critical
= 5, dan None
= 6.
Bila LogLevel
ditetapkan, pengelogan diaktifkan untuk pesan pada tingkat yang ditentukan dan lebih tinggi. Di JSON sebelumnya, Default
kategori dicatat dan Information
lebih tinggi. Misalnya, pesan Information
, Warning
, Error
, dan Critical
dicatat. Jika tidak ada LogLevel
yang ditentukan, pengelogan diatur ke default, yakni tingkat Information
. Untuk informasi lebih lanjut, lihat Tingkat log.
Properti penyedia dapat menentukan properti LogLevel
. LogLevel
di bawah penyedia menentukan tingkat yang perlu dicatat untuk penyedia tersebut, dan menimpa pengaturan log non-penyedia. Pertimbangkan file appsettings.json berikut:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information",
"Microsoft.Hosting": "Trace"
}
},
"EventSource": {
"LogLevel": {
"Default": "Warning"
}
}
}
}
Pengaturan di Logging.{ProviderName}.LogLevel
menimpa pengaturan di Logging.LogLevel
. Di JSON sebelumnya, Debug
tingkat log default penyedia diatur ke Information
:
Logging:Debug:LogLevel:Default:Information
Pengaturan sebelumnya menetapkan tingkat log Information
untuk setiap kategori Logging:Debug:
kecuali Microsoft.Hosting
. Ketika kategori tertentu dicantumkan, kategori tersebut menimpa kategori default. Di JSON sebelumnya, Logging:Debug:LogLevel
kategori "Microsoft.Hosting"
dan "Default"
ambil alih pengaturan di Logging:LogLevel
Tingkat log minimum dapat ditentukan untuk salah satu dari:
Logging:EventSource:LogLevel:Default:Information
Logging:LogLevel:Microsoft:Warning
Logging:LogLevel:Default:Warning
Setiap log di bawah tingkat minimum tidak:
Untuk menyembunyikan semua log, tentukan LogLevel.None. LogLevel.None
memiliki nilai 6, yang lebih tinggi dari LogLevel.Critical
(5).
Jika penyedia mendukung cakupan log, IncludeScopes
menunjukkan apakah cakupan diaktifkan. Untuk informasi lebih lanjut, lihat cakupan log
File appsettings.json berikut berisi pengaturan untuk semua penyedia bawaan:
{
"Logging": {
"LogLevel": {
"Default": "Error",
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Warning"
},
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft.Extensions.Hosting": "Warning",
"Default": "Information"
}
},
"EventSource": {
"LogLevel": {
"Microsoft": "Information"
}
},
"EventLog": {
"LogLevel": {
"Microsoft": "Information"
}
},
"AzureAppServicesFile": {
"IncludeScopes": true,
"LogLevel": {
"Default": "Warning"
}
},
"AzureAppServicesBlob": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Information"
}
},
"ApplicationInsights": {
"LogLevel": {
"Default": "Information"
}
}
}
}
Dalam sampel sebelumnya:
Logging.{ProviderName}.LogLevel
menimpa pengaturan di Logging.LogLevel
. Misalnya, tingkat di Debug.LogLevel.Default
menggantikan tingkat di LogLevel.Default
.Console
Debug
EventSource
EventLog
AzureAppServicesFile
AzureAppServicesBlob
ApplicationInsights
Tingkat log dapat diatur oleh penyedia konfigurasi mana pun. Misalnya, Anda dapat membuat variabel lingkungan yang bertahan bernama Logging:LogLevel:Microsoft
dengan nilai Information
.
Buat dan tetapkan variabel lingkungan yang bertahan, mengingat nilai tingkat log.
:: Assigns the env var to the value
setx "Logging__LogLevel__Microsoft" "Information" /M
Dalam instans baru Prompt Perintah, baca variabel lingkungan.
:: Prints the env var value
echo %Logging__LogLevel__Microsoft%
Pengaturan lingkungan sebelumnya dipertahankan di lingkungan. Untuk menguji pengaturan saat menggunakan aplikasi yang dibuat dengan templat layanan .NET Worker, gunakan dotnet run
perintah di direktori proyek setelah variabel lingkungan ditetapkan.
dotnet run
Tip
Setelah menetapkan variabel lingkungan, mulai ulang lingkungan pengembangan terpadu (IDE) Anda untuk memastikan bahwa variabel lingkungan yang baru ditambahkan tersedia.
Pada Azure App Service, pilih Pengaturan aplikasi baru di halaman Pengaturan > Konfigurasi. Pengaturan aplikasi Azure App Service:
Untuk informasi selengkapnya tentang mengatur nilai konfigurasi .NET menggunakan variabel lingkungan, lihat variabel lingkungan.
Untuk mengonfigurasi pengelogan dalam kode, gunakan ILoggingBuilder API. Ini dapat diakses dari berbagai tempat:
ILoggerFactory
di LoggerFactory.Create.Contoh ini menunjukkan pengaturan penyedia pengelogan konsol dan beberapa filter.
using Microsoft.Extensions.Logging;
using var loggerFactory = LoggerFactory.Create(static builder =>
{
builder
.AddFilter("Microsoft", LogLevel.Warning)
.AddFilter("System", LogLevel.Warning)
.AddFilter("LoggingConsoleApp.Program", LogLevel.Debug)
.AddConsole();
});
ILogger logger = loggerFactory.CreateLogger<Program>();
logger.LogDebug("Hello {Target}", "Everyone");
Dalam contoh AddFilter sebelumnya digunakan untuk menyesuaikan tingkat log yang diaktifkan untuk berbagai kategori. AddConsole digunakan untuk menambahkan penyedia pengelogan konsol. Secara default, log dengan Debug
tingkat keparahan tidak diaktifkan, tetapi karena konfigurasi menyesuaikan filter, pesan debug "Halo Semua Orang" ditampilkan di konsol.
Saat objek ILogger<TCategoryName> dibuat, objek ILoggerFactory memilih satu aturan per penyedia untuk diterapkan ke pencatat tersebut. Semua pesan yang ditulis oleh instans ILogger
difilter berdasarkan aturan yang dipilih. Aturan paling spesifik untuk setiap pasangan penyedia dan kategori dipilih dari aturan yang tersedia.
Algoritma berikut digunakan untuk setiap penyedia saat ILogger
dibuat untuk kategori tertentu:
Saat objek ILogger
dibuat, kategori ditentukan. Kategori tersebut disertakan dengan setiap pesan log yang dibuat oleh instans ILogger
tersebut. String kategori bersifat arbitrer, tetapi konvensinya adalah menggunakan nama kelas yang sepenuhnya memenuhi syarat. Misalnya, dalam aplikasi dengan layanan yang ditentukan seperti objek berikut, kategorinya mungkin "Example.DefaultService"
:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger<DefaultService> _logger;
public DefaultService(ILogger<DefaultService> logger) =>
_logger = logger;
// ...
}
}
Jika kategorisasi lebih lanjut diinginkan, konvensinya adalah menggunakan nama hierarkis dengan menambahkan subkategori ke nama kelas yang sepenuhnya memenuhi syarat, dan secara eksplisit menentukan kategori menggunakan LoggerFactory.CreateLogger:
namespace Example
{
public class DefaultService : IService
{
private readonly ILogger _logger;
public DefaultService(ILoggerFactory loggerFactory) =>
_logger = loggerFactory.CreateLogger("Example.DefaultService.CustomCategory");
// ...
}
}
Panggilan CreateLogger
dengan nama tetap dapat berguna saat digunakan dalam beberapa kelas/jenis sehingga peristiwa dapat diatur berdasarkan kategori.
ILogger<T>
sama dengan memanggil CreateLogger
, dengan nama jenis T
yang sepenuhnya memenuhi syarat.
Tabel berikut mencantumkan nilai LogLevel, metode ekstensi Log{LogLevel}
yang praktis, dan penggunaan yang disarankan:
LogLevel | Nilai | Metode | Deskripsi |
---|---|---|---|
Bekas | 0 | LogTrace | Berisi pesan paling terperinci. Pesan ini mungkin berisi data aplikasi yang sensitif. Pesan-pesan ini dinonaktifkan secara default dan tidak boleh diaktifkan dalam produksi. |
Debug | 1 | LogDebug | Untuk penelusuran kesalahan dan pengembangan. Gunakan dengan hati-hati dalam produksi karena volume yang tinggi. |
Informasi | 2 | LogInformation | Melacak alur umum aplikasi. Mungkin memiliki nilai jangka panjang. |
Peringatan | 3 | LogWarning | Untuk peristiwa yang tidak normal atau tidak terduga. Biasanya menyertakan kesalahan atau kondisi yang tidak menyebabkan aplikasi gagal. |
Kesalahan | 4 | LogError | Untuk kesalahan dan pengecualian yang tidak dapat ditangani. Pesan-pesan ini menunjukkan kegagalan dalam operasi atau permintaan saat ini, bukan kegagalan di seluruh aplikasi. |
Kritis | 5 | LogCritical | Untuk kegagalan yang membutuhkan perhatian sesegera mungkin. Contoh: skenario kehilangan data, ruang disk yang habis. |
Tidak | 6 | Menentukan bahwa tidak ada pesan yang harus ditulis. |
Pada tabel sebelumnya, LogLevel
dicantumkan dari tingkat keparahan terendah hingga tertinggi.
Parameter pertama metode Log, LogLevel, menunjukkan tingkat keparahan log. Alih-alih memanggil Log(LogLevel, ...)
, sebagian besar pengembang memanggil metode ekstensi Log{LogLevel}. Metode Log{LogLevel}
ekstensi memanggil Log
metode dan menentukan LogLevel
. Misalnya, dua panggilan pengelogan berikut secara fungsional setara dan menghasilkan log yang sama:
public void LogDetails()
{
var logMessage = "Details for log.";
_logger.Log(LogLevel.Information, AppLogEvents.Details, logMessage);
_logger.LogInformation(AppLogEvents.Details, logMessage);
}
AppLogEvents.Details
adalah ID peristiwa, dan secara implisit diwakili oleh nilai konstanta Int32 . AppLogEvents
adalah kelas yang mengekspos berbagai konstanta pengidentifikasi bernama dan ditampilkan di bagian ID peristiwa Log.
Kode berikut membuat log Information
dan Warning
:
public async Task<T> GetAsync<T>(string id)
{
_logger.LogInformation(AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
return result;
}
Dalam kode sebelumnya, parameter pertama Log{LogLevel}
, AppLogEvents.Read
, adalah ID peristiwa Log. Parameter kedua adalah template pesan dengan tempat penampung untuk nilai argumen yang disediakan oleh parameter metode yang tersisa. Parameter metode dijelaskan di bagian templat pesan nanti di artikel ini.
Konfigurasikan tingkat log yang sesuai dan panggil metode yang benar Log{LogLevel}
untuk mengontrol berapa banyak output log yang ditulis ke media penyimpanan tertentu. Contohnya:
Trace
atau Debug
menghasilkan pesan log terperinci dengan volume yang tinggi. Untuk mengontrol biaya dan tidak melebihi batas penyimpanan data, catat pesan tingkat Trace
dan Debug
ke penyimpanan data bervolume tinggi dan berbiaya rendah. Pertimbangkan untuk membatasi Trace
dan Debug
pada kategori tertentu.Warning
sampai Critical
akan menghasilkan beberapa pesan log.
Warning
.Trace
atau Debug
saat memecahkan masalah. Untuk membatasi output, atur Trace
atau Debug
hanya untuk kategori yang sedang diselidiki.Set Logging:Console:LogLevel:Microsoft:Information
JSON berikut :
{
"Logging": {
"LogLevel": {
"Microsoft": "Warning"
},
"Console": {
"LogLevel": {
"Microsoft": "Information"
}
}
}
}
Setiap log dapat menentukan pengidentifikasi peristiwa, EventId adalah struktur dengan Id
properti readonly opsional Name
dan . Kode sumber sampel menggunakan AppLogEvents
kelas untuk menentukan ID peristiwa:
using Microsoft.Extensions.Logging;
internal static class AppLogEvents
{
internal static EventId Create = new(1000, "Created");
internal static EventId Read = new(1001, "Read");
internal static EventId Update = new(1002, "Updated");
internal static EventId Delete = new(1003, "Deleted");
// These are also valid EventId instances, as there's
// an implicit conversion from int to an EventId
internal const int Details = 3000;
internal const int Error = 3001;
internal static EventId ReadNotFound = 4000;
internal static EventId UpdateNotFound = 4001;
// ...
}
Tip
Untuk informasi selengkapnya tentang mengonversi int
ke EventId
, lihat Operator EventId.Implicit(Int32 ke EventId).
ID peristiwa mengaitkan serangkaian peristiwa. Misalnya, semua log yang terkait dengan membaca nilai dari repositori mungkin .1001
Penyedia pengelogan dapat mencatat ID peristiwa di bidang ID, dalam pesan pengelogan, atau tidak sama sekali. Penyedia Debug tidak menampilkan ID peristiwa. Penyedia konsol menunjukkan ID peristiwa dalam tanda kurung setelah kategori:
info: Example.DefaultService.GetAsync[1001]
Reading value for a1b2c3
warn: Example.DefaultService.GetAsync[4000]
GetAsync(a1b2c3) not found
Beberapa penyedia pengelogan menyimpan ID peristiwa di bidang, yang memungkinkan pemfilteran pada ID.
Setiap API log menggunakan template pesan. Template pesan dapat berisi tempat penampung yang argumennya disediakan. Gunakan nama untuk tempat penampung, bukan angka. Urutan tempat penampung, bukan namanya, menentukan parameter mana yang digunakan untuk memberikan nilainya. Dalam kode berikut, nama parameter di luar urutan dalam templat pesan:
string p1 = "param1";
string p2 = "param2";
_logger.LogInformation("Parameter values: {p2}, {p1}", p1, p2);
Kode sebelumnya membuat pesan log dengan nilai parameter secara berurutan:
Parameter values: param1, param2
Catatan
Berhati-hatilah saat menggunakan beberapa tempat penampung dalam satu templat pesan, karena berbasis ordinal. Nama tidak digunakan untuk meratakan argumen ke tempat penampung.
Pendekatan ini memungkinkan penyedia pengelogan untuk mengimplementasikan pengelogan semantik atau terstruktur. Argumen itu sendiri diteruskan ke sistem pengelogan, bukan hanya template pesan yang diformat. Ini memungkinkan penyedia pengelogan untuk menyimpan nilai parameter sebagai bidang. Pertimbangkan metode pencatat berikut:
_logger.LogInformation("Getting item {Id} at {RunTime}", id, DateTime.Now);
Misalnya, saat mencatat ke Azure Table Storage:
ID
dan RunTime
.RunTime
tertentu tanpa harus menguraikan waktu habis pesan teks.Templat pesan log mendukung pemformatan tempat penampung. Templat bebas untuk menentukan format yang valid untuk argumen jenis yang diberikan. Misalnya, pertimbangkan templat pesan pencatat berikut Information
:
_logger.LogInformation("Logged on {PlaceHolderName:MMMM dd, yyyy}", DateTimeOffset.UtcNow);
// Logged on January 06, 2022
Dalam contoh sebelumnya, DateTimeOffset
instans adalah jenis yang sesuai dengan PlaceHolderName
di templat pesan pencatat. Nama ini bisa apa saja karena nilainya berbasis ordinal. MMMM dd, yyyy
Format ini valid untuk jenis tersebutDateTimeOffset
.
Untuk informasi selengkapnya tentang DateTime
dan DateTimeOffset
pemformatan, lihat String format tanggal dan waktu kustom.
Contoh berikut menunjukkan cara memformat templat pesan menggunakan {}
sintaks tempat penampung. Selain itu, contoh melarikan diri {}
dari sintaks tempat penampung ditunjukkan dengan outputnya. Terakhir, interpolasi string dengan tempat penampung templat juga ditampilkan:
logger.LogInformation("Number: {Number}", 1); // Number: 1
logger.LogInformation("{{Number}}: {Number}", 3); // {Number}: 3
logger.LogInformation($"{{{{Number}}}}: {{Number}}", 5); // {Number}: 5
Tip
Metode pencatat memiliki overload yang mengambil parameter pengecualian:
public void Test(string id)
{
try
{
if (id is "none")
{
throw new Exception("Default Id detected.");
}
}
catch (Exception ex)
{
_logger.LogWarning(
AppLogEvents.Error, ex,
"Failed to process iteration: {Id}", id);
}
}
Pengelogan pengecualian sifatnya khusus untuk penyedia.
Jika tingkat log bawaan tidak diatur, nilai tingkat log defaultnya adalah Information
.
Misalnya, pertimbangkan aplikasi layanan pekerja berikut:
Dengan penyiapan sebelumnya, membuka halaman privasi atau beranda akan menghasilkan banyak pesan Trace
, Debug
, dan Information
dengan Microsoft
dalam nama kategori.
Kode berikut menetapkan tingkat log default ketika tingkat log default tidak diatur dalam konfigurasi:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.SetMinimumLevel(LogLevel.Warning);
using IHost host = builder.Build();
await host.RunAsync();
Fungsi filter dipanggil untuk semua penyedia dan kategori yang tidak memiliki aturan yang ditetapkan padanya oleh konfigurasi atau kode:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.AddFilter((provider, category, logLevel) =>
{
return provider.Contains("ConsoleLoggerProvider")
&& (category.Contains("Example") || category.Contains("Microsoft"))
&& logLevel >= LogLevel.Information;
});
using IHost host = builder.Build();
await host.RunAsync();
Kode sebelumnya menampilkan log konsol jika kategori berisi Example
atau Microsoft
dan tingkat log adalah Information
atau yang lebih tinggi.
Cakupan mengelompokkan serangkaian operasi logis. Pengelompokan ini dapat digunakan untuk melampirkan data yang sama ke setiap log yang dibuat sebagai bagian dari kumpulan. Misalnya, setiap log yang dibuat sebagai bagian dari pemrosesan transaksi dapat menyertakan ID transaksi.
Cakupan:
Penyedia berikut mendukung cakupan:
Gunakan cakupan dengan membungkus panggilan pencatat di blok using
:
public async Task<T> GetAsync<T>(string id)
{
T result;
var transactionId = Guid.NewGuid().ToString();
using (_logger.BeginScope(new List<KeyValuePair<string, object>>
{
new KeyValuePair<string, object>("TransactionId", transactionId),
}))
{
_logger.LogInformation(
AppLogEvents.Read, "Reading value for {Id}", id);
var result = await _repository.GetAsync(id);
if (result is null)
{
_logger.LogWarning(
AppLogEvents.ReadNotFound, "GetAsync({Id}) not found", id);
}
}
return result;
}
JSON berikut memungkinkan cakupan untuk penyedia konsol:
{
"Logging": {
"Debug": {
"LogLevel": {
"Default": "Information"
}
},
"Console": {
"IncludeScopes": true,
"LogLevel": {
"Microsoft": "Warning",
"Default": "Information"
}
},
"LogLevel": {
"Default": "Debug"
}
}
}
Kode berikut memungkinkan cakupan untuk penyedia konsol:
HostApplicationBuilder builder = Host.CreateApplicationBuilder(args);
builder.Logging.ClearProviders();
builder.Logging.AddConsole(options => options.IncludeScopes = true);
using IHost host = builder.Build();
await host.RunAsync();
Kode berikut mencatat di Main
dengan mendapatkan instans ILogger
dari DI setelah membangun host:
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using IHost host = Host.CreateApplicationBuilder(args).Build();
var logger = host.Services.GetRequiredService<ILogger<Program>>();
logger.LogInformation("Host created.");
await host.RunAsync();
Kode sebelumnya bergantung pada dua paket NuGet:
File proyeknya akan terlihat mirip dengan yang berikut ini:
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Hosting" Version="7.0.1" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="7.0.0" />
</ItemGroup>
</Project>
Pengelogan harus dilakukan dengan sangat cepat sehingga tidak sebanding dengan biaya performa dari kode asinkron. Jika datastore pengelogan lambat, jangan menulisnya secara langsung. Pertimbangkan untuk terlebih dahulu menulis pesan log ke penyimpanan cepat, lalu memindahkannya ke penyimpanan lambat nanti. Misalnya, saat mencatat ke SQL Server, jangan lakukan secara langsung dalam metode Log
, karena metode Log
bersifat sinkron. Sebagai gantinya, tambahkan pesan log secara sinkron ke antrean dalam memori dan minta pekerja latar belakang untuk menarik pesan keluar dari antrean untuk melakukan pekerjaan asinkron berupa mendorong data ke SQL Server.
Logging API tidak menyertakan skenario untuk mengubah tingkat log saat aplikasi sedang berjalan. Namun, beberapa penyedia konfigurasi mampu untuk memuat ulang konfigurasi, yang langsung berpengaruh pada konfigurasi pengelogan. Misalnya, Penyedia Konfigurasi File memuat ulang konfigurasi pengelogan secara default. Jika konfigurasi diubah dalam kode saat aplikasi berjalan, aplikasi dapat memanggil IConfigurationRoot.Reload untuk memperbarui konfigurasi pengelogan aplikasi.
Antarmuka ILogger<TCategoryName> dan ILoggerFactory dan implementasi disertakan dalam sebagian besar .NET SDK sebagai referensi paket implisit. Mereka juga tersedia secara eksplisit dalam paket NuGet berikut ketika tidak direferensikan secara implisit:
Untuk informasi selengkapnya tentang .NET SDK mana yang menyertakan referensi paket implisit, lihat .NET SDK: tabel ke namespace implisit.
Umpan balik .NET
.NET adalah proyek sumber terbuka. Pilih tautan untuk memberikan umpan balik:
Pelatihan
Modul
Memformat data alfanumerik untuk presentasi dalam C# - Training
Jelajahi metode dasar dalam C# untuk memformat data alfanumerik.