James Green
 |
| 06/15/2009 5:25 PM |
|
Hi All,
I've spent about 4 hours today trying to get this working and have totally failed so far.
I can't even really find much info on how to configure this purely in Code. In fact there is precious little I can find on the net in fact.
Here is the code I'm using the set up the AdoNetAppender in my app:
public static void ConfigureDatabaseAppender(string connString) { PatternLayout layout = GetDefaultLayout(); _sqlDatabaseAppender = new AdoNetAppender(); _sqlDatabaseAppender.Layout = layout; _sqlDatabaseAppender.UseTransactions = false; _sqlDatabaseAppender.BufferSize = 1;
_sqlDatabaseAppender.CommandType = System.Data.CommandType.Text; _sqlDatabaseAppender.ConnectionString = connString; _sqlDatabaseAppender.CommandText = "INSERT INTO Log ([Date],[Level],[Thread],[Logger],[Message],[Exception]) VALUES (@log_date, @log_level, @thread, @logger, @message, @exception)"; AdoNetAppenderParameter logDate = new AdoNetAppenderParameter(); RawTimeStampLayout dateLayout = new RawTimeStampLayout(); logDate.ParameterName = "@log_date"; logDate.Layout = dateLayout; logDate.DbType = System.Data.DbType.DateTime; _sqlDatabaseAppender.AddParameter(logDate); AdoNetAppenderParameter logThread = new AdoNetAppenderParameter(); logThread.ParameterName = "@thread"; logThread.Size = 255; logThread.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logThread); AdoNetAppenderParameter logLevel = new AdoNetAppenderParameter(); logLevel.ParameterName = "@log_level"; logLevel.Size = 50; logLevel.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logLevel); AdoNetAppenderParameter logLogger = new AdoNetAppenderParameter(); logLogger.ParameterName = "@logger"; logLogger.Size = 255; logLogger.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logLogger); AdoNetAppenderParameter logMessage = new AdoNetAppenderParameter(); logMessage.ParameterName = "@message"; logMessage.Size = 4000; logMessage.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logMessage); AdoNetAppenderParameter logException = new AdoNetAppenderParameter(); logException.ParameterName = "@exception"; logException.Size = 2000; logException.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logException); _sqlDatabaseAppender.ActivateOptions();
BasicConfigurator.Configure(_sqlDatabaseAppender); }
Any help would be great.
James.
|
|
|
|
|
Matt Lund
 |
| 06/15/2009 5:27 PM |
|
Have you already gotten AdoNetAppender to work from a app.config / web.config first? If not, I'd suggest getting that to work first. You may learn something in that process and it'll spark a realization of what you're missing in the from-code approach?
|
|
|
|
|
James Green
 |
| 06/15/2009 5:31 PM |
|
I may have to try that. Currently it just fails with an "Oject reference not set to an instance of an object."
Thanks,
James.
|
|
|
|
|
codingvista@googlemail.com
 |
| 06/15/2009 5:57 PM |
|
AppConfig is much simpler - you should start with that then convert to this if you need to - not sure why you'd need to tho?
|
|
|
|
|
James Green
 |
| 06/15/2009 6:04 PM |
|
I think I'm going to have to try the config file method first.
I'm wrapping log4net and I don't want to cause every consuming component to require loads of config information in it just for logging purposes.
Everything else is a sinch to configure in code, save for this appender ... *sigh* ...
Cheers,
James. |
|
|
|
|
Ron Grabowski
 |
|
Ron Grabowski
 |
|
James Green
 |
| 06/16/2009 10:39 AM |
|
Hi Ron,
I did actually spot this just after posting the code and it did remove the connection error I was seeing.
However, we have got it logging the date values now, however the other fields are @log_level etc ... are still null.
Any ideas?
Cheers,
James. |
|
|
|
|
James Green
 |
| 06/16/2009 10:48 AM |
|
Hi Again,
Surely, this is all pointing to a far bigger problem. That is an horrific piece of code!! Surely this is doable in pure C#?
I'm amazed that this AdoNetAppender is so poorly documented and has so few examples. It's starting to put me off log4net!
James. |
|
|
|
|
codingvista@googlemail.com
 |
