ELMAH Bootstrapper automatically registers ELMAH during application start-up. It is available as a NuGet package and designed to work with ASP.NET 4.x web applications only.
ELMAH (Error Logging Modules and Handlers) is an ASP.NET web application-wide error logging facility that is completely pluggable. It can be enabled without changing a single line of your application code so there is no need for re-compilation or re-deployment.
ELMAH is wired into an application by registering its modules and handlers via
the application's configuration (web.config
). Getting all the registration
configuration right can occasionally get frustrating as the details can vary
between hosting servers, like IIS, and when going from development to
production.
Recent versions of ASP.NET have made it possible to dynamically register modules at run-time, during application start-up, and that is exactly what ELMAH Bootstrapper does.
Once you add ELMAH Bootstrapper via NuGet, it will automatically add ELMAH (if not already installed) and register it with your web application without any need for configuration whatsoever.
To view error log pages, simply navigate to elmah
, errors
or errorlog
under your web application root. So if your web application is installed at
http://www.example.com/
then any of the following URLs can be used to reach
the ELMAH web interface:
http://www.example.com/elmah
http://www.example.com/errors
http://www.example.com/errorlog
You can change this by adding the key elmah:web:path
under <appSettings>
in your web.config
:
<add key="elmah:web:path" value="/admin/errors" />
Now the error log web will be reachable at http://www.example.com/admin/elmah
.
(note that the value is case-sensitive). You can even list multiple
space-separated paths though one will usually suffice.
ELMAH Bootstrapper can also select the ErrorLog
implementation based on
certain conventions. For example, if you add the folders App_Data\errors\xmlstore
under your web application root then errors will automatically be logged there
as XML files, using XmlFileErrorLog
.
ELMAH ships with six ErrorLog
implementations that use a database for
storage:
SqlErrorLog
SQLiteErrorLog
SqlServerCompactErrorLog
OracleErrorLog
MySqlErrorLog
PgsqlErrorLog
To use one of these, create a connection string entry in your
web.config
named elmah:LOGNAME
where LOGNAME
is the error log name
minus the ErrorLog
suffix (case-insensitive). So to use SqlErrorLog
,
create a connection string named elmah:sql
.
If the ErrorLog
implementation requires additional settings, these can
be supplied via appSettings
using the naming convention
elmah:LOGNAME:KEY
, e.g. elmah:sql:applicationName
.
With ELMAH Bootstrapper, you can also selectively filter errors (to
prevent them being logged or e-mailed) by simply adding a file named
Elmah.ErrorFilter.config
in your web application root. The content of the
file should be the desired filtering rules in XML, like:
<and>
<greater binding="HttpStatusCode" value="399" type="Int32" />
<lesser binding="HttpStatusCode" value="500" type="Int32" />
</and>
If the file doesn't start with the angle bracket <
then you can throw in
an error filtering rule expressed entirely as a JScript Boolean
expression:
// @assembly mscorlib
// @assembly System.Web, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a
// @import System.IO
// @import System.Web
$.HttpStatusCode == 404
|| $.BaseException instanceof FileNotFoundException
|| $.BaseException instanceof HttpRequestValidationException
/* Using RegExp below (see http://msdn.microsoft.com/en-us/library/h6e2eb7w.aspx) */
|| $.Context.Request.UserAgent.match(/crawler/i)
|| $.Context.Request.ServerVariables['REMOTE_ADDR'] == '127.0.0.1' // IPv4 only
For some inspiration on rules, see Error Filtering Examples.
ELMAH Bootstrapper can refresh the error filtering rules whenever the
Elmah.ErrorFilter.config
file is updated without causing the application to
restart!
ELMAH Bootstrapper also allows control over who is authorized to see the
built-in error log web. The NuGet package automatically adds a file called
Elmah.Athz.config
with a single rule permitting only local requests:
@local
Each line of the file represents an access grant or denial and here is what to keep in mind:
- To allow users access, simply list their accounts on separate lines.
- An asterisk (
*
) represents all authenticated users. - A question mark (
?
) represents all anonymous users. - Roles are identified with a caret prefix (
^
), like this:^admins
- A line starting with an exclamation mark or bang (
!
) is a denial; otherwise a grant. - Denials take precedence over grants.
- A hash or pound (
#
) delimits a single-line comment. @local
is special and represents a local request.
Here is an example Elmah.Athz.config
:
# this is a single-line comment
!? # deny anonymous users
^admins # allow users in admin role
^ops # allow users in ops role
!bob # deny Bob
alice # allow Alice
@local # allow local requests
Changes to authorization file are effective immediately and without requiring a restart of the web application.
If you do not want to use Global.asax
, ELMAH Bootrapper also provides
global hooks for module events via its App.OnModuleEvent
method. The
following code illustrates how to use it for various module events:
using Elmah;
using Elmah.Bootstrapper;
static class MyWebApp
{
static void Init()
{
App.OnModuleEvent(
(m, h) => m.Filtering += h,
(m, h) => m.Filtering -= h,
h => new ExceptionFilterEventHandler((sender, args) => h(sender, args)),
(IExceptionFiltering sender, ExceptionFilterEventArgs args) =>
{
// TODO event handling code
});
App.OnModuleEvent(
(m, h) => m.Mailing += h,
(m, h) => m.Mailing -= h,
h => new ErrorMailEventHandler((sender, args) => h(sender, args)),
(Elmah.ErrorMailModule sender, ErrorMailEventArgs args) =>
{
// TODO event handling code
});
App.OnModuleEvent(
(m, h) => m.Mailing += h,
(m, h) => m.Mailing -= h,
h => new ErrorMailEventHandler((sender, args) => h(sender, args)),
(Elmah.ErrorMailModule sender, ErrorMailEventArgs args) =>
{
// TODO event handling code
});
App.OnModuleEvent(
(m, h) => m.DisposingMail += h,
(m, h) => m.DisposingMail -= h,
h => new ErrorMailEventHandler((sender, args) => h(sender, args)),
(Elmah.ErrorMailModule sender, ErrorMailEventArgs args) =>
{
// TODO event handling code
});
App.OnModuleEvent(
(m, h) => m.Logged += h,
(m, h) => m.Logged -= h,
h => new ErrorLoggedEventHandler((sender, args) => h(sender, args)),
(Elmah.ErrorLogModule sender, ErrorLoggedEventArgs args) =>
{
// TODO event handling code
});
}
}