awesome, can you by any chance post your ILoggerRepository implementation (KMS.Core.Log4Net.KmsLogger) ?
On Tue, Jul 21, 2009 at 11:12 PM, Roy Chastain<[email protected]> wrote: > I think we have done what you want, plus a little bit. I have an > Interface > public interface IKmsTraceLog: ILog > { > void Alert (System.Exception ex); > void Alert (string message); > void Alert (string message, System.Exception ex); > void Alert (object target); > void Alert (object target, System.Exception ex); > void Alert (object target, string message); > void Alert (object target, string message, > System.Exception ex); > void Alert (object target, string format, object > param1); > void Alert (object target, string format, params > object[] paramList); > bool IsAlertEnabled > { > get; > } > .... repeat above for each 'level' of trace wanted such as trace, > debug, warn etc) > } > > It is implemented as > public class KmsTraceLogImpl: log4net.Core.LogImpl, IKmsTraceLog > { > public void Alert (System.Exception ex) > { > LogItWithCheck(Level.Alert, null, ex, null); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (string message) > { > LogItWithCheck(Level.Alert, message, null, > null); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (string message, System.Exception ex) > { > LogItWithCheck(Level.Alert, message, ex, null); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target) > { > LogItWithCheck(Level.Alert, null, null, target); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target, System.Exception ex) > { > LogItWithCheck(Level.Alert, null, ex, target); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target, string message) > { > LogItWithCheck(Level.Alert, message, null, > target); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target, string message, > System.Exception ex) > { > LogItWithCheck(Level.Alert, message, ex, > target); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target, string format, object > param1) > { > if (IsAlertEnabled) > LogItNoCheck(Level.Alert, > string.Format(FormatterInstance, format, param1), null, target); > } /* method KmsTraceLogImpl Alert */ > > public void Alert (object target, string format, params > object[] paramList) > { > if (IsAlertEnabled) > LogItNoCheck(Level.Alert, > string.Format(FormatterInstance, format, paramList), null, target); > } /* method KmsTraceLogImpl Alert */ > > public bool IsAlertEnabled > { > get > { > return > Logger.IsEnabledFor(log4net.Core.Level.Alert); > } > } /* property KmsTraceLogImpl > IsAlertEnabled */} > ... repeats for other levels > > /// two helper methods used by each of the above routines. > > private void LogItNoCheck (Level logLevel, object > message, Exception ex, object target) > { > LoggingEvent le; > > le = new LoggingEvent(my_type, > this.Logger.Repository, this.Logger.Name, logLevel, message, ex); > if (target != null) > le.Properties["instance"] = > target.ToString(); > Logger.Log(le); > } /* method KmsTraceLogUtil LogItNoCheck > */ > > /// <summary> > /// Internal log method. All externally visible trace/verbose should go > through here. > /// </summary> > /// <param name="level">The level of the message to be logged.</param> > /// <param name="message">The message object to log.</param> > /// <param name="t">the exception to log, including its stack trace. > Pass <c>null</c> to not log an exception.</param> > /// <remarks> > /// Generates a logging event for the specified <paramref name="level"/> > using > /// the <paramref name="message"/> and <paramref name="t"/>. > /// <para>Code is duplicated from LogItNoCheck for performance > reasons</para> > /// </remarks> > private void LogItWithCheck (Level level, object message, Exception ex, > object target) > { > LoggingEvent le; > > if (Logger.IsEnabledFor(level)) > { > le = new LoggingEvent(my_type, this.Logger.Repository, > this.Logger.Name, level, message, ex); > if (target != null) > le.Properties["instance"] = target.ToString(); > Logger.Log(le); > } > } > } > > Then to use this each class that need unique trace info has a static > member such as > > static private KMS.Core.Log4Net.KmsLogger LogTrace = > KMS.Core.Log4Net.LoggerManager.GetLogger(System.Reflection.MethodBase.Ge > tCurrentMethod().DeclaringType); > > Sometime I even define a virtual method called LogTrace with a get > accessor in a base class that has overriding classes. Then each class > in the tree gets its own static instance of KmsLogger that is returned > by the property so that the correct class, not the base class shows in > the trace. > > Then the calls to log4Net are done as > > LogrTrace.Alert(this,"string and format info",p1,p2,p3...): > Where of course Alert could be Trace, Debug Warn etc. > > This results in an output that looks like with the Full Qualified class > name and method name inserted into the trace. In the example below, I > have the Day, Time Threadid class name and finally my text "- Entered". > Of couse the formatting is done via the config as normal. > > 27 14:11:57.916 [ServiceThread] > KMS.CertMinder.Service.CertMinderService::OnStart - Entered > > One note, is that doing all this does not meet your 2nd requirement of > removing the references to log4Net from the calling projects. They > still care. > > ---------------------------------------------------------------------- > Roy Chastain > > > > > -----Original Message----- > From: xalex [mailto:[email protected]] > Sent: Tuesday, July 21, 2009 1:40 AM > To: [email protected] > Subject: RE: Wrapping Log4Net > > > Hi James, > > yes, this works of course, but there are 2 drawbacks: you need to > request the logger to the type for every single call. Instead of doing > so, i would like to instanciate as static variable per type only once > like this: > private static readonly ILog logger = > LogManager.GetLogger(typeof(Program)); > The second (little) drawback is, that you have to provide the type for > every call. > I have a question: the call to the logger itself is done by your wrapper > code. How did you solve the problem, that the log4net.LocationInfo is > wrong in the logfile? I think also in your case the class, sourcefile > and line will be printed out of your wrapper and not the location of the > application code, right? > > best regards > Alex > > > > > > James Green-5 wrote: >> >> Hi, >> >> Despite what you have been told already I have wrapped log4net, if you > >> do it right it is fine imho. >> >> I wrapped log4net since we need to consume it in scenarios where we >> absoloutely cannot have a plethora of config files kicking around all >> the time simply to enable some logging in the consuming components. >> >> For instance, what if you want to log from an SSIS pipeline? You >> absolutely do not want to generate dependencies on config files in >> such situations. This is also why I had a nightmare of a time getting > >> log4net configured using pure C# because it just doesn't seem to be >> done all that often so isn't documented (I'm working on some docs for >> that scenario to share). >> >> The way I got around the log source problem was to use method >> signatures like this on my wrapper class: >> >> Log.Debug(Type sender, string message) >> >> Then inside the wrapper it is a simple task to request the ILog from >> log4net using the Type parameter, no need to walk the stack. >> >> Works for us anyway ... >> >> Cheers, >> >> James. >> >> -----Original Message----- >> From: xalex [mailto:[email protected]] >> Sent: 18 July 2009 21:54 >> To: [email protected] >> Subject: Wrapping Log4Net >> >> >> Hi forum, >> >> I would like to use log4net in a large .net development. because i >> have the requirement to prepare a potential replacement of the log4net > >> framework e.g. >> against ms-enterprise library or against a newer version of log4net, i > >> would like to wrap this. My way to do it is straight forward: >> A single assembly references the log4net framework, offes the ILog and > >> LogManager classes, and all other projects reference only this wrapper > >> (see below). >> >> This wrapper allows me to restrict the users on only the main >> functions which are really needed and allows me to replace this >> framework, potentially. >> >> Now my question: When the ILog.Debug() Method is called, the output in > >> the logfile is wrong, because the LocationInfo used for this output >> corresponds to the Wrapper and not to the code from which it is really > >> called :-( >> >> A: Is there an easy way to fix this problem? >> B: Is there a better idea to wrap log4net >> C: Is it true, that logging is only possible in DEBUG-Builds? When >> using the release build, i dont get any output >> >> Thanks >> Alex >> >> >> >> Wrapper: >> ------------ >> public interface ILog >> { >> bool IsDebugEnabled { get; } >> bool IsErrorEnabled { get; } >> bool IsFatalEnabled { get; } >> bool IsInfoEnabled { get; } >> bool IsWarnEnabled { get; } >> >> void Debug(object message); >> void Error(object message); >> void Fatal(object message); >> void Info(object message); >> void Warn(object message); >> } >> >> public static class LogManager >> { >> static LogManager() >> { >> XmlConfigurator.Configure( new >> System.IO.FileInfo("c:/logger.xml")) ; >> } >> >> public static ILog GetLogger(Type type) >> { >> MyLog log = new MyLog(log4net.LogManager.GetLogger(type) > ); >> return log; >> } >> } >> >> public class MyLog :ILog >> { >> private log4net.ILog _log; >> >> public MyLog(log4net.ILog log) >> { >> _log = log; >> } >> >> #region ILog Members >> >> public bool IsDebugEnabled >> { >> get { return _log.IsDebugEnabled; } >> } >> >> >> public void Debug(object message) >> { >> _log.Debug(message); >> } >> >> ... >> } >> >> -- >> View this message in context: >> http://www.nabble.com/Wrapping-Log4Net-tp24551728p24551728.html >> Sent from the Log4net - Users mailing list archive at Nabble.com. >> >> >> scanned by MessageLabs [www.messagelabs.com] >> >> >> >> > > -- > View this message in context: > http://www.nabble.com/Wrapping-Log4Net-tp24551728p24581996.html > Sent from the Log4net - Users mailing list archive at Nabble.com. > >
