Skip to content

Instantly share code, notes, and snippets.

@joe-oli
Forked from mrshridhara/RedisStorageErrorLog.cs
Created January 10, 2021 05:03
Show Gist options
  • Save joe-oli/31f69f1c74907fe8fe049705898173c6 to your computer and use it in GitHub Desktop.
Save joe-oli/31f69f1c74907fe8fe049705898173c6 to your computer and use it in GitHub Desktop.
Provides storage using Redis for ELMAH error logging.
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