2016-07-14 36 views
6

'dan erişme ASP.NET Core 1.0'da, ILoggerProvider ve ILogger arabirimlerinin özel bir uygulamasına sahibim. HttpContext'e Log yönteminden erişebilmek istiyorum.Geçerli HttpContext'e bir ILogger

Özel bir ILogger ürününe IHttpContextAccessor enjekte etmem gerekiyor, ancak nasıl yapılacağını bulamıyorum. ILoggerProvider nesnesi, başlangıçta oluşturulur ve CreateLogger yöntemi, bağımlılık enjeksiyonuna izin vermez.

ILogger ile bağımlılık enjeksiyonunu kullanmanın basit bir yolu var mı? yolu çalışır yukarıda i tercih ediyorum rağmen

public class CustomLogProvider : ILoggerProvider 
{ 

    private readonly Func<string, LogLevel, bool> _filter; 
    private readonly IHttpContextAccessor _accessor; 

    public CustomLogProvider(Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor) 
    { 
     _filter = filter; 
     _accessor = accessor; 
    } 

    public ILogger CreateLogger(string categoryName) 
    { 
     return new CustomLogger(categoryName, _filter, _accessor); 
    } 

    public void Dispose() 
    { 
    } 
} 

public class CustomLogger : ILogger 
{ 
    private string _categoryName; 
    private Func<string, LogLevel, bool> _filter; 
    private readonly IHttpContextAccessor _accessor; 

    public CustomLogger(string categoryName, Func<string, LogLevel, bool> filter, IHttpContextAccessor accessor) 
    { 
     _categoryName = categoryName; 
     _filter = filter; 
     _accessor = accessor; 
    } 

    public IDisposable BeginScope<TState>(TState state) 
    { 
     return null; 
    } 

    public bool IsEnabled(LogLevel logLevel) 
    { 
     return (_filter == null || _filter(_categoryName, logLevel)); 
    } 

    public void Log<TState>(LogLevel logLevel, EventId eventId, TState state, Exception exception, Func<TState, Exception, string> formatter) 
    { 
     if (!IsEnabled(logLevel)) 
     { 
      return; 
     } 

     if (formatter == null) 
     { 
      throw new ArgumentNullException(nameof(formatter)); 
     } 

     var message = formatter(state, exception); 

     if (string.IsNullOrEmpty(message)) 
     { 
      return; 
     } 

     message = $"{ logLevel }: {message}"; 

     if (exception != null) 
     { 
      message += Environment.NewLine + Environment.NewLine + exception.ToString(); 
     } 
     if(_accessor.HttpContext != null) // you should check HttpContext 
     { 
      message += Environment.NewLine + Environment.NewLine + _accessor.HttpContext.Request.Path; 
     } 
     // your implementation 

    } 

} 
public static class CustomLoggerExtensions 
{ 
    public static ILoggerFactory AddCustomLogger(this ILoggerFactory factory, IHttpContextAccessor accessor, 
              Func<string, LogLevel, bool> filter = null) 
    { 
     factory.AddProvider(new CustomLogProvider(filter, accessor)); 
     return factory; 
    } 
} 

yerine HttpContextAccessor enjekte özel IRequestLogger uygulamak için:

cevap

6

İşte

Startup.cs

public void ConfigureServices(IServiceCollection services) 
    { 
     services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
    } 

    public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory, IServiceProvider serviceProvider) 
    { 
     loggerFactory.AddCustomLogger(serviceProvider.GetService<IHttpContextAccessor>()); 
     // 
    } 

Özel Logger bir örnektir.

public interface IRequestLogger<T> 
{ 
    void Log(LogLevel logLevel, EventId eventId, string message); // you can change this 
} 

public class RequestLogger<T> : IRequestLogger<T> 
{ 
    private readonly IHttpContextAccessor _accessor; 
    private readonly ILogger _logger; 
    public RequestLogger(ILogger<T> logger, IHttpContextAccessor accessor) 
    { 
     _accessor = accessor; 
     _logger = logger; 
    } 

    public void Log(LogLevel logLevel, EventId eventId, string message) 
    { 
     Func<object, Exception, string> _messageFormatter = (object state, Exception error) => 
     { 
      return state.ToString(); 
     }; 
     _logger.Log(LogLevel.Critical, 0, new FormattedLogValues(message), null, _messageFormatter); 
    } 
} 

Ve basit kullanım

: Uygulama (Bu test değildir) aşağıda gibidir Bu kodu test değil

public class LogType 
{ 

} 
public void ConfigureServices(IServiceCollection services) 
{ 
    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 
    services.AddSingleton(typeof(IRequestLogger<>), typeof(RequestLogger<>)); 
} 

public void Configure(IApplicationBuilder app, ILoggerFactory loggerFactory) 
{ 
    loggerFactory.AddConsole(true); 
    app.Run(async (context) => 
    { 
     var requestLogger = context.RequestServices.GetService<IRequestLogger<LogType>>(); 
     requestLogger.Log(LogLevel.Critical, 11, "<message>"); 
     // 
    }); 
} 
+0

Üzgünüm, benim cevap yayınlanmıştır ve sonra beni alt gördü. Bu zaten daha eksiksiz, bu yüzden oy verdim. –

2

ama yaklaşım aşağıdaki gibi bir şey olacağına inanıyoruz. Sonra

services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); 

yapılandır yöntemi (hala Startup.cs iç) gibi bir şey IHttpContextAccessor httpContextAccessor için ek bir parametre ekleyin: senin Startup.cs sınıfta

, ConfigureServices yöntemine aşağıdaki satırı ekleyerek HttpContextAccessor kayıt Bu Configure yöntemle içinde

public void Configure(
         IApplicationBuilder app, 
         IHostingEnvironment env, 
         ILoggerFactory loggerFactory, 
         IHttpContextAccessor httpContextAccessor) 

, sen pr şimdi eklemek özel günlüğü oluşturmak için logger fabrikaya bir uzantısı yöntemi çağırabilirsiniz ovider, gibi bir şey:

loggerFactory.AddMyCustomProvider(httpContextAccessor); 

uzatma yöntemi (oluşturmanız gereken o) nerede olacak gibi bir şey:

public static class MyCustomLoggerExtensions 
    { 
    public static ILoggerFactory AddMyCustomProvider(
     this ILoggerFactory factory, 
     IHttpContextAccessor httpContextAccessor) 
    { 
     factory.AddProvider(new MyCustomLoggerProvider(httpContextAccessor)); 
     return factory; 
    } 
    } 
İlgili konular