Remember my previous blogpost about Umbraco, ELMAH (with SQL CE 4.0) and authentication?
After some nice chats with the creator of ELMAH, Atif Aziz, I tried to implement my wishes without modifying the ELMAH core, so it’s easy to upgrade ELMAH with, for example, NuGet.
I also tried not having to create a sub-application to use ELMAH in conjunction with Basic Authentication, by using MADAM, but I just couldn’t get that to work. One of my must-haves was it should use Windows Authentication, but that’s only possible by using the default IIS implementation as far as I know.
Anyway, my journey to add my wishes to ELMAH without modifying the core went well!
After a nice chat with Atif on Twitter, I’ve created a wrapper for the ErrorLogModule and managed to remove the AUTH_PASSWORD server var and add a custom HTTP_RAW_URL server var. It’s kind of a hack and only work with SQL CE, but hey, it works fine for me!
Also I’m now using the errorLog’s applicationName attribute to set a static application name.
Here’s the code:
public class CustomErrorLogModule : ErrorLogModule { protected override void OnInit(HttpApplication application) { this.Logged += new ErrorLoggedEventHandler(CustomErrorLogModule_Logged); base.OnInit(application); } protected override void LogException(Exception e, HttpContext context) { context.Items.Add("RAW_URL", context.Request.RawUrl); base.LogException(e, context); } void CustomErrorLogModule_Logged(object sender, ErrorLoggedEventArgs args) { SqlServerCompactErrorLog sqlServerCompactErrorLog = args.Entry.Log as SqlServerCompactErrorLog; if (sqlServerCompactErrorLog != null) { Error error = args.Entry.Error; error.ServerVariables.Remove("AUTH_PASSWORD"); error.ServerVariables.Add("HTTP_RAW_URL", HttpContext.Current.Items["RAW_URL"].ToString()); HttpContext.Current.Items.Remove("RAW_URL"); string errorXml = ErrorXml.EncodeString(error); const string query = @" UPDATE ELMAH_Error SET [AllXml] = @AllXml WHERE [ErrorId] = @ErrorId;"; using (SqlCeConnection connection = new SqlCeConnection(sqlServerCompactErrorLog.ConnectionString)) { using (SqlCeCommand command = new SqlCeCommand(query, connection)) { SqlCeParameterCollection parameters = command.Parameters; parameters.Add("@AllXml", SqlDbType.NText).Value = errorXml; parameters.Add("@ErrorId", SqlDbType.UniqueIdentifier).Value = args.Entry.Id; command.Connection = connection; connection.Open(); command.ExecuteNonQuery(); } } } } }
With log4net it is possible to enable logging at runtime without modifying the original application binary and without incurring a high performance cost. Multiple “levels” of logging can be set within your program as well, and so you can determine quickly where “fatal” errors occur, and where “warnings” occur that can be ignored in the safe running of your application.