사용자 클레임의 일부 정보를 기록하려는 목적으로 Building a Simple Sink 예제를 사용하여 ILogEventSink
을 구현하는 자체 SeriLog 싱크를 만듭니다. 코어에서 HttpContext에 액세스하려면 일반적으로 IHttpContextAccessor
의 인스턴스를 삽입하지만 예제에서는 확장 메서드에서 싱크의 인스턴스를 만드는 예를 보여줍니다. SeriLog 싱크에서 현재 HttpContext를 가져 오는 방법은 무엇입니까?
public class MySink : ILogEventSink
{
private readonly IFormatProvider _formatProvider;
public MySink(IFormatProvider formatProvider)
{
_formatProvider = formatProvider;
}
public void Emit(LogEvent logEvent)
{
// How to get HttpContext here?
}
}
public static class MySinkExtensions
{
public static LoggerConfiguration MySink(
this LoggerSinkConfiguration loggerConfiguration,
IFormatProvider formatProvider = null)
{
return loggerConfiguration.Sink(new MySink(formatProvider));
}
}
... 다음 싱크를 사용하는 ...
var log = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.MySink()
.CreateLogger();
어떻게 싱크대의 방출 방법에서 현재 HttpContext에 대한 액세스를 얻을 수 있습니까? 또는 예를 들어 DI 프레임 워크에서 싱크대를 만들 수 있습니까?
Serilog.AspNetCore v2.1.0을 사용하는 .Net 4.6.2 런타임에 대해 Asp.Net Core 2 프레임 워크를 실행하는 MVC 사이트가 있습니다.
업데이트 - 나는 아래의 코드와 유사 미들웨어 만들어 @tsimbalar에서 포인터 후 해결
. 내 StartUp.Configure
메서드에서 app.UseMiddleware<ClaimsMiddleware>();
을 사용하여 추가합니다. 이후 앱 인증 단계가 발생했습니다 (그렇지 않으면 클레임이로드되지 않습니다).
public class ClaimsMiddleware
{
private static readonly ILogger Log = Serilog.Log.ForContext<ClaimsMiddleware>();
private readonly RequestDelegate next;
public ClaimsMiddleware(RequestDelegate next)
{
this.next = next ?? throw new ArgumentNullException(nameof(next));
}
public async Task Invoke(HttpContext httpContext)
{
if (httpContext == null) throw new ArgumentNullException(nameof(httpContext));
// Get values from claims here
var myVal = httpContext
.User
.Claims
.Where(x => x.Type == "MyVal")
.Select(x => x.Value)
.DefaultIfEmpty(string.Empty)
.SingleOrDefault();
using (LogContext.PushProperty("MyVal", myVal))
{
try
{
await next(httpContext);
}
// Never caught, because `LogException()` returns false.
catch (Exception ex) when (LogException(httpContext, ex)) { }
}
}
private static bool LogException(HttpContext httpContext, Exception ex)
{
var logForContext = Log.ForContext("StackTrace", ex.StackTrace);
logForContext.Error(ex, ex.Message);
return false;
}
}
감사 @tsimbalar. ** configure ** 단계에서 당신은'contextAccessor'를'MyEnricher' 객체의 인스턴스로 넘깁니다. 이것은 의존성 주입을 사용하지 않기 때문에, Startup (그리고 그 이후에'ConfigureServices')이 호출되기 전에 Program Main 메서드에서 로깅을 설정한다면 어떻게 컨텍스트를 얻게 될까요? –
오, 예, 당신이 프로그램 메인에 있다면, 그건 작동하지 않을 수 있습니다 .... mmmm 어떻게 작동 할 수 있을지 모르겠다 – tsimbalar
@ gavin 난 내 대답을 – tsimbalar