참고 항목
이 문서의 최신 버전은 아닙니다. 현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
중요합니다
이 정보는 상업적으로 출시되기 전에 실질적으로 수정될 수 있는 시험판 제품과 관련이 있습니다. Microsoft는 여기에 제공된 정보에 대해 어떠한 명시적, 또는 묵시적인 보증을 하지 않습니다.
현재 릴리스는 이 문서의 .NET 9 버전을 참조 하세요.
HTTP 로깅은 들어오는 HTTP 요청 및 HTTP 응답에 대한 정보를 기록하는 미들웨어입니다. HTTP 로깅은 다음의 로그를 제공합니다.
- HTTP 요청 정보
- 일반 속성
- 헤더
- 본문
- HTTP 응답 정보
HTTP 로깅은 다음을 수행할 수 있습니다.
- 모든 요청 및 응답 또는 특정 조건을 충족하는 요청 및 응답만 기록합니다.
- 요청 및 응답이 기록되는 부분을 선택합니다.
- 로그에서 중요한 정보를 수정할 수 있습니다.
HTTP 로깅 은 특히 요청 및 응답 본문을 로깅할 때 앱의 성능을 저하시킬 수 있습니다. 로그할 필드를 선택할 때 성능에 미치는 영향을 고려하고 선택한 로깅 속성이 성능에 미치는 영향을 테스트하세요.
경고
HTTP 로깅은 PII(개인 식별 정보)를 기록할 수 있습니다. 위험성을 고려해 중요한 정보를 로그하지 않도록 하세요. 편집에 대한 자세한 내용은 중요한 데이터 수정을 확인하세요.
HTTP 로깅 사용
HTTP 로깅은 다음 예제와 같이 호출 AddHttpLogging 하여 사용하도록 설정됩니다 UseHttpLogging.
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();
이전 호출 AddHttpLogging
예제의 빈 람다는 기본 구성을 사용하여 미들웨어를 추가합니다. 기본적으로 HTTP 로깅은 요청 및 응답에 대한 경로, 상태 코드 및 헤더와 같은 일반적인 속성을 기록합니다.
HTTP 로그가 표시되도록 appsettings.Development.json
수준에서 다음 줄을 "LogLevel": {
파일에 추가:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
기본 구성을 사용하면 요청 및 응답이 다음 예제와 유사한 메시지 쌍으로 기록됩니다.
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
HTTP 로깅 옵션
HTTP 로깅 미들웨어에 대한 전역 옵션을 구성하려면 람다를 사용하여 호출 AddHttpLoggingProgram.cs
하여 구성 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();
참고 항목
앞의 샘플과 다음 샘플에서는 UseHttpLogging
다음에 UseStaticFiles
가 호출되므로 정적 파일에 대해 HTTP 로깅이 활성화되지 않습니다. 정적 파일 HTTP 로깅을 사용하도록 설정하려면 앞에 호출 UseHttpLogging
합니다 UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
는 로그 요청 및 응답의 특정 부분을 구성하는 열거형 플래그입니다.
LoggingFields
기본값은 RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders입니다.
RequestHeaders
및 ResponseHeaders
RequestHeaders 로 ResponseHeaders 깅되는 HTTP 헤더 집합입니다. 헤더 값은 이러한 컬렉션에 있는 헤더 이름에 대해서만 기록됩니다. 헤더 값 sec-ch-ua
이 RequestHeaders기록되도록 다음 코드가 추가 sec-ch-ua
됩니다.
MyResponseHeader
헤더 값 ResponseHeaders 이 MyResponseHeader
기록되도록 추가됩니다. 이러한 줄이 제거되면 이러한 헤더의 값은 다음과 같습니다 [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는 특정 미디어 유형에 사용할 인코딩을 선택하기 위한 구성을 제공합니다.
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();
이 방법은 기본적으로 기록되지 않은 데이터에 대한 로깅을 사용하도록 설정하는 데도 사용할 수 있습니다(예: 양식 데이터, 미디어 형식 또는 application/x-www-form-urlencoded
같은 multipart/form-data
형식이 있을 수 있음).
MediaTypeOptions
메서드
RequestBodyLogLimit
및 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
요청 및 응답에 CombineLogs 대해 사용하도록 설정된 모든 로그를 마지막에 하나의 로그에 통합하도록 미들웨어를 구성하도록 설정합니다true
. 여기에는 요청, 요청 본문, 응답, 응답 본문 및 기간이 포함됩니다.
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();
엔드포인트별 구성
최소 API 앱의 엔드포인트별 구성의 경우 확장 메서드를 WithHttpLogging 사용할 수 있습니다. 다음 예제에서는 하나의 엔드포인트에 대해 HTTP 로깅을 구성하는 방법을 보여 줍니다.
app.MapGet("/response", () => "Hello World! (logging response)")
.WithHttpLogging(HttpLoggingFields.ResponsePropertiesAndHeaders);
컨트롤러를 사용하는 앱의 엔드포인트별 구성에는 [HttpLogging]
특성을 사용할 수 있습니다. 이 특성은 다음 예제와 같이 최소 API 앱에서도 사용할 수 있습니다.
app.MapGet("/duration", [HttpLogging(loggingFields: HttpLoggingFields.Duration)]
() => "Hello World! (logging duration)");
IHttpLoggingInterceptor
IHttpLoggingInterceptor 는 기록되는 세부 정보를 사용자 지정하기 위해 요청당 및 응답별 콜백을 처리하도록 구현할 수 있는 서비스의 인터페이스입니다. 엔드포인트별 로그 설정이 먼저 적용된 다음 이러한 콜백에서 재정의될 수 있습니다. 구현은 다음을 수행할 수 있습니다.
- 요청 또는 응답을 검사합니다.
- 을 사용하거나 사용하지 않도록 설정합니다 HttpLoggingFields.
- 기록되는 요청 또는 응답 본문의 양을 조정합니다.
- 로그에 사용자 지정 필드를 추가합니다.
에서 IHttpLoggingInterceptor 호출 AddHttpLoggingInterceptor 하여 구현을 등록합니다 Program.cs
. 여러 IHttpLoggingInterceptor 인스턴스가 등록된 경우 등록된 순서대로 실행됩니다.
다음 예제에서는 구현을 등록하는 IHttpLoggingInterceptor 방법을 보여줍니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(logging =>
{
logging.LoggingFields = HttpLoggingFields.Duration;
});
builder.Services.AddHttpLoggingInterceptor<SampleHttpLoggingInterceptor>();
다음 예제는 구현입니다.IHttpLoggingInterceptor
- 요청 메서드를 검사하고 POST 요청에 대한 로깅을 사용하지 않도록 설정합니다.
- POST가 아닌 요청의 경우:
- 요청 경로, 요청 헤더 및 응답 헤더를 수정합니다.
- 요청 및 응답 로그에 사용자 지정 필드 및 필드 값을 추가합니다.
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");
}
}
이 인터셉터를 사용하면 HTTP 로깅이 로깅되도록 구성된 경우에도 POST 요청이 로그 HttpLoggingFields.All
를 생성하지 않습니다. GET 요청은 다음 예제와 유사한 로그를 생성합니다.
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
우선 순위의 로깅 구성 순서
다음 목록에서는 로깅 구성의 우선 순위 순서를 보여 줍니다.
- 에서 전역 구성 HttpLoggingOptions, 호출 AddHttpLogging을 통해 설정합니다.
-
[HttpLogging]
속성 또는 WithHttpLogging 확장 메서드의 엔드포인트별 구성은 전역 구성을 재정의합니다. -
IHttpLoggingInterceptor
는 결과와 함께 호출되며 요청당 구성을 추가로 수정할 수 있습니다.
HTTP 로깅은 들어오는 HTTP 요청 및 HTTP 응답에 대한 정보를 로그하는 미들웨어입니다. HTTP 로깅은 다음의 로그를 제공합니다.
- HTTP 요청 정보
- 일반 속성
- 헤더
- 본문
- HTTP 응답 정보
HTTP 로깅이 유용한 몇 가지 시나리오는 다음과 같습니다.
- 들어오는 요청 및 응답에 대한 정보를 기록합니다.
- 요청 및 응답의 어느 부분이 로그되는지 필터링합니다.
- 로그할 헤더를 필터링합니다.
HTTP 로깅은 특히 요청 및 응답 본문을 로그할 때 앱의 성능을 저하시킬 수 있습니다. 로그할 필드를 선택할 때 성능에 미치는 영향을 고려하고 선택한 로깅 속성이 성능에 미치는 영향을 테스트하세요.
경고
HTTP 로깅 사용 시 PII(개인 식별 정보)가 로그될 가능성이 있습니다. 위험성을 고려해 중요한 정보를 로그하지 않도록 하세요.
HTTP 로깅 사용
HTTP 로깅은 HTTP 로깅 미들웨어를 추가하는 UseHttpLogging을 통해 사용할 수 있습니다.
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();
기본적으로 HTTP 로깅은 요청 및 응답에 대한 경로, 상태 코드, 헤더와 같은 공통 속성을 로그합니다. HTTP 로그가 표시되도록 appsettings.Development.json
수준에서 다음 줄을 "LogLevel": {
파일에 추가:
"Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware": "Information"
출력은 LogLevel.Information
에서 단일 메시지로 로그됩니다.
HTTP 로깅 옵션
HTTP 로깅 미들웨어를 구성하려면 AddHttpLogging에서 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();
참고 항목
앞의 샘플 및 다음 샘플 UseHttpLogging
에서는 정 UseStaticFiles
적 파일에 대해 HTTP 로깅을 사용할 수 없도록 호출됩니다. 정적 파일 HTTP 로깅을 사용하도록 설정하려면 앞에 호출 UseHttpLogging
합니다 UseStaticFiles
.
LoggingFields
HttpLoggingOptions.LoggingFields
는 로그 요청 및 응답의 특정 부분을 구성하는 열거형 플래그입니다.
HttpLoggingOptions.LoggingFields
기본값은 RequestPropertiesAndHeaders | ResponsePropertiesAndHeaders입니다.
RequestHeaders
Headers는 로그할 수 있는 HTTP 요청 헤더의 집합입니다. 헤더 값은 이 컬렉션에 있는 헤더 이름에 대해서만 로그됩니다. 다음 코드는 요청 헤더 "sec-ch-ua"
를 로그합니다.
logging.RequestHeaders.Add("sec-ch-ua");
가 제거된 경우 요청 헤더 "sec-ch-ua"
의 값이 수정됩니다. 다음 강조 표시된 코드는 HttpLoggingOptions.RequestHeaders
및 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는 특정 미디어 유형에 사용할 인코딩을 선택하기 위한 구성을 제공합니다.
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();
이 방법을 사용하여 기본적으로 기록되지 않은 데이터에 대한 로깅을 사용하도록 설정할 수도 있습니다. 예를 들어 미디어 형식(예: application/x-www-form-urlencoded
또는 multipart/form-data
.)을 가질 수 있는 양식 데이터입니다.
MediaTypeOptions
메서드
RequestBodyLogLimit
및 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();
중요한 데이터 수정
AddHttpLoggingRedaction를 호출하여 편집과 함께 Http 로깅을 활성화할 수 있습니다.
.NET의 데이터 삭제 라이브러리에 대한 자세한 내용은 .NET의 데이터 삭제에서 참조하세요.
로깅 편집 옵션
편집을 포함한 로깅 옵션을 구성하려면, AddHttpLoggingRedaction를 Program.cs
에서 호출하여 람다로 LoggingRedactionOptions를 구성합니다.
using Microsoft.Extensions.Compliance.Classification;
namespace HttpLoggingSample
{
public static class MyTaxonomyClassifications
{
public static string Name => "MyTaxonomy";
public static DataClassification Private => new(Name, nameof(Private));
public static DataClassification Public => new(Name, nameof(Public));
public static DataClassification Personal => new(Name, nameof(Personal));
}
}
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
이전 편집 구성에서는 출력이 다음과 유사합니다.
info: Microsoft.AspNetCore.HttpLogging.HttpLoggingMiddleware[9]
Request and Response:
server.address: localhost:61361
Path: /
http.request.header.accept:
Protocol: HTTP/2
Method: GET
Scheme: https
http.response.header.content-type:
StatusCode: 200
Duration: 8.4684
info: Microsoft.AspNetCore.Hosting.Diagnostics[2]
Request finished HTTP/2 GET https://localhost:61361/ - 200 - text/plain;+charset=utf-8 105.5334ms
참고 항목
요청 경로 /home
는 속성에 포함되어 ExcludePathStartsWith
있으므로 기록되지 않습니다.
http.request.header.accept
및 http.response.header.content-type
는 Microsoft.Extensions.Compliance.Redaction.ErasingRedactor에 의해 삭제되었습니다.
RequestPathLoggingMode
RequestPathLoggingMode는 요청 경로가 로깅되는 방법을 결정합니다. Formatted
여부 또는 Structured
여부가 IncomingPathLoggingMode에 의해 설정됩니다.
-
Formatted
: 매개 변수 없이 요청 경로를 기록합니다. -
Structured
: 매개 변수가 포함된 요청 경로를 기록합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RequestPathParameterRedactionMode
RequestPathParameterRedactionMode는 요청 경로의 경로 매개 변수를 Strict
, Loose
, None
중 하나로 마스킹하는 방법을 HttpRouteParameterRedactionMode에 의해 설정합니다.
-
Strict
: 요청 경로 매개 변수는 중요한 것으로 간주되고, 데이터 분류를 사용하여 명시적 주석이 필요하며, 기본적으로 수정됩니다. -
Loose
: 모든 매개 변수는 민감하지 않은 것으로 간주되며 기본적으로 as-is에 포함됩니다. -
None
: 경로 매개 변수는 데이터 분류 주석이 있는지와 관계없이 수정되지 않습니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RequestHeadersDataClasses
RequestHeadersDataClasses 는 요청 헤더를 데이터 분류에 매핑하여 수정 방법을 결정합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
ResponseHeadersDataClasses
ResponseHeadersDataClasses는 RequestHeadersDataClasses와 비슷하지만 응답 헤더에 관한 것입니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
RouteParameterDataClasses
RouteParameterDataClasses 는 경로 매개 변수를 데이터 분류에 매핑합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
ExcludePathStartsWith
ExcludePathStartsWith 로깅에서 완전히 제외해야 하는 경로를 지정합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
IncludeUnmatchedRoutes
IncludeUnmatchedRoutes 는 일치하지 않는 경로를 보고할 수 있습니다.
true
로 설정되면, 라우팅으로 식별되지 않는 경로의 전체 경로를 기록하며, 경로 특성의 값을 기록하는 대신 Unknown
를 사용합니다.
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddHttpLogging(o => { });
builder.Services.AddRedaction();
builder.Services.AddHttpLoggingRedaction(op =>
{
op.RequestPathParameterRedactionMode = HttpRouteParameterRedactionMode.None;
op.RequestPathLoggingMode = IncomingPathLoggingMode.Formatted;
op.RequestHeadersDataClasses.Add(HeaderNames.Accept, MyTaxonomyClassifications.Public);
op.ResponseHeadersDataClasses.Add(HeaderNames.ContentType, MyTaxonomyClassifications.Private);
op.RouteParameterDataClasses = new Dictionary<string, DataClassification>
{
{ "one", MyTaxonomyClassifications.Personal },
};
// Add the paths that should be filtered, with a leading '/'.
op.ExcludePathStartsWith.Add("/home");
op.IncludeUnmatchedRoutes = true;
});
var app = builder.Build();
app.UseHttpLogging();
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.MapGet("/", () => "Logged!");
app.MapGet("/home", () => "Not logged!");
app.Run();
ASP.NET Core