Skip to content

Instantly share code, notes, and snippets.

@chgeuer
Last active December 10, 2015 00:29
Show Gist options
  • Select an option

  • Save chgeuer/4351796 to your computer and use it in GitHub Desktop.

Select an option

Save chgeuer/4351796 to your computer and use it in GitHub Desktop.
using Elmah;
using Microsoft.WindowsAzure.ServiceRuntime;
using Microsoft.WindowsAzure.Storage;
using Microsoft.WindowsAzure.Storage.Table;
using Microsoft.WindowsAzure.Storage.Table.DataServices;
using System;
using System.Collections;
using System.Data.Services.Client;
using System.Linq;
using System.Threading.Tasks;
namespace MvcWebRole1
{
public class ErrorEntity : TableServiceEntity
{
public string MachineInstance { get; set; }
public string DeploymentId { get; set; }
public string ApplicationName { get; set; }
public string Detail { get; set; }
public string HostName { get; set; }
public string Message { get; set; }
public string Source { get; set; }
public string StatusCode { get; set; }
public string Type { get; set; }
public string User { get; set; }
public string WebHostHtmlMessage { get; set; }
public string SerializedError { get; set; }
public ErrorEntity() { }
public ErrorEntity(Error error)
: base(string.Empty, (DateTime.MaxValue.Ticks - DateTime.UtcNow.Ticks).ToString("d19"))
{
var reallyInTheCloud = RoleEnvironment.IsAvailable && !RoleEnvironment.IsEmulated;
this.MachineInstance = reallyInTheCloud ?
RoleEnvironment.CurrentRoleInstance.Id :
Environment.MachineName;
this.DeploymentId = reallyInTheCloud ?
RoleEnvironment.DeploymentId :
string.Empty;
this.ApplicationName = error.ApplicationName;
this.Detail = error.Detail;
this.HostName = error.HostName;
this.Message = error.Message;
this.Source = error.Source;
this.StatusCode = error.StatusCode.ToString();
this.Type = error.Type;
this.User = error.User;
this.WebHostHtmlMessage = error.WebHostHtmlMessage;
this.SerializedError = ErrorXml.EncodeString(error);
}
}
public class TableErrorLog : ErrorLog
{
public string TableName { get { return "elmaherrors2".ToLower(); } }
private string connectionString;
private CloudTableClient CreateCloudTableClient()
{
return CloudStorageAccount.Parse(connectionString).CreateCloudTableClient();
}
private TableServiceContext CreateTableServiceContext()
{
return CreateCloudTableClient().GetTableServiceContext();
}
private DataServiceQuery<ErrorEntity> CreateQuery()
{
return CreateTableServiceContext().CreateQuery<ErrorEntity>(TableName);
}
void Initialize()
{
CreateCloudTableClient().GetTableReference(TableName).CreateIfNotExists();
}
public override ErrorLogEntry GetError(string id)
{
return new ErrorLogEntry(this, id, ErrorXml.DecodeString(CreateQuery()
.Where(e => e.PartitionKey == string.Empty && e.RowKey == id).Single().SerializedError));
}
public override int GetErrors(int pageIndex, int pageSize, IList errorEntryList)
{
var context = CreateTableServiceContext();
var count = 0;
foreach (var error in context.CreateQuery<ErrorEntity>(TableName).Where(e => e.PartitionKey == string.Empty)
.AsTableServiceQuery(context).Take((pageIndex + 1) * pageSize).ToList().Skip(pageIndex * pageSize))
{
errorEntryList.Add(new ErrorLogEntry(this, error.RowKey, ErrorXml.DecodeString(error.SerializedError)));
count++;
}
return count;
}
public override string Log(Error error)
{
var entity = new ErrorEntity(error);
Task.Factory.StartNew(() =>
{
int attempts = 0;
bool success = false;
while (!success && attempts < 5)
{
attempts++;
try
{
var context = CreateTableServiceContext();
context.AddObject(TableName, entity);
context.SaveChangesWithRetries();
success = true;
}
catch (Exception)
{
;
}
}
});
return entity.RowKey;
}
public TableErrorLog(IDictionary config)
{
var directlyConfigured = (string)config["connectionString"];
if (!string.IsNullOrEmpty(directlyConfigured))
{
connectionString = directlyConfigured;
}
else
{
var elmahStorageAccountSettingName = (string)config["elmahStorageAccountSettingName"];
connectionString = RoleEnvironment.GetConfigurationSettingValue(elmahStorageAccountSettingName);
RoleEnvironment.Changing += (sender, roleEnvironmentChangingEventArgs) =>
{
connectionString = RoleEnvironment.GetConfigurationSettingValue(elmahStorageAccountSettingName);
Initialize();
};
}
Initialize();
}
public TableErrorLog(string connectionString)
{
this.connectionString = connectionString;
Initialize();
}
}
}
<configuration>
<configSections>
<sectionGroup name="elmah">
<section name="security" requirePermission="false" type="Elmah.SecuritySectionHandler, Elmah" />
<section name="errorLog" requirePermission="false" type="Elmah.ErrorLogSectionHandler, Elmah" />
<section name="errorMail" requirePermission="false" type="Elmah.ErrorMailSectionHandler, Elmah" />
<section name="errorFilter" requirePermission="false" type="Elmah.ErrorFilterSectionHandler, Elmah" />
</sectionGroup>
</configSections>
<appSettings>
<add key="elmah.mvc.disableHandler" value="false" />
<add key="elmah.mvc.disableHandleErrorFilter" value="false" />
<add key="elmah.mvc.requiresAuthentication" value="false" />
<add key="elmah.mvc.allowedRoles" value="*" />
<add key="elmah.mvc.route" value="elmah" />
</appSettings>
<system.webServer>
<modules runAllManagedModulesForAllRequests="true">
<add name="ErrorLog" type="Elmah.ErrorLogModule, Elmah" preCondition="managedHandler" />
<add name="ErrorMail" type="Elmah.ErrorMailModule, Elmah" preCondition="managedHandler" />
<add name="ErrorFilter" type="Elmah.ErrorFilterModule, Elmah" preCondition="managedHandler" />
</modules>
</system.webServer>
<elmah>
<security allowRemoteAccess="yes" />
<errorLog type="MvcWebRole1.TableErrorLog, MvcWebRole1" elmahStorageAccountSettingName="elmahStorageAccount" />
</elmah>
</configuration>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment