2015-09-06 15 views
5

Sto tentando di aggiungere la registrazione alla mia app utilizzando Web Api 2 e Owin, quindi ho iniziato a utilizzare Microsoft Owin Logging, che richiede uno ILogger e ILoggerFactory, che è stato implementato e funziona perfettamente quando devo registrare qualcosa all'interno di STARTUP metodo o uno dei componenti di Owin Middleware.Microsoft Owin Logging - Web Api 2 - Come si crea il logger?

Per esempio, quando sono nel metodo Startup posso creare il registratore utilizzando:

public void Configuration(IAppBuilder app) 
    { 
     // Creates configuration 
     var configuration = new HttpConfiguration(); 

     // Configure WebApi Settings 
     WebApiConfig.Register(configuration); 

     app.SetLoggerFactory(new OwinLog4NetLoggerFactory("Default")); 

     var logger = app.CreateLogger<Startup>(); 
     logger.WriteInformation("test log"); 

     // Enabled WebApi in OWIN 
     app.UseWebApi(configuration); 
    } 

Dove "OwinLog4NetLoggerFactory" è la mia implementazione ILoggerFactory personalizzato.

Finora, tutto bene ... ma ... Come posso creare il registratore quando sono nel vero metodo di azione web API? ... Ho provato ad accedere allo Request.GetOwinEnvironment() e la fabbrica del logger non è nel dizionario .

Ad esempio:

public class AccountController : ApiController 
{ 
    public int Get(int id) 
    { 
     // Create logger here 

     return id + 1; 
    } 
} 

so di poter creare una classe statica con un riferimento al logger di fabbrica o anche Iniezione di aggiungere il registratore al controller api, ma che sembra troppo complicato per qualcosa che dovrebbe essere già lì

Qualsiasi idea sarebbe apprezzata.

+0

qualcuno può rispondere l'attuale domanda del poster originale? L'unica risposta di seguito non è ciò che ha chiesto. –

risposta

-1

invece di aggiungere il codice di registrazione in tutti i metodi, creo un MessageLoggingHandler che può essere registrato in Global.asax.cs una volta e quindi registra ogni richiesta e risposta.

Ecco il codice che uso, è possibile modificare secondo le vostre esigenze:

prima creare una classe che eredita da messageHandler DelegationHandler:

public abstract class MessageHandler : DelegatingHandler 
{ 
    protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     var corrId = Guid.NewGuid(); 
     var requestMethod = request.Method.Method.ToString(); 
     var requestUri = request.RequestUri.ToString(); 
     var ipAddress = request.GetOwinContext().Request.RemoteIpAddress; 

     var requestMessage = await request.Content.ReadAsByteArrayAsync(); 
     await LogMessageAsync(corrId, requestUri, ipAddress, "Request", requestMethod, request.Headers.ToString(), requestMessage, string.Empty); 

     var response = await base.SendAsync(request, cancellationToken); 

     var responseMessage = await response.Content.ReadAsByteArrayAsync(); 
     await LogMessageAsync(corrId, requestUri, ipAddress, "Response", requestMethod, response.Headers.ToString(), responseMessage, ((int)response.StatusCode).ToString() + "-" + response.ReasonPhrase); 

     return response; 
    } 

    protected abstract Task LogMessageAsync(Guid CorrelationId, string APIUrl, string ClientIPAddress, string RequestResponse, string HttpMethod, string HttpHeaders, byte[] HttpMessage, string HttpStatusCode); 

} 

public class MessageLoggingHandler : MessageHandler 
{ 
    protected override async Task LogMessageAsync(Guid CorrelationId, string APIUrl, string ClientIPAddress, string RequestResponse, string HttpMethod, string HttpHeaders, byte[] HttpMessage, string HttpStatusCode) 
    { 
     // Create logger here 

     //Do your logging here 
    } 
} 

Poi, nel tuo Global.asax.cs, è necessario registrare il sopra MessageLoggingHandler creato:

GlobalConfiguration.Configuration.MessageHandlers.Add(new MessageLoggingHandler()); 

