Pengelogan HTTP di ASP.NET Core
Catatan
Ini bukan versi terbaru dari artikel ini. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Peringatan
Versi ASP.NET Core ini tidak lagi didukung. Untuk informasi selengkapnya, lihat Kebijakan Dukungan .NET dan .NET Core. Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Penting
Informasi ini berkaitan dengan produk pra-rilis yang mungkin dimodifikasi secara substansial sebelum dirilis secara komersial. Microsoft tidak memberikan jaminan, tersirat maupun tersurat, sehubungan dengan informasi yang diberikan di sini.
Untuk rilis saat ini, lihat versi .NET 8 dari artikel ini.
Pengelogan HTTP adalah middleware yang mencatat informasi tentang permintaan HTTP masuk dan respons HTTP. Pengelogan HTTP menyediakan log dari:
- Informasi permintaan HTTP
- Properti umum
- Header
- Isi
- Informasi respons HTTP
Pengelogan HTTP dapat:
- Catat semua permintaan dan respons atau hanya permintaan dan respons yang memenuhi kriteria tertentu.
- Pilih bagian mana dari permintaan dan respons yang dicatat.
- Memungkinkan Anda untuk meredaksi informasi sensitif dari log.
Pengelogan HTTP dapat mengurangi performa aplikasi, terutama saat mencatat isi permintaan dan respons. Pertimbangkan dampak performa saat memilih bidang yang akan dicatat. Uji dampak performa dari properti pengelogan yang dipilih.
Peringatan
Pengelogan HTTP berpotensi mencatat informasi pengidentifikasi pribadi (PII). Pertimbangkan risikonya dan hindari pengelogan informasi sensitif.
Aktifkan pengelogan HTTP
Pengelogan HTTP diaktifkan dengan memanggil AddHttpLogging dan UseHttpLogging, seperti yang ditunjukkan dalam contoh berikut:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.Run();
Lambda kosong dalam contoh panggilan AddHttpLogging
sebelumnya menambahkan middleware dengan konfigurasi default. Secara default, log pengelogan HTTP mencatat properti umum seperti jalur, kode status, dan header untuk permintaan dan respons.
Tambahkan baris berikut ke file appsettings.Development.json
di tingkat "LogLevel": {
sehingga log HTTP ditampilkan:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Dengan konfigurasi default, permintaan dan respons dicatat sebagai sepasang pesan yang mirip dengan contoh berikut:
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Protocol: HTTP/2
Method: GET
Scheme: https
PathBase:
Path: /
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Host: localhost:52941
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36 Edg/118.0.2088.61
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Upgrade-Insecure-Requests: [Redacted]
sec-ch-ua: [Redacted]
sec-ch-ua-mobile: [Redacted]
sec-ch-ua-platform: [Redacted]
sec-fetch-site: [Redacted]
sec-fetch-mode: [Redacted]
sec-fetch-user: [Redacted]
sec-fetch-dest: [Redacted]
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
StatusCode: 200
Content-Type: text/plain; charset=utf-8
Date: Tue, 24 Oct 2023 02:03:53 GMT
Server: Kestrel
Opsi pengelogan HTTP
Untuk mengonfigurasi opsi global untuk middleware pengelogan HTTP, panggil AddHttpLogging di Program.cs
, menggunakan lambda untuk mengonfigurasi HttpLoggingOptions.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Catatan
Dalam sampel sebelumnya dan sampel berikut, UseHttpLogging
dipanggil setelah UseStaticFiles
, sehingga pengelogan HTTP tidak diaktifkan untuk file statis. Untuk mengaktifkan pengelogan HTTP file statis, panggil UseHttpLogging
sebelum UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
adalah bendera enum yang mengonfigurasi bagian tertentu dari permintaan dan respons terhadap log. HttpLoggingOptions.LoggingFields
defaultnya adalah RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
dan ResponseHeaders
RequestHeaders dan ResponseHeaders merupakan set header HTTP yang dicatat. Nilai header hanya dicatat untuk nama header yang ada di koleksi ini. Kode berikut menambahkan sec-ch-ua
ke RequestHeaders, sehingga nilai sec-ch-ua
header dicatat. Dan menambahkan MyResponseHeader
ke ResponseHeaders, sehingga nilai MyResponseHeader
header dicatat. Jika baris ini dihapus, nilai header ini adalah [Redacted]
.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
MediaTypeOptions
MediaTypeOptions menyediakan konfigurasi untuk memilih pengodean mana yang akan digunakan untuk jenis media tertentu.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Pendekatan ini juga dapat digunakan untuk mengaktifkan pengelogan untuk data yang tidak dicatat secara default (misalnya, data formulir, yang mungkin memiliki jenis media seperti application/x-www-form-urlencoded
atau multipart/form-data
).
Metode MediaTypeOptions
RequestBodyLogLimit
dan ResponseBodyLogLimit
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
CombineLogs
Pengaturan CombineLogs untuk true
mengonfigurasi middleware untuk mengonsolidasikan semua log yang diaktifkan untuk permintaan dan respons ke dalam satu log di akhir. Ini termasuk permintaan, isi permintaan, respons, isi respons, dan durasi.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
logging.CombineLogs = true;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Konfigurasi khusus titik akhir
Untuk konfigurasi khusus titik akhir di aplikasi API minimal, WithHttpLogging metode ekstensi tersedia. Contoh berikut menunjukkan cara mengonfigurasi pengelogan HTTP untuk satu titik akhir:
app.MapGet("/response", () => "Hello World! (logging response)")
.WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);
Untuk konfigurasi khusus titik akhir di aplikasi yang menggunakan pengontrol, [HttpLogging]
atribut tersedia. Atribut juga dapat digunakan dalam aplikasi API minimal, seperti yang ditunjukkan dalam contoh berikut:
app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
() => "Hello World! (logging duration)");
IHttpLoggingInterceptor
IHttpLoggingInterceptor adalah antarmuka untuk layanan yang dapat diimplementasikan untuk menangani panggilan balik per permintaan dan per respons untuk menyesuaikan detail apa yang dicatat. Setiap pengaturan log khusus titik akhir diterapkan terlebih dahulu dan kemudian dapat ditimpa dalam panggilan balik ini. Implementasi dapat:
- Periksa permintaan atau respons.
- Aktifkan atau nonaktifkan .HttpLoggingFields
- Sesuaikan berapa banyak isi permintaan atau respons yang dicatat.
- Tambahkan bidang kustom ke log.
IHttpLoggingInterceptor
Daftarkan implementasi dengan memanggil AddHttpLoggingInterceptor<T>
di Program.cs
. Jika beberapa IHttpLoggingInterceptor
instans terdaftar, instans tersebut dijalankan dalam urutan terdaftar.
Contoh berikut menunjukkan cara mendaftarkan IHttpLoggingInterceptor
implementasi:
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();
Contoh berikut adalah IHttpLoggingInterceptor
implementasi yang:
- Memeriksa metode permintaan dan menonaktifkan pengelogan untuk permintaan POST.
- Untuk permintaan non-POST:
- Meredaksi jalur permintaan, header permintaan, dan header respons.
- Menambahkan bidang kustom dan nilai bidang ke log permintaan dan respons.
using Microsoft.AspNetCore.HttpLogging;
namespace HttpLoggingSample;
internal sealed class SampleHttpLoggingInterceptor : IHttpLoggingInterceptor
{
public ValueTask OnRequestAsync(HttpLoggingInterceptorContext logContext)
{
if (logContext.HttpContext.Request.Method == "POST")
{
// Don't log anything if the request is a POST.
logContext.LoggingFields = HttpLoggingFields.None;
}
// Don't enrich if we're not going to log any part of the request.
if (!logContext.IsAnyEnabled(HttpLoggingFields.Request))
{
return default;
}
if (logContext.TryDisable(HttpLoggingFields.RequestPath))
{
RedactPath(logContext);
}
if (logContext.TryDisable(HttpLoggingFields.RequestHeaders))
{
RedactRequestHeaders(logContext);
}
EnrichRequest(logContext);
return default;
}
public ValueTask OnResponseAsync(HttpLoggingInterceptorContext logContext)
{
// Don't enrich if we're not going to log any part of the response
if (!logContext.IsAnyEnabled(HttpLoggingFields.Response))
{
return default;
}
if (logContext.TryDisable(HttpLoggingFields.ResponseHeaders))
{
RedactResponseHeaders(logContext);
}
EnrichResponse(logContext);
return default;
}
private void RedactPath(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter(nameof(logContext.HttpContext.Request.Path), "RedactedPath");
}
private void RedactRequestHeaders(HttpLoggingInterceptorContext logContext)
{
foreach (var header in logContext.HttpContext.Request.Headers)
{
logContext.AddParameter(header.Key, "RedactedHeader");
}
}
private void EnrichRequest(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter("RequestEnrichment", "Stuff");
}
private void RedactResponseHeaders(HttpLoggingInterceptorContext logContext)
{
foreach (var header in logContext.HttpContext.Response.Headers)
{
logContext.AddParameter(header.Key, "RedactedHeader");
}
}
private void EnrichResponse(HttpLoggingInterceptorContext logContext)
{
logContext.AddParameter("ResponseEnrichment", "Stuff");
}
}
Dengan pencegat ini, permintaan POST tidak menghasilkan log apa pun bahkan jika pengelogan HTTP dikonfigurasi untuk mencatat HttpLoggingFields.All
. Permintaan GET menghasilkan log yang mirip dengan contoh berikut:
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[1]
Request:
Path: RedactedPath
Accept: RedactedHeader
Host: RedactedHeader
User-Agent: RedactedHeader
Accept-Encoding: RedactedHeader
Accept-Language: RedactedHeader
Upgrade-Insecure-Requests: RedactedHeader
sec-ch-ua: RedactedHeader
sec-ch-ua-mobile: RedactedHeader
sec-ch-ua-platform: RedactedHeader
sec-fetch-site: RedactedHeader
sec-fetch-mode: RedactedHeader
sec-fetch-user: RedactedHeader
sec-fetch-dest: RedactedHeader
RequestEnrichment: Stuff
Protocol: HTTP/2
Method: GET
Scheme: https
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[2]
Response:
Content-Type: RedactedHeader
MyResponseHeader: RedactedHeader
ResponseEnrichment: Stuff
StatusCode: 200
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[4]
ResponseBody: Hello World!
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[8]
Duration: 2.2778ms
Urutan konfigurasi pengelogan prioritas
Daftar berikut menunjukkan urutan prioritas untuk konfigurasi pengelogan:
- Konfigurasi global dari HttpLoggingOptions, diatur dengan memanggil AddHttpLogging.
- Konfigurasi khusus titik akhir
[HttpLogging]
dari atribut atau WithHttpLogging metode ekstensi mengambil alih konfigurasi global. IHttpLoggingInterceptor
dipanggil dengan hasil dan dapat memodifikasi konfigurasi lebih lanjut per permintaan.
Pengelogan HTTP adalah middleware yang mencatat informasi tentang permintaan HTTP dan respons HTTP. Pengelogan HTTP menyediakan log dari:
- Informasi permintaan HTTP
- Properti umum
- Header
- Isi
- Informasi respons HTTP
Pengelogan HTTP berguna dalam beberapa skenario untuk:
- Mencatat informasi tentang permintaan dan respons yang masuk.
- Memfilter bagian mana dari permintaan dan respons yang dicatat.
- Memfilter header mana yang akan dicatat.
Pengelogan HTTP dapat mengurangi performa aplikasi, terutama saat melakukan pengelogan badan permintaan dan respons. Pertimbangkan dampak performa saat memilih bidang yang akan dicatat. Uji dampak performa dari properti pengelogan yang dipilih.
Peringatan
Pengelogan HTTP berpotensi dapat mencatat informasi pengidentifikasi pribadi (PII). Pertimbangkan risikonya dan hindari pengelogan informasi sensitif.
Mengaktifkan pengelogan HTTP
Pengelogan HTTP diaktifkan dengan UseHttpLogging, yang menambahkan middleware pengelogan HTTP.
var builder = WebApplication.CreateBuilder(args);
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Hello World!");
app.Run();
Secara default, Pengelogan HTTP mencatat properti umum seperti jalur, kode status, dan header untuk permintaan dan respons. Tambahkan baris berikut ke file appsettings.Development.json
di tingkat "LogLevel": {
sehingga log HTTP ditampilkan:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
Outputnya dicatat sebagai satu pesan di LogLevel.Information
.
Opsi Pengelogan HTTP
Untuk mengonfigurasi middleware pengelogan HTTP, panggil AddHttpLogging di Program.cs
.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Catatan
Dalam sampel sebelumnya dan sampel berikut, UseHttpLogging
dipanggil setelah UseStaticFiles
, sehingga pengelogan HTTP tidak diaktifkan untuk file statis. Untuk mengaktifkan pengelogan HTTP file statis, panggil UseHttpLogging
sebelum UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
adalah bendera enum yang mengonfigurasi bagian tertentu dari permintaan dan respons terhadap log. HttpLoggingOptions.LoggingFields
defaultnya adalah RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders.
RequestHeaders
Headers adalah sekumpulan Header Permintaan HTTP yang diizinkan untuk dicatat. Nilai header hanya dicatat untuk nama header yang ada di koleksi ini. Kode berikut mencatat "sec-ch-ua"
header permintaan. Jika logging.RequestHeaders.Add("sec-ch-ua");
dihapus, nilai header permintaan "sec-ch-ua"
akan dihapus. Kode yang disorot berikut memanggil HttpLoggingOptions.RequestHeaders
dan HttpLoggingOptions.ResponseHeaders
:
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
MediaTypeOptions
MediaTypeOptions menyediakan konfigurasi untuk memilih pengodean mana yang akan digunakan untuk jenis media tertentu.
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
Pendekatan ini juga dapat digunakan untuk mengaktifkan pengelogan untuk data yang tidak dicatat secara default. Misalnya, data formulir, yang mungkin memiliki jenis media seperti application/x-www-form-urlencoded
atau multipart/form-data
.
Metode MediaTypeOptions
RequestBodyLogLimit
dan ResponseBodyLogLimit
using Microsoft.AspNetCore.HttpLogging;
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.All;
logging.RequestHeaders.Add("sec-ch-ua");
logging.ResponseHeaders.Add("MyResponseHeader");
logging.MediaTypeOptions.AddText("application/javascript");
logging.RequestBodyLogLimit = 4096;
logging.ResponseBodyLogLimit = 4096;
});
var app = builder.Build();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseHttpLogging();
app.Use(async (context, next) =>
{
context.Response.Headers["MyResponseHeader"] =
new string[] { "My Response Header Value" };
await next();
});
app.MapGet("/", () => "Hello World!");
app.Run();
ASP.NET Core