Pengelogan Sederhana
Tip
Anda dapat mengunduh sampel artikel ini dari GitHub.
Pengelogan sederhana Entity Framework Core (EF Core) dapat digunakan untuk dengan mudah mendapatkan log saat mengembangkan dan men-debug aplikasi. Bentuk pengelogan ini membutuhkan konfigurasi minimal dan tidak ada paket NuGet tambahan.
Tip
EF Core juga terintegrasi dengan Microsoft.Extensions.Logging, yang membutuhkan lebih banyak konfigurasi, tetapi seringkali lebih cocok untuk pengelogan dalam aplikasi produksi.
Konfigurasi
Log EF Core dapat diakses dari segala jenis aplikasi melalui penggunaan LogTo saat mengonfigurasi instans DbContext. Konfigurasi ini pada umumnya dilakukan untuk mengambil alih DbContext.OnConfiguring. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine);
Secara bergantian, LogTo
dapat dipanggil sebagai bagian AddDbContext dari atau saat membuat DbContextOptions instans untuk diteruskan ke DbContext
konstruktor.
Tip
OnConfiguring masih dipanggil ketika AddDbContext digunakan atau instans DbContextOptions diteruskan ke konstruktor DbContext. Ini menjadikannya tempat yang ideal untuk menerapkan konfigurasi konteks terlepas dari bagaimana DbContext dibangun.
Mengarahkan log
Pengelogan ke konsol
LogTo
Action<T> memerlukan delegasi yang menerima string. EF Core akan memanggil delegasi ini dengan string untuk setiap pesan log yang dihasilkan. Kemudian terserah delegasi untuk melakukan sesuatu dengan pesan yang diberikan.
Metode Console.WriteLine ini sering digunakan untuk delegasi ini, seperti yang ditunjukkan di atas. Ini menghasilkan setiap pesan log yang ditulis ke konsol.
Pengelogan ke jendela debug
Debug.WriteLine dapat digunakan untuk mengirim output ke jendela Debug di Visual Studio atau ID Lainnya. Sintaks lambda harus digunakan dalam kasus ini karena kelas dikompilasi Debug
dari build rilis. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(message => Debug.WriteLine(message));
Pengelogan ke file
Menulis ke file memerlukan pembuatan atau serupa StreamWriter untuk file. Metode ini WriteLine kemudian dapat digunakan seperti pada contoh lain di atas. Ingatlah untuk memastikan file ditutup dengan bersih dengan membuang penulis ketika konteks dibuang. Contohnya:
private readonly StreamWriter _logStream = new StreamWriter("mylog.txt", append: true);
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(_logStream.WriteLine);
public override void Dispose()
{
base.Dispose();
_logStream.Dispose();
}
public override async ValueTask DisposeAsync()
{
await base.DisposeAsync();
await _logStream.DisposeAsync();
}
Tip
Pertimbangkan untuk menggunakan Microsoft.Extensions.Logging untuk pengelogan ke file dalam aplikasi produksi.
Mendapatkan pesan terperinci
Data sensitif
Secara default, EF Core tidak akan menyertakan nilai data apa pun dalam pesan pengecualian. Ini karena data tersebut mungkin bersifat rahasia, dan dapat diungkapkan dalam penggunaan produksi jika pengecualian tidak ditangani.
Namun, mengetahui nilai data, terutama untuk kunci, bisa sangat membantu saat men-debug. Ini dapat diaktifkan di EF Core dengan memanggil EnableSensitiveDataLogging(). Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(Console.WriteLine)
.EnableSensitiveDataLogging();
Pengecualian kueri terperinci
Untuk alasan performa, EF Core tidak membungkus setiap panggilan untuk membaca nilai dari penyedia database dalam blok try-catch. Namun, ini terkadang menghasilkan pengecualian yang sulit didiagnosis, terutama ketika database mengembalikan NULL ketika tidak diizinkan oleh model.
Mengaktifkan EnableDetailedErrors akan menyebabkan EF memperkenalkan blok try-catch ini dan dengan demikian memberikan kesalahan yang lebih rinci. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(Console.WriteLine)
.EnableDetailedErrors();
Filter
Tingkat log
Setiap pesan log EF Core ditetapkan ke tingkat yang ditentukan oleh LogLevel enum. Secara default, pengelogan sederhana EF Core mencakup setiap pesan pada tingkat atau di Debug
atasnya. LogTo
dapat diteruskan tingkat minimum yang lebih tinggi untuk memfilter beberapa pesan. Misalnya, meneruskan Information
menghasilkan sekumpulan log minimal yang terbatas pada akses database dan beberapa pesan housekeeping.
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(Console.WriteLine, LogLevel.Information);
Pesan tertentu
Setiap pesan log diberi EventId. ID ini dapat diakses dari CoreEventId kelas atau RelationalEventId kelas untuk pesan khusus relasional. Penyedia database mungkin juga memiliki ID khusus penyedia di kelas serupa. Misalnya, SqlServerEventId untuk penyedia SQL Server.
LogTo
dapat dikonfigurasi untuk hanya mencatat pesan yang terkait dengan satu atau beberapa ID peristiwa. Misalnya, untuk mencatat hanya pesan untuk konteks yang diinisialisasi atau dibuang:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(Console.WriteLine, new[] { CoreEventId.ContextDisposed, CoreEventId.ContextInitialized });
Kategori pesan
Setiap pesan log ditetapkan ke kategori pencatat hierarkis bernama. Kategorinya adalah:
Kategori | Pesan |
---|---|
Microsoft.EntityFrameworkCore | Semua pesan EF Core |
Microsoft.EntityFrameworkCore.Database | Semua interaksi database |
Microsoft.EntityFrameworkCore.Database. Koneksi ion | Penggunaan koneksi database |
Microsoft.EntityFrameworkCore.Database.Command | Penggunaan perintah database |
Microsoft.EntityFrameworkCore.Database.Transaction | Penggunaan transaksi database |
Microsoft.EntityFrameworkCore.Update | Menyimpan entitas, tidak termasuk interaksi database |
Microsoft.EntityFrameworkCore.Model | Semua interaksi model dan metadata |
Microsoft.EntityFrameworkCore.Model.Validation | Validasi model |
Microsoft.EntityFrameworkCore.Query | Kueri, tidak termasuk interaksi database |
Microsoft.EntityFrameworkCore.Infrastructure | Peristiwa umum, seperti pembuatan konteks |
Microsoft.EntityFrameworkCore.Scaffolding | Rekayasa terbalik database |
Microsoft.EntityFrameworkCore.Migrations | Migrasi |
Microsoft.EntityFrameworkCore.ChangeTracking | Interaksi pelacakan perubahan |
LogTo
dapat dikonfigurasi untuk hanya mencatat pesan dari satu atau beberapa kategori. Misalnya, untuk mencatat hanya interaksi database:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(Console.WriteLine, new[] { DbLoggerCategory.Database.Name });
Perhatikan bahwa DbLoggerCategory kelas menyediakan API hierarkis untuk menemukan kategori dan menghindari kebutuhan untuk string hard-code.
Karena kategori bersifat hierarkis, contoh ini menggunakan Database
kategori akan menyertakan semua pesan untuk subkategori Database.Connection
, , Database.Command
dan Database.Transaction
.
Filter khusus
LogTo
memungkinkan filter kustom digunakan untuk kasus di mana tidak ada opsi pemfilteran di atas yang cukup. Misalnya, untuk mencatat pesan apa pun pada tingkat Information
atau di atasnya, serta pesan untuk membuka dan menutup koneksi:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.LogTo(
Console.WriteLine,
(eventId, logLevel) => logLevel >= LogLevel.Information
|| eventId == RelationalEventId.ConnectionOpened
|| eventId == RelationalEventId.ConnectionClosed);
Tip
Pemfilteran menggunakan filter kustom atau menggunakan salah satu opsi lain yang ditampilkan di sini lebih efisien daripada pemfilteran di LogTo
delegasi. Ini karena jika filter menentukan pesan tidak boleh dicatat, maka pesan log bahkan tidak dibuat.
Konfigurasi untuk pesan tertentu
EF Core ConfigureWarnings API memungkinkan aplikasi untuk mengubah apa yang terjadi ketika peristiwa tertentu ditemui. Ini dapat digunakan untuk:
- Mengubah tingkat log tempat peristiwa dicatat
- Lewati pengelogan peristiwa sama sekali
- Melemparkan pengecualian saat peristiwa terjadi
Mengubah tingkat log untuk suatu peristiwa
Contoh sebelumnya menggunakan filter kustom untuk mencatat setiap pesan serta LogLevel.Information
dua peristiwa yang ditentukan untuk LogLevel.Debug
. Hal yang sama dapat dicapai dengan mengubah tingkat log dari dua Debug
peristiwa menjadi Information
:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.ConfigureWarnings(
b => b.Log(
(RelationalEventId.ConnectionOpened, LogLevel.Information),
(RelationalEventId.ConnectionClosed, LogLevel.Information)))
.LogTo(Console.WriteLine, LogLevel.Information);
Menyembunyikan pengelogan peristiwa
Dengan cara yang sama, peristiwa individu dapat ditekan dari pengelogan. Ini sangat berguna untuk mengabaikan peringatan yang telah ditinjau dan dipahami. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.ConfigureWarnings(b => b.Ignore(CoreEventId.DetachedLazyLoadingWarning))
.LogTo(Console.WriteLine);
Melemparkan untuk suatu peristiwa
Terakhir, EF Core dapat dikonfigurasi untuk dilemparkan untuk peristiwa tertentu. Ini sangat berguna untuk mengubah peringatan menjadi kesalahan. (Memang, ini adalah tujuan ConfigureWarnings
asli metode, oleh karena itu namanya.) Misalnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder
.ConfigureWarnings(b => b.Throw(RelationalEventId.MultipleCollectionIncludeWarning))
.LogTo(Console.WriteLine);
Isi dan pemformatan pesan
Konten default dari LogTo
diformat di beberapa baris. Baris pertama berisi metadata pesan:
- LogLevel sebagai awalan empat karakter
- Tanda waktu lokal, diformat untuk budaya saat ini
- EventId dalam formulir yang dapat disalin/ditempelkan untuk mendapatkan anggota dari CoreEventId atau salah satu kelas lainnya
EventId
, ditambah nilai ID mentah - Kategori peristiwa, seperti yang dijelaskan di atas.
Contohnya:
info: 10/6/2020 10:52:45.581 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Blogs" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,
"Name" INTEGER NOT NULL
);
dbug: 10/6/2020 10:52:45.582 RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction)
Committing transaction.
dbug: 10/6/2020 10:52:45.585 RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction)
Committed transaction.
Konten ini dapat dikustomisasi dengan meneruskan nilai dari DbContextLoggerOptions, seperti yang ditunjukkan di bagian berikut.
Tip
Pertimbangkan untuk menggunakan Microsoft.Extensions.Logging untuk kontrol lebih besar atas pemformatan log.
Menggunakan waktu UTC
Secara default, tanda waktu dirancang untuk konsumsi lokal saat penelusuran kesalahan. Gunakan DbContextLoggerOptions.DefaultWithUtcTime untuk menggunakan tanda waktu UTC budaya-agnostik sebagai gantinya, tetapi menjaga segala sesuatu yang lain tetap sama. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(
Console.WriteLine,
LogLevel.Debug,
DbContextLoggerOptions.DefaultWithUtcTime);
Contoh ini menghasilkan pemformatan log berikut:
info: 2020-10-06T17:55:39.0333701Z RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command)
Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']
CREATE TABLE "Blogs" (
"Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT,
"Name" INTEGER NOT NULL
);
dbug: 2020-10-06T17:55:39.0333892Z RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction)
Committing transaction.
dbug: 2020-10-06T17:55:39.0351684Z RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction)
Committed transaction.
Pengelogan baris tunggal
Terkadang berguna untuk mendapatkan tepat satu baris per pesan log. Ini dapat diaktifkan oleh DbContextLoggerOptions.SingleLine. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(
Console.WriteLine,
LogLevel.Debug,
DbContextLoggerOptions.DefaultWithLocalTime | DbContextLoggerOptions.SingleLine);
Contoh ini menghasilkan pemformatan log berikut:
info: 10/6/2020 10:52:45.723 RelationalEventId.CommandExecuted[20101] (Microsoft.EntityFrameworkCore.Database.Command) -> Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']CREATE TABLE "Blogs" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT, "Name" INTEGER NOT NULL);
dbug: 10/6/2020 10:52:45.723 RelationalEventId.TransactionCommitting[20210] (Microsoft.EntityFrameworkCore.Database.Transaction) -> Committing transaction.
dbug: 10/6/2020 10:52:45.725 RelationalEventId.TransactionCommitted[20202] (Microsoft.EntityFrameworkCore.Database.Transaction) -> Committed transaction.
Opsi konten lainnya
Bendera lain di DbContextLoggerOptions dapat digunakan untuk memangkas jumlah metadata yang disertakan dalam log. Ini dapat berguna bersama dengan pengelogan baris tunggal. Contohnya:
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(
Console.WriteLine,
LogLevel.Debug,
DbContextLoggerOptions.UtcTime | DbContextLoggerOptions.SingleLine);
Contoh ini menghasilkan pemformatan log berikut:
2020-10-06T17:52:45.7320362Z -> Executed DbCommand (0ms) [Parameters=[], CommandType='Text', CommandTimeout='30']CREATE TABLE "Blogs" ( "Id" INTEGER NOT NULL CONSTRAINT "PK_Blogs" PRIMARY KEY AUTOINCREMENT, "Name" INTEGER NOT NULL);
2020-10-06T17:52:45.7320531Z -> Committing transaction.
2020-10-06T17:52:45.7339441Z -> Committed transaction.
Berpindah dari EF6
Pengelogan sederhana EF Core berbeda dari Database.Log di EF6 dengan dua cara penting:
- Pesan log tidak terbatas hanya pada interaksi database
- Pengelogan harus dikonfigurasi pada waktu inisialisasi konteks
Untuk perbedaan pertama, pemfilteran yang dijelaskan di atas dapat digunakan untuk membatasi pesan mana yang dicatat.
Perbedaan kedua adalah perubahan yang disengaja untuk meningkatkan performa dengan tidak menghasilkan pesan log saat tidak diperlukan. Namun, masih mungkin untuk mendapatkan perilaku yang sama dengan EF6 dengan membuat Log
properti pada Anda DbContext
dan kemudian menggunakannya hanya ketika telah ditetapkan. Contohnya:
public Action<string> Log { get; set; }
protected override void OnConfiguring(DbContextOptionsBuilder optionsBuilder)
=> optionsBuilder.LogTo(s => Log?.Invoke(s));
Saran dan Komentar
https://aka.ms/ContentUserFeedback.
Segera hadir: Sepanjang tahun 2024 kami akan menghentikan penggunaan GitHub Issues sebagai mekanisme umpan balik untuk konten dan menggantinya dengan sistem umpan balik baru. Untuk mengetahui informasi selengkapnya, lihat:Kirim dan lihat umpan balik untuk