Basta essere consapevoli, questo registrerà ogni richiesta e di risposta, la volontà corpo pieno messaggio. Questo può richiedere molto spazio molto rapidamente (a seconda dell'utilizzo della tua API). Quindi potrebbe essere necessario modificare questo (ad esempio, mantenere i record per un mese o ignorare 200 risposte OK ecc.)

+2

Grazie mille, sfortunatamente non ho bisogno di registrare ogni richiesta/risposta (per la cronaca, nel mondo Owin, normalmente lo fai attraverso un middleware). Devo creare il logger perché devo registrare "alcuni messaggi di debug o di avvertimento" in alcune azioni. Grazie ancora per la tua risposta. – Daniel

1

Si consiglia di scrivere il middleware in modo che sia possibile gestire la registrazione all'esterno del controller:

public class LoggingMiddleware : OwinMiddleware 
{ 
    public LoggingMiddleware(OwinMiddleware next) 
     : base(next) 
    { 
    } 

    public override async Task Invoke(IOwinContext context) 
    { 
      //handle request logging 

      await Next.Invoke(context); 

      //handle response logging 
    } 

} 

poi in classe di avvio:

public class Startup 
{ 
    // ReSharper disable once UnusedMember.Global 
    public void Configuration(IAppBuilder appBuilder) 
    { 
     HttpConfiguration config = new HttpConfiguration(); 

     config.MapHttpAttributeRoutes(); 
     appBuilder.Use<LoggingMiddleware>(); 
     appBuilder.UseWebApi(config); 
    } 
} 

la richiesta sarebbe poi entrato, ha colpito il codice di richiesta di registrazione nel LoggingMiddleware, ha colpito il codice di controllo e quindi la risposta sarebbe effettuato il login al LoggingMiddleware sul ritorno.

Tuttavia, se tutti si vogliono fare è inviare un oggetto tramite dal middleware al controller è possibile utilizzare context.Set("loggingObject", loggingObject); nel middleware e poi var loggingObject = Request.GetOwinContext().Get<LoggerClass>("loggingObject"); nel controller.

Edit: corretto un}

+0

Grazie, Sam, ma mi consente solo di accedere PRIMA e DOPO la chiamata al controller ... NON ALL'INTERNO del controller. Ho finito per usare Log4Net all'interno di ogni controller/classe .... Come consigliato da Trevor, potrei usare un'astrazione di logging, quindi non devo creare una dipendenza diretta da Log4Net, ma volevo usare l'astrazione di registrazione interna fornita da Registrazione di Microsoft Owin. Grazie. – Daniel

0

mi consiglia di utilizzare la libreria Common.Logging nelle applicazioni, disponibile su NuGet. Common.Logging offre un'interfaccia comune per l'utilizzo della soluzione di registrazione preferita. Risolve un sacco di problemi come il tuo. Ecco un esempio di utilizzo Common.Logging con NLog:

Nel vostro controller, si accede in questo modo:

public class MyController : ApiController 
    { 
    private static readonly ILog Log = LogManager.GetLogger<MyController>(); 

    public async Task<IHttpActionResult> Get([FromUri] int id) 
    { 
     Log.Debug("Called Get with id " + id.ToString()); 
     return Ok(); 
    } 
    } 

Prendete l'ultimo pacchetto Common.Logging.NLog su NuGet (al momento della stesura , dovrebbe essere Common.Logging.NLog41). Poi, nel tuo web.config, si dovrebbe configurare Common.Logging per utilizzare la configurazione NLog:

<common> 
    <logging> 
    <factoryAdapter type="Common.Logging.NLog.NLogLoggerFactoryAdapter, Common.Logging.NLog41"> 
     <arg key="configType" value="FILE" /> 
     <arg key="configFile" value="~/NLog.config" /> 
    </factoryAdapter> 
    </logging> 
</common> 

Ecco alcuni ulteriori collegamenti:

https://github.com/net-commons/common-logging

https://cmatskas.com/an-introduction-to-common-logging-api-2/

+0

Grazie ... Ho finito per utilizzare Log4Net direttamente in ogni classe di controller, ma l'idea era di usare l'astrazione di registrazione incorporata (non un "altro" pacchetto). Grazie! – Daniel

Problemi correlati