How to use my own ErrorLog?

111 views
Skip to first unread message

shapper

unread,
Oct 29, 2009, 7:18:42 AM10/29/09
to ELMAH
Hello,

I created a custom ErrorLog class that uses Linq and my own Error
table.

The problem is this is not a Module so I can't add this to Web.Config
Modules.
I suppose I need to place Elmah Module in Web.Config and "tell" which
ErrorService should be used?

Is that it? How should I do this?

My ErrorLog class is as follows:

// ----------- BEGIN CODE -----------

public class ErrorModule : ErrorLog {

// GetError
public override ErrorLogEntry GetError(String id) {

// Check parameters
if (id == null) throw new ArgumentNullException("id");
if (id.Length == 0) throw new ArgumentOutOfRangeException("id");

// Get error
ISession session = new Context();
ErrorService errorService = new ErrorService(session);
Domain.Models.Error error = errorService.GetById
(this.ApplicationName, Int32.Parse(id));
session.Commit();

// Parse error
if (String.IsNullOrEmpty(error.Content)) return null;
Elmah.Error _error = ErrorXml.DecodeString(error.Content);
return new ErrorLogEntry(this, id, _error);

} // GetError

// GetErrors
public override Int32 GetErrors(Int32 pageIndex, Int32 pageSize,
IList errorEntryList) {

// Check parameters
if (pageIndex < 0) throw new ArgumentOutOfRangeException
("pageIndex", pageIndex, null);
if (pageSize < 0) throw new ArgumentOutOfRangeException
("pageSize", pageSize, null);

// Get errors
ISession session = new Context();
ErrorService errorService = new ErrorService(session);
IQueryable<Domain.Models.Error> errors = errorService.GetByPage
(this.ApplicationName, pageIndex, pageSize);
session.Commit();

// Parse errors xml
foreach (Domain.Models.Error e in errors) {
Elmah.Error error = ErrorXml.DecodeString(e.Content);
errorEntryList.Add(new ErrorLogEntry(this, e.Id.ToString(),
error));
}

return errors.Count();

} // GetErrors

// Log
public override String Log(Elmah.Error error) {

// Check parameters
if (error == null) throw new ArgumentNullException("error");

// Define error
Domain.Models.Error _error = new Domain.Models.Error {
Application = this.ApplicationName,
Content = ErrorXml.EncodeString(error),
Created = error.Time.ToUniversalTime(),
Host = error.HostName,
Message = error.Message,
Status = error.StatusCode,
Source = error.Source,
Type = error.Type,
User = error.User
};

// Create error
ISession session = new Context();
ErrorService errorService = new ErrorService(session);
errorService.Create(_error);
session.Commit();
return _error.Id.ToString();

} // Log

} // ErrorModule

// ----------- END CODE -----------

Thanks,
Miguel

James_2JS

unread,
Oct 29, 2009, 7:39:40 AM10/29/09
to ELMAH
Hi Miguel,

Sounds like you're making good progress!!

I think you've got a bit of a naming issue going on here which may be
confusing you slightly.
Let's look at some of the other log provider declarations:

public class SqlErrorLog : ErrorLog
public class OracleErrorLog : ErrorLog
public class SQLiteErrorLog : ErrorLog

Try changing your declaration to something like this (assuming you're
using LinqToSql):

public class LinqToSqlErrorLog : ErrorLog

Notice how none of this has anything to do with Modules!!
ELMAH already has the ErrorLogModule which will log unhandled
exceptions to a configured ErrorLog.

Now look in the <elmah> section of your web.config. You'll see a line
that looks like this:

<errorLog type="Elmah.SqlErrorLog, Elmah"
connectionStringName="..." />

This tells the ErrorLogModule which ErrorLog implementation to use.
So you would probably want to change this to be:

<errorLog type="YourNameSpace.LinqToSqlErrorLog, YourDll"
attribute1="" attribute2="" />

where attribute1 and attribute2 are placeholders for any attributes
that you may require for your specific implementation.

Hope this helps!

James

shapper

unread,
Oct 29, 2009, 10:41:21 AM10/29/09
to ELMAH
Hello,

I followed your advice and gave it a new name.
I also added those code lines to Web.Config and I get an error:

Constructor on type 'MyApp.Application.LinqToSqlErrorLog' not found.
Description: An unhandled exception occurred during the execution of
the current web request. Please review the stack trace for more
information about the error and where it originated in the code.

Exception Details: System.MissingMethodException: Constructor on type
'MyApp.Application.LinqToSqlErrorLog' not found.

[MissingMethodException: Constructor on type
'BonsAlunos.Application.LinqToSqlErrorLog' not found.]
System.RuntimeType.CreateInstanceImpl(BindingFlags bindingAttr,
Binder binder, Object[] args, CultureInfo culture, Object[]
activationAttributes) +1051
System.Activator.CreateInstance(Type type, BindingFlags
bindingAttr, Binder binder, Object[] args, CultureInfo culture, Object
[] activationAttributes) +111
System.Activator.CreateInstance(Type type, Object[] args) +16
Elmah.SimpleServiceProviderFactory.CreateFromConfigSection(String
sectionName) +309
Elmah.ErrorLog.GetDefault(HttpContext context) +132
Elmah.ErrorPageBase.get_ErrorLog() +60
Elmah.ErrorLogPage.OnLoad(EventArgs e) +387
System.Web.UI.Control.LoadRecursive() +50
System.Web.UI.Page.ProcessRequestMain(Boolean
includeStagesBeforeAsyncPoint, Boolean includeStagesAfterAsyncPoint)
+627

I added the following to my code but keep having the error:

public class LinqToSqlErrorLog : ErrorLog {

public LinqToSqlErrorLog() {
}

// Rest of the code as posted before
}

Any idea what I am doing wrong?

Thanks,
Miguel

James_2JS

unread,
Oct 29, 2009, 10:50:46 AM10/29/09
to ELMAH
Hi again!

I think you're missing a constructor that accepts an IDictionary as
its only parameter.

I would recommend looking at one of the existing ErrorLog
implementations and checking what your missing from there.
The big things you are missing are:

1) The correct signature for the constructor

public LinqToSql(IDictionary config)

NB the dictionary will give you the parameters from the config (which
I described as attribute1 and attribute2 in my previous post)

2) An override for the name property e.g.

public override string Name
{
get { return "LinqToSql Error Log"; }
}

So that your implementation gets correctly described in elmah.axd

Hope this helps!

Cheers,

James
> > > Miguel- Hide quoted text -
>
> - Show quoted text -

shapper

unread,
Oct 29, 2009, 10:52:24 AM10/29/09
to ELMAH
On my Web.Config I have:

<elmah>
<security allowRemoteAccess="1" />
<errorLog type="MyApp.Application.LinqToSqlErrorLog,
MyApp.Application"/>
</elmah>

And I change the code as follows:

public class LinqToSqlErrorLog : ErrorLog {

private ISession _session;
private ErrorService _errorService;

public LinqToSqlErrorLog() {

_session = new Context();
_errorService = new ErrorService(_session);

}

public override ErrorLogEntry GetError(String id) {

// Check parameters
if (id == null) throw new ArgumentNullException("id");
if (id.Length == 0) throw new ArgumentOutOfRangeException("id");

// Get error
Domain.Models.Error error = _errorService.GetById
(this.ApplicationName, Int32.Parse(id));
_session.Commit();

// Parse error
if (String.IsNullOrEmpty(error.Content)) return null;
Elmah.Error _error = ErrorXml.DecodeString(error.Content);
return new ErrorLogEntry(this, id, _error);

} // GetError

// GetErrors
public override Int32 GetErrors(Int32 pageIndex, Int32 pageSize,
IList errorEntryList) {

// Check parameters
if (pageIndex < 0) throw new ArgumentOutOfRangeException
("pageIndex", pageIndex, null);
if (pageSize < 0) throw new ArgumentOutOfRangeException
("pageSize", pageSize, null);

// Get errors
IQueryable<Domain.Models.Error> errors = _errorService.GetByPage
(this.ApplicationName, pageIndex, pageSize);
_session.Commit();

// Parse errors xml
foreach (Domain.Models.Error e in errors) {
Elmah.Error error = ErrorXml.DecodeString(e.Content);
errorEntryList.Add(new ErrorLogEntry(this, e.Id.ToString(),
error));
}

// Return errors count
return errors.Count();

} // GetErrors

// Log
public override String Log(Elmah.Error error) {

// Check parameters
if (error == null) throw new ArgumentNullException("error");

// Define error
Domain.Models.Error _error = new Domain.Models.Error {
Application = this.ApplicationName,
Content = ErrorXml.EncodeString(error),
Created = error.Time.ToUniversalTime(),
Host = error.HostName,
Message = error.Message,
Status = error.StatusCode,
Source = error.Source,
Type = error.Type,
User = error.User
};

// Create error
_errorService.Create(_error);
_session.Commit();
return _error.Id.ToString();

} // Log

}

I keep having the same Constructor error.

Any idea what I am doing wrong?

I have the constructor defined on my log ...

Thanks,
Miguel

Atif Aziz

unread,
Oct 29, 2009, 6:30:16 PM10/29/09
to el...@googlegroups.com
I keep having the same Constructor error.
Any idea what I am doing wrong?
I have the constructor defined on my log ...
 
Yes you have a parameterless constructor but the one ELMAH requires is one that takes a since parameter typed as IDictionary as James already pointed out.
 
- Atif

Reply all
Reply to author
Forward
0 new messages