Wir verwenden den folgenden Filter, den wir zu HttpConfiguration.Filters
hinzufügen. Einige Code:
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);
}
}
Wir verwenden log4net, können Sie die ILog
Implementierung ersetzen mit dem, was Sie für richtig halten. ILog.DebugTiming
ist nur eine Erweiterungsmethode, die eine Stoppuhr verwendet, um die verstrichene Zeit für jeden Anruf abzurufen.
Edit: Dieser Beitrag Get the IP address of the remote host enthält Details, wie Sie die IP-Adresse des Remote-Aufrufers erhalten.
Cheers, Dean
Der Link funktioniert gesendet: privat string GetClientIp (HttpRequestMessage Anfrage) \t \t { \t \t \t if (request.Properties.ContainsKey ("MS_HttpContext")) \t \t \t { \t \t \t \t Rückgabe ((HttpContextWrapper) request.Properties ["MS_HttpContext"]). Request.UserHostAddress; \t \t \t} \t \t \t if (request.Properties.ContainsKey (RemoteEndpointMessageProperty.Name)) \t \t \t { \t \t \t \t RemoteEndpointMessageProperty prop; \t \t \t \t prop = (RemoteEndpointMessageProperty) request.Properties [RemoteEndpointMessageProperty.Name]; \t \t \t \t Rückgabe prop.Address; \t \t \t} \t \t \t zurück null; \t \t} – maxfridbe
Es scheint wie Mike Antwort ist die bessere Wahl - wo Sie die eigentliche Logging-Implementierung oder sogar das integrierte Web-API-Framework, wenn gewünscht (und damit eine Verdoppelung der Aufwand) injizieren können. – Lex
Wir haben die "ITraceWriter" -Bits untersucht, aber es schien sehr schwierig zu sein, Anfangs- und Endzeiten zu korrelieren, und es scheint einen deutlichen Mangel an Implementierungen der Produktionsstärke in der Community zu geben, um das eigene zu steuern. Wir entschieden, dass der obige Ansatz einfacher war. –