Tôi đang tạo bồn rửa SeriLog của riêng mình triển khai ILogEventSink
sử dụng ví dụ Building a Simple Sink với mục đích ghi nhật ký một số thông tin từ xác nhận quyền sở hữu của người dùng. Để truy cập vào HttpContext trong Core, tôi thường tiêm vào một thể hiện của IHttpContextAccessor
nhưng ví dụ này cho thấy việc tạo một thể hiện của bồn rửa trong một phương thức mở rộng, ví dụ:Làm thế nào tôi có thể nhận được HttpContext hiện tại trong một SeriLog Sink?
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));
}
}
... sau đó sử dụng bồn rửa chén ...
var log = new LoggerConfiguration()
.MinimumLevel.Information()
.WriteTo.MySink()
.CreateLogger();
Làm thế nào tôi có thể nhận được quyền truy cập vào các HttpContext hiện trong phương pháp Emit của bồn rửa chén? Hoặc là nó có thể có bồn rửa được tạo ra bởi khuôn khổ DI ví dụ ?!
Tôi có trang web MVC chạy khuôn khổ Asp.Net Core 2 dựa trên thời gian chạy Net 4.6.2 bằng Serilog.AspNetCore v2.1.0.
Update - Cách giải quyết
Sau khi con trỏ từ @tsimbalar Tôi tạo ra middleware tương tự như mã dưới đây. Trong phương pháp StartUp.Configure
tôi thêm nó bằng cách sử dụng app.UseMiddleware<ClaimsMiddleware>();
sau bước xác thực ứng dụng đã xảy ra (nếu không sẽ không có xác nhận quyền sở hữu nào được tải).
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;
}
}
Cảm ơn @tsimbalar. Trong bước ** configure ** bạn đang chuyển 'contextAccessor' vào một cá thể của đối tượng' MyEnricher'. Đây không phải là sử dụng tiêm phụ thuộc vì vậy làm thế nào tôi sẽ nhận được bối cảnh nếu tôi đang cấu hình đăng nhập vào chương trình chính Phương pháp trước khi khởi động (và sau đó 'ConfigureServices') đã được gọi? –
oh có, nếu bạn đang ở trong chương trình chính, mà không thể làm việc .... mmmm không chắc chắn làm thế nào mà sẽ làm việc – tsimbalar
@ gavin Tôi đã cập nhật câu trả lời của tôi – tsimbalar