Last active
January 10, 2021 05:03
-
-
Save mrshridhara/59779783e113049f487d to your computer and use it in GitHub Desktop.
Provides storage using Redis for ELMAH error logging.
This file contains hidden or 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 System; | |
using System.Collections; | |
using System.Collections.Generic; | |
using System.Globalization; | |
using System.Linq; | |
using Elmah; | |
using ServiceStack.Redis; | |
/// <summary> | |
/// Provides storage for error logging using Redis. | |
/// </summary> | |
public class RedisStorageErrorLog : ErrorLog | |
{ | |
private readonly IRedisClientFactory redisClientFactory; | |
private readonly long db; | |
private readonly string host; | |
private readonly int port; | |
public RedisStorageErrorLog (IDictionary config) | |
{ | |
this.redisClientFactory = RedisClientFactory.Instance; | |
this.host = config ["host"] as string ?? RedisNativeClient.DefaultHost; | |
this.port = int.Parse (config ["port"] as string ?? RedisNativeClient.DefaultPort.ToString (CultureInfo.InvariantCulture)); | |
this.db = long.Parse (config ["db"] as string ?? RedisNativeClient.DefaultDb.ToString (CultureInfo.InvariantCulture)); | |
} | |
public RedisStorageErrorLog (string host, int port, long db = 0) | |
{ | |
this.redisClientFactory = RedisClientFactory.Instance; | |
this.host = host; | |
this.port = port; | |
this.db = db; | |
} | |
public RedisStorageErrorLog (IRedisClientFactory redisClientFactory, string host, int port, long db = 0) | |
{ | |
this.redisClientFactory = redisClientFactory; | |
this.host = host; | |
this.port = port; | |
this.db = db; | |
} | |
public override string Name | |
{ | |
get { return "Redis Storage Error Log"; } | |
} | |
public override string Log (Error error) | |
{ | |
if (error == null) | |
throw new ArgumentNullException ("error"); | |
var errorXml = ErrorXml.EncodeString (error); | |
var id = Guid.NewGuid (); | |
var redisKey = GetRedisKey (id.ToString ()); | |
var errorLog = new RedisErrorData | |
{ | |
Id = id, | |
ErrorTime = error.Time, | |
ErrorXml = errorXml | |
}; | |
using (var redisClient = this.GetRedisClient ()) | |
{ | |
redisClient.Add (redisKey, errorLog); | |
} | |
return id.ToString (); | |
} | |
public override ErrorLogEntry GetError (string id) | |
{ | |
if (id == null) | |
throw new ArgumentNullException ("id"); | |
if (id.Length == 0) | |
throw new ArgumentException (null, "id"); | |
Guid errorGuid; | |
try | |
{ | |
errorGuid = new Guid (id); | |
} | |
catch (FormatException e) | |
{ | |
throw new ArgumentException (e.Message, "id", e); | |
} | |
var redisKey = GetRedisKey (errorGuid.ToString ()); | |
RedisErrorData loggedError; | |
using (var redisClient = this.GetRedisClient ()) | |
{ | |
loggedError = redisClient.Get<RedisErrorData> (redisKey); | |
} | |
var errorXml = loggedError.ErrorXml; | |
if (errorXml == null) | |
return null; | |
var error = ErrorXml.DecodeString (errorXml); | |
return new ErrorLogEntry (this, id, error); | |
} | |
public override int GetErrors (int pageIndex, int pageSize, IList errorEntryList) | |
{ | |
if (pageIndex < 0) | |
throw new ArgumentOutOfRangeException ("pageIndex", pageIndex, null); | |
if (pageSize < 0) | |
throw new ArgumentOutOfRangeException ("pageSize", pageSize, null); | |
if (errorEntryList == null) | |
errorEntryList = new ArrayList (); | |
IEnumerable<RedisErrorData> allLoggedErrors; | |
using (var redisClient = this.GetRedisClient ()) | |
{ | |
var keyPattern = GetRedisKey ("*"); | |
var errorLogKeys = redisClient.SearchKeys (keyPattern); | |
allLoggedErrors | |
= redisClient | |
.GetAll<RedisErrorData> (errorLogKeys) | |
.Values | |
.OrderByDescending (eachLog => eachLog.ErrorTime); | |
} | |
foreach (var eachLog in allLoggedErrors.Skip (pageSize * pageIndex).Take (pageSize)) | |
{ | |
var error = ErrorXml.DecodeString (eachLog.ErrorXml); | |
errorEntryList.Add (new ErrorLogEntry (this, eachLog.Id.ToString (), error)); | |
} | |
return allLoggedErrors.Count(); | |
} | |
private static string GetRedisKey (string id) | |
{ | |
return "elmah-error:" + id; | |
} | |
private IRedisClient GetRedisClient () | |
{ | |
var redisClient = this.redisClientFactory.CreateRedisClient (this.host, this.port); | |
redisClient.Db = this.db; | |
return redisClient; | |
} | |
private sealed class RedisErrorData | |
{ | |
public DateTime ErrorTime { get; set; } | |
public string ErrorXml { get; set; } | |
public Guid Id { get; set; } | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment