2012-09-06 20 views
8

ho bisogno di controllare le chiamate al mio API Web log, Idealmente mi piacerebbe utilizzare un attributo, qualcosa di simile:Web la registrazione di controllo API

[HttpPost, Auditing] 
    public dynamic MyAPICall() 

l'attributo deve essere in grado di intercettare la chiamata API prima e dopo l'esecuzione per registrare i parametri e anche per quanto tempo ha impiegato la chiamata API per l'esecuzione.

Con MVC, è possibile creare una derivata ActionFilterAttribute e sovrascrivere OnActionExecuted e OnActionExecuting.

L'equivalente è possibile nel mondo dell'API Web?

+1

http://stackoverflow.com/questions/10307333/asp-net-mvc-4-webapi-actionfilter-example – BNL

risposta

15

Vorrei utilizzare un gestore di messaggi piuttosto che attributi.

public class LoggingHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     LogRequest(request); 

     return base.SendAsync(request, cancellationToken).ContinueWith(task => 
     { 
      var response = task.Result; 

      LogResponse(response); 

      return response; 
     }); 
    } 

    private void LogRequest(HttpRequestMessage request) 
    { 
     (request.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x => 
     { 
      Logger.Info("{4:yyyy-MM-dd HH:mm:ss} {5} {0} request [{1}]{2} - {3}", request.GetCorrelationId(), request.Method, request.RequestUri, x.Result, DateTime.Now, Username(request)); 
     }); 
    } 

    private void LogResponse(HttpResponseMessage response) 
    { 
     var request = response.RequestMessage; 
     (response.Content ?? new StringContent("")).ReadAsStringAsync().ContinueWith(x => 
     { 
      Logger.Info("{3:yyyy-MM-dd HH:mm:ss} {4} {0} response [{1}] - {2}", request.GetCorrelationId(), response.StatusCode, x.Result, DateTime.Now, Username(request)); 
     }); 
    } 

    private string Username(HttpRequestMessage request) 
    { 
     var values = new List<string>().AsEnumerable(); 
     if (request.Headers.TryGetValues("my-custom-header-for-current-user", out values) == false) return "<anonymous>"; 

     return values.First(); 
    } 
} 
+0

come è possibile analizzare i registri? creare dashboard e definire l'elenco di kpi nel sharepoint? –

+4

questo è semplicemente catturare le informazioni per la registrazione. i dettagli di come/cosa viene registrato o anche come visualizzare i registri sono diversi. Uno che è indipendente da questo problema. –

+0

@JasonMeckley come si fa a usare 'LoggingHandler' nel proprio' api' 'controller'? – uikrosoft

7
+0

Ho riscontrato un errore con 'ITraceWriter' e Thread.CurrentPrincipal, quindi non ho utilizzato il listener. [Collegamento] (http://stackoverflow.com/questions/11870806/httpmessagehandler-reading-content) –

+0

Ottenuto .. sembra che quell'errore sia stato risolto tho '? –

+0

ITraceWriter ha interrotto il mio progetto quando ho provato ad installarlo, non lo consiglio. Ha disinstallato il file di assembly, quindi se qualcuno vuole provarlo, assicurati di eseguire il backup del tuo progetto! – rtp

5

penso che saranno interessati a dare un'occhiata al Web API tracing http://www.asp.net/web-api/overview/testing-and-debugging/tracing-in-aspnet-web-api. Ti consente di esaminare il meccanismo interno dell'API Web.

Nel tuo caso, presumo che tu sia particolarmente interessato a quale sia l'input e l'output delle azioni. Così si può scorretto Suo TraceWriter come riportato di seguito per filtrare le informazioni ridondanti: gestore di messaggi

public class ActionAuditor : ITraceWriter 
{ 
    private const string TargetOperation = "ExecuteAsync"; 
    private const string TargetOpeartor = "ReflectedHttpActionDescriptor"; 

    public void Trace(HttpRequestMessage request, string category, TraceLevel level, Action<TraceRecord> traceAction) 
    { 
     var rec = new TraceRecord(request, category, level); 
     traceAction(rec); 

     if (rec.Operation == TargetOperation && rec.Operator == TargetOpeartor) 
     { 
      if (rec.Kind == TraceKind.Begin) 
      { 
       // log the input of the action 
      } 
      else 
      { 
       // log the output of the action 
      } 
     } 
    } 
} 
15

Http dovrebbe essere un buon punto estendibile per tali scopi. Attenzione però, ci possono essere alcuni problemi con la lettura di contenuti di richiesta simultanea. Ad esempio, Model Binder può provare a leggere il contenuto della richiesta mentre LoggingHandler lo sta leggendo e non riesce a deserializzare un modello. Per evitare tali problemi, basta aggiungere Wait call al metodo LogRequestLoggingInfo.

public class LoggingHandler : DelegatingHandler 
{ 
    protected override Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken) 
    { 
     // Log the request information 
     LogRequestLoggingInfo(request); 

     // Execute the request 
     return base.SendAsync(request, cancellationToken).ContinueWith(task => 
     { 
      var response = task.Result; 
      // Extract the response logging info then persist the information 
      LogResponseLoggingInfo(response); 
      return response; 
     }); 
    } 

    private void LogRequestLoggingInfo(HttpRequestMessage request) 
    { 
     if (request.Content != null) 
     { 
      request.Content.ReadAsByteArrayAsync() 
       .ContinueWith(task => 
        { 
         var result = Encoding.UTF8.GetString(task.Result); 
         // Log it somewhere 
        }).Wait(); // !!! Here is the fix !!! 
     } 
    } 

    private void LogResponseLoggingInfo(HttpResponseMessage response) 
    { 
     if (response.Content != null) 
     { 
      response.Content.ReadAsByteArrayAsync() 
       .ContinueWith(task => 
       { 
        var responseMsg = Encoding.UTF8.GetString(task.Result); 
        // Log it somewhere 
       }); 
     } 
    } 
} 

Ulteriori informazioni a riguardo here.

+0

Mi è successo ... Quindi ho davvero apprezzato la tua risposta, mi ha risparmiato un sacco di tempo. –

+0

+1 per esattamente quello di cui avevo bisogno – raider33

+0

@ k0stya come si applica 'LoggingHandler' nel proprio' api' 'controller'? – uikrosoft

2

Ho lavorato su una libreria che consente di registrare le interazioni con i controller API Web ASP.NET utilizzando i filtri di azione.

Può registrare le chiamate al metodo di azione con informazioni sul chiamante, argomenti, output, durata, eccezioni e altro.

Dai uno sguardo allo Audit.WebApi.