Last active
December 18, 2015 16:49
-
-
Save miketrebilcock/5814235 to your computer and use it in GitHub Desktop.
DatabaseRequestLogger for ServiceStack
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using ServiceStack.Common.Web; | |
using ServiceStack.Logging; | |
using ServiceStack.OrmLite; | |
using ServiceStack.ServiceHost; | |
using ServiceStack.ServiceInterface; | |
using ServiceStack.ServiceInterface.ServiceModel; | |
using ServiceStack.ServiceModel; | |
using System; | |
using System.Collections.Generic; | |
using System.Data; | |
using System.Linq; | |
namespace servicestack.custom | |
{ | |
public class DatabaseRequestLogger : IRequestLogger | |
{ | |
private ILog logger = LogManager.GetLogger(typeof(DatabaseRequestLogger)); | |
private IDbConnection db; | |
public DatabaseRequestLogger(IDbConnectionFactory dbFactory) | |
{ | |
this.dbFactory = dbFactory; | |
} | |
public virtual IDbConnection Db | |
{ | |
get { return db ?? (db = dbFactory.Open()); } | |
} | |
public bool EnableErrorTracking { get; set; } | |
public bool EnableRequestBodyTracking { get; set; } | |
public bool EnableResponseTracking { get; set; } | |
public bool EnableSessionTracking { get; set; } | |
public Type[] ExcludeRequestDtoTypes { get; set; } | |
public Type[] HideRequestBodyForRequestDtoTypes { get; set; } | |
public string[] RequiredRoles { get; set; } | |
private IDbConnectionFactory dbFactory { get; set; } | |
public static object ToSerializableErrorResponse(object response) | |
{ | |
var errorResult = response as IHttpResult; | |
if (errorResult != null) | |
return errorResult.Response; | |
var ex = response as Exception; | |
return ex != null ? ex.ToResponseStatus() : null; | |
} | |
public List<RequestLogEntry> GetLatestLogs(int? take) | |
{ | |
if (!take.HasValue) | |
take = 50; | |
SqlExpressionVisitor<CORERequestLogEntry> ev = OrmLiteConfig.DialectProvider.ExpressionVisitor<CORERequestLogEntry>(); | |
ev.OrderByDescending(e => e.DateTime).Limit(take.Value); | |
var CORERequestLogEntries = Db.Select(ev); | |
var requestLogEntries = new List<RequestLogEntry>(); | |
foreach (var logEntry in CORERequestLogEntries) | |
{ | |
RequestLogEntry log = new RequestLogEntry(); | |
log.AbsoluteUri = logEntry.AbsoluteUri; | |
log.DateTime = logEntry.DateTime; | |
log.ErrorResponse = logEntry.ErrorResponse; | |
log.FormData = logEntry.FormData; | |
log.ForwardedFor = logEntry.ForwardedFor; | |
log.Headers = logEntry.Headers; | |
log.HttpMethod = logEntry.HttpMethod; | |
log.Id = logEntry.Id; | |
log.IpAddress = logEntry.IpAddress; | |
log.Items = logEntry.Items; | |
log.PathInfo = logEntry.PathInfo; | |
log.Referer = logEntry.Referer; | |
log.RequestBody = logEntry.RequestBody; | |
log.RequestDto = logEntry.RequestDto; | |
log.RequestDuration = TimeSpan.FromMilliseconds(logEntry.RequestDuration); | |
log.ResponseDto = logEntry.ResponseDto; | |
log.Session = logEntry.Session; | |
log.SessionId = logEntry.SessionId; | |
log.UserAuthId = logEntry.UserAuthId; | |
requestLogEntries.Add(log); | |
} | |
return requestLogEntries; | |
} | |
public void Log(IRequestContext requestContext, object requestDto, object response, TimeSpan requestDuration) | |
{ | |
var requestType = requestDto != null ? requestDto.GetType() : null; | |
if (ExcludeRequestDtoTypes != null | |
&& requestType != null | |
&& ExcludeRequestDtoTypes.Contains(requestType)) | |
return; | |
var entry = new CORERequestLogEntry | |
{ | |
DateTime = DateTime.UtcNow, | |
RequestDuration = requestDuration.TotalMilliseconds, | |
}; | |
var httpReq = requestContext != null ? requestContext.Get<IHttpRequest>() : null; | |
if (httpReq != null) | |
{ | |
entry.HttpMethod = httpReq.HttpMethod; | |
entry.AbsoluteUri = httpReq.AbsoluteUri; | |
entry.PathInfo = httpReq.PathInfo; | |
entry.IpAddress = requestContext.IpAddress; | |
entry.ForwardedFor = httpReq.Headers[HttpHeaders.XForwardedFor]; | |
entry.Referer = httpReq.Headers[HttpHeaders.Referer]; | |
entry.Headers = httpReq.Headers.ToDictionary(); | |
entry.UserAuthId = httpReq.GetItemOrCookie(HttpHeaders.XUserAuthId); | |
entry.SessionId = httpReq.GetSessionId(); | |
entry.Items = httpReq.Items; | |
entry.Session = EnableSessionTracking ? httpReq.GetSession() : null; | |
entry.servername = System.Environment.MachineName; | |
try | |
{ | |
entry.UserAgent = httpReq.UserAgent; | |
} | |
catch(Exception e) | |
{ | |
} | |
} | |
if (HideRequestBodyForRequestDtoTypes != null | |
&& requestType != null | |
&& !HideRequestBodyForRequestDtoTypes.Contains(requestType)) | |
{ | |
entry.RequestDto = requestDto; | |
if (httpReq != null) | |
{ | |
entry.FormData = httpReq.FormData.ToDictionary(); | |
if (EnableRequestBodyTracking) | |
{ | |
entry.RequestBody = httpReq.GetRawBody(); | |
} | |
} | |
} | |
if (!response.IsErrorResponse()) | |
{ | |
if (EnableResponseTracking) | |
entry.ResponseDto = response; | |
} | |
else | |
{ | |
if (EnableErrorTracking) | |
entry.ErrorResponse = ToSerializableErrorResponse(response); | |
} | |
try | |
{ | |
Db.Insert<CORERequestLogEntry>(entry); | |
} | |
catch (System.Exception ex) | |
{ | |
logger.ErrorFormat("Error Saving request", ex); | |
} | |
} | |
public class CORERequestLogEntry | |
{ | |
public string AbsoluteUri { get; set; } | |
public DateTime DateTime { get; set; } | |
public object ErrorResponse { get; set; } | |
public Dictionary<string, string> FormData { get; set; } | |
public string ForwardedFor { get; set; } | |
public Dictionary<string, string> Headers { get; set; } | |
public string HttpMethod { get; set; } | |
[PrimaryKey] | |
[AutoIncrement] | |
public int Id { get; set; } | |
public string IpAddress { get; set; } | |
public Dictionary<string, object> Items { get; set; } | |
public string PathInfo { get; set; } | |
public string Referer { get; set; } | |
public string RequestBody { get; set; } | |
public object RequestDto { get; set; } | |
public double RequestDuration { get; set; } | |
public object ResponseDto { get; set; } | |
public string servername { get; set; } | |
public object Session { get; set; } | |
public string SessionId { get; set; } | |
public string UserAgent { get; set; } | |
public string UserAuthId { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment