Skip to content

Instantly share code, notes, and snippets.

@miketrebilcock
Last active December 18, 2015 16:49
Show Gist options
  • Save miketrebilcock/5814235 to your computer and use it in GitHub Desktop.
Save miketrebilcock/5814235 to your computer and use it in GitHub Desktop.
DatabaseRequestLogger for ServiceStack
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