| 06/16/2009 10:57 AM |
|
why don't you write a fluent interface for it!?!?
I think that for FREE software provided with SOURCE - it's a pretty darn good tool at a pretty darn good price - and so does the rest of the _whole_ industry - it being an _industry_ _standard_!
There are plenty of other loggers out there too - for free - open source - some good some not so good - all off the backs of some very hard work by some very tallented and commited people.
w://
|
|
|
|
|
James Green
 |
| 06/16/2009 11:08 AM |
|
Hi Wayne,
I didn't wish to start a flame war.
This is not the first time I've had trouble finding decent log4net docs when configuring without AppConfig, in fact Google hardly returns a thing on this topic. Surely database logging is one of the most popular features and I'm highlighting what I think to be a massive gap in its documentation.
I love log4net, it was a no brainer for me to pick but don't think getting this library configured using pure C# is easy. Have you completed this task without using Xml config? Xml config is not always possible nor desirable.
James. |
|
|
|
|
codingvista@googlemail.com
 |
| 06/16/2009 11:17 AM |
|
No I haven't - and to be fair, I did try doing this a while ago:
<code file='global.asax' method='Application_Start'>
log4net.Config.XmlConfigurator.Configure();
//reset the logger to use the default con string - so we only need to change it on one place var hier = log4net.LogManager.GetRepository() as log4net.Repository.Hierarchy.Hierarchy;
if (hier != null) { //get ADONetAppender var adoAppender = (log4net.Appender.AdoNetAppender)hier.GetLogger("root",hier.LoggerFactory).GetAppender("AdoNetAppender"); var adoAppender = (log4net.Appender.AdoNetAppender)hier.Root.AppendersΎ] if (adoAppender != null) { adoAppender.ConnectionString = AppSettings.GetConfigurationString("MainConnection"); adoAppender.ActivateOptions(); //refresh settings of appender } }
</code>
and failed - but this is possibly because of a few things outside the responsibility of the log4net codebase.
There's nothing wrong working through a poroblem - to help improve the situ - but just rubbishing it won't help anyone.
w://
|
|
|
|
|
James Green
 |
| 06/16/2009 11:23 AM |
|
Hi Again,
<snip> </code>
Indeed, this isn't the most straight forward thing.
>and failed - but this is possibly because of a few things outside the >responsibility of the log4net codebase.
>There's nothing wrong working through a poroblem - to help improve the >situ - but just rubbishing it won't help anyone.
Sure, but when your back is against the wall and you've been given a day to write a complete logging library running up against this problem when *everything* else works as expected is a bit frustrating.
What is even weirder is that I now have dates going into the database ... However, everything else is null ...
I've just pulled it down to two fields now, using this as a pattern:
"%date %level"
Date logs find ... Level is always null ...
You are right, rubbishing it is plain stupid on my part.
Cheers,
James. |
|
|
|
|
James Green
 |
| 06/16/2009 11:58 AM |
|
Cracked it ...
AdoNetAppenderParameter logLevel = new AdoNetAppenderParameter(); logLevel.ParameterName = "@log_level"; logLevel.Layout = new Layout2RawLayoutAdapter(new PatternLayout("%level")); logLevel.Size = 50; logLevel.DbType = System.Data.DbType.String; _sqlDatabaseAppender.AddParameter(logLevel);
Regards,
James. |
|
|
|
|
codingvista@googlemail.com
 |
| 06/16/2009 12:01 PM |
|
bet that was a 'punching hands in the air' geek moment from hell!!!!
|
|
|
|
|
James Green
 |
| 06/16/2009 12:20 PM |
|
> bet that was a 'punching hands in the air' geek moment from hell!!!!
Indeed ... I may even make a cup of tea to celebrate! :)
Cheers,
James. |
|
|
|
|
Ron Grabowski
 |
|
Ron Grabowski
 |
| 06/17/2009 12:12 AM |
|
You could have also copied the built-in TimeStamp layout
// log4net.Layout public class RawTimeStampLayout : IRawLayout { public object Format(LoggingEvent loggingEvent) { return loggingEvent.TimeStamp; } }
and made your own Level layout:
public class RawLevelLayout : IRawLayout { public object Format(LoggingEvent loggingEvent) { return loggingEvent.Level; } }
|
|
|
|
|
James Green
 |
| 06/17/2009 10:27 AM |
|
Hi Ron,
For sure, I totally understand that!
I think it would be good to include some C# config examples. I just have to finish off my wrapper and then I'll get my C# code over to you for comment / inclusion in the docs.
Thanks!
James. |
|
|
|
|