2012-07-10 10 views
19

लिए लॉगिंग जोड़ें मैं इस के अनुसार एक ApiController पर एक Get() के लिए एक [LoggedApiCall] फिल्टर बनाने के लिए कोशिश कर रहा हूँ: ASP.NET Web API ActionFilter exampleकैसे MVC4 WebAPI

मैं एक System.Web.HttpFilters.ActionFilterAttribute बनाया है। ओवरराइड के लिए OnActionExecuted(HttpActionExecutedContext actionExecutedContext)

मैं HttpActionExecutedContext

शायद मैं प्रवेश करने हर एपीआई गलत तरीके से फोन के बारे में जा रहा हूँ से फोन करने वाले का आईपी पाने के लिए एक रास्ता खोज नहीं कर पा रहे अनुमति देता है?

उत्तर

13

हम निम्नलिखित फ़िल्टर का उपयोग करते हैं जिसे हम HttpConfiguration.Filters में जोड़ते हैं। कुछ कोड:

internal class LoggingFilter : IExceptionFilter, IActionFilter 
{ 
    private readonly ILog log; 

    public LoggingFilter(ILog log) 
    { 
     if (log == null) 
     { 
      throw new ArgumentNullException("log"); 
     } 

     this.log = log; 
    } 

    public bool AllowMultiple 
    { 
     get { return false; } 
    } 

    Task IExceptionFilter.ExecuteExceptionFilterAsync(HttpActionExecutedContext actionContext, CancellationToken cancellationToken) 
    { 
     if (actionContext == null) 
     { 
      throw new ArgumentNullException("actionContext"); 
     } 

     this.log.Error(string.Format("Unexpected error while executing {0}", this.BuildLogEntry(actionContext.ActionContext)), actionContext.Exception); 
     return TaskHelpers.Completed(); 
    } 

    Task<HttpResponseMessage> IActionFilter.ExecuteActionFilterAsync(HttpActionContext actionContext, CancellationToken cancellationToken, Func<Task<HttpResponseMessage>> continuation) 
    { 
     if (actionContext == null) 
     { 
      throw new ArgumentNullException("actionContext"); 
     } 

     if (continuation == null) 
     { 
      throw new ArgumentNullException("continuation"); 
     } 

     if (!this.log.IsDebugEnabled) 
     { 
      // no point running at all if logging isn't currently enabled 
      return continuation(); 
     } 

     string logEntry = this.BuildLogEntry(actionContext); 
     IDisposable logContext = this.log.DebugTiming("Executing {0}", logEntry); 

     Task<string> requestContent; 
     if (actionContext.Request.Content != null) 
     { 
      requestContent = actionContext.Request.Content.ReadAsStringAsync().ContinueWith(requestResult => string.IsNullOrEmpty(requestResult.Result) ? "N/A" : requestResult.Result); 
     } 
     else 
     { 
      requestContent = TaskHelpers.FromResult("N/A"); 
     } 

     return requestContent.ContinueWith(
      requestResult => 
       { 
        this.log.DebugFormat("{0}, Request = {1}", logEntry, requestResult.Result); 

        return continuation() 
         .ContinueWith(t => 
          { 
           Task<string> responseContent; 
           if (t.IsCompleted && t.Result.Content != null) 
           { 
            responseContent = t.Result.Content.ReadAsStringAsync().ContinueWith(responseResult => string.IsNullOrEmpty(responseResult.Result) ? "N/A" : responseResult.Result); 
           } 
           else 
           { 
            responseContent = TaskHelpers.FromResult("N/A"); 
           } 

           return responseContent.ContinueWith(
            responseResult => 
             { 
              using (logContext) 
              { 
               this.log.DebugFormat("{0}, Status Code: {1}, Response = {2}", logEntry, t.Result.StatusCode, responseResult.Result); 
              } 

              return t.Result; 
             }); 
          }).Unwrap(); 
       }).Unwrap(); 
    } 

    /// <summary> 
    /// Builds log data about the request. 
    /// </summary> 
    /// <param name="actionContext">Data associated with the call</param> 
    private string BuildLogEntry(HttpActionContext actionContext) 
    { 
     string route = actionContext.Request.GetRouteData().Route.RouteTemplate; 
     string method = actionContext.Request.Method.Method; 
     string url = actionContext.Request.RequestUri.AbsoluteUri; 
     string controllerName = actionContext.ActionDescriptor.ControllerDescriptor.ControllerName; 
     string actionName = actionContext.ActionDescriptor.ActionName; 

     return string.Format("{0} {1}, route: {2}, controller:{3}, action:{4}", method, url, route, controllerName, actionName); 
    } 
} 

हम log4net का उपयोग करें, आप ILog कार्यान्वयन जो कुछ के साथ आपको योग्य जगह ले सकता है। ILog.DebugTiming सिर्फ एक विस्तार विधि है जो प्रत्येक कॉल के लिए समाप्त समय प्राप्त करने के लिए स्टॉपवॉच का उपयोग करती है।

संपादित करें: यह पोस्ट Get the IP address of the remote host पर रिमोट कॉलर का आईपी पता कैसे प्राप्त करें इस बारे में विवरण है।

चीयर्स, डीन

+0

लिंक आप काम करता भेजा: निजी स्ट्रिंग GetClientIp (HttpRequestMessage अनुरोध) \t \t { \t \t \t अगर (request.Properties.ContainsKey ("MS_HttpContext")) \t \t \t { \t \t \t \t वापसी ((HttpContextWrapper) अनुरोध। प्रॉपर्टीज ["MS_HttpContext"])। Request.UserHostAddress; \t \t \t} \t \t \t अगर (request.Properties.ContainsKey (RemoteEndpointMessageProperty.Name)) \t \t \t { \t \t \t \t RemoteEndpointMessageProperty प्रोप; \t \t \t \t प्रोप = (रिमोटएन्डपॉइंट मैसेजप्रोपर्टी) अनुरोध। प्रॉपर्टीज [रिमोट एंड पॉइंट मैसेजप्रोपर्टी नाम]; \t \t \t \t वापसी प्रोप। एड्रेस; \t \t \t} \t \t वापसी शून्य; \t \t} – maxfridbe

+0

ऐसा लगता है जैसे माइक का जवाब बेहतर विकल्प है - जहां आप वास्तविक लॉगिंग कार्यान्वयन या यहां तक ​​कि इनबिल्ट वेब एपीआई लॉग फ्रेमवर्क को इंजेक्ट कर सकते हैं, और यदि इस तरह से वांछित हो (और इस प्रकार प्रयास को दोगुना करना बंद हो)। – Lex

+0

हमने 'आईट्रेसवाइटर' बिट्स की जांच की लेकिन शुरुआत और समाप्ति समय से संबंधित होना बहुत मुश्किल लग रहा था और समुदाय में उत्पादन शक्ति कार्यान्वयन की एक अलग कमी है जो स्वयं को लिखने के लिए मार्गदर्शन करती है। हमने तय किया कि उपर्युक्त दृष्टिकोण सरल था। –

संबंधित मुद्दे