You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4net-user@logging.apache.org by xalex <al...@pixafe.com> on 2009/07/18 22:53:58 UTC

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.


RE: Wrapping Log4Net

Posted by Roy Chastain <Ro...@roychastain.org>.
Sorry, I mixed code from two different versions in what I sent you.  Forget that you saw KmsTraceLogImpl, it is really KmsLogger, which is NOT a ILoggerRepository, but instead derives from log4net.Core.LogImpl.  I also removed the IKMSTraceLog interface and just defined the methods within KmsLogger.  I could find no advantage to having the interface.

So, in the code below where you see
public class KmsTraceLogImpl: log4net.Core.LogImpl, IKmsTraceLog
it should read
public class KmsLogger: log4net.Core.LogImpl

Since getting from what I have given you to the full implementation is just a lot of tedious code, I am posting the code on my SkyDrive account at 
http://cid-08858f983336f8ec.skydrive.live.com/self.aspx/.Public/CoreLog4Net.zip
Note that there is code in there to handle Event Log logging, but it does not fully work.
Also take a look at the LTUniqueId class.  Classes can derive from it or implement ILTUniqueId to provide unique instance tracking in the log entries.

----------------------------------------------------------------------
Roy Chastain




-----Original Message-----
From: steven higgan [mailto:steven.higgan@gmail.com] 
Sent: Wednesday, July 22, 2009 4:39 AM
To: Log4NET User
Subject: Re: Wrapping Log4Net

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<Ro...@roychastain.org> 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:alex@pixafe.com]
> Sent: Tuesday, July 21, 2009 1:40 AM
> To: log4net-user@logging.apache.org
> 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:alex@pixafe.com]
>> Sent: 18 July 2009 21:54
>> To: log4net-user@logging.apache.org
>> 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.
>
>

Re: Wrapping Log4Net

Posted by steven higgan <st...@gmail.com>.
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<Ro...@roychastain.org> 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:alex@pixafe.com]
> Sent: Tuesday, July 21, 2009 1:40 AM
> To: log4net-user@logging.apache.org
> 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:alex@pixafe.com]
>> Sent: 18 July 2009 21:54
>> To: log4net-user@logging.apache.org
>> 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.
>
>

RE: Wrapping Log4Net

Posted by Roy Chastain <Ro...@roychastain.org>.
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:alex@pixafe.com] 
Sent: Tuesday, July 21, 2009 1:40 AM
To: log4net-user@logging.apache.org
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:alex@pixafe.com]
> Sent: 18 July 2009 21:54
> To: log4net-user@logging.apache.org
> 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.


RE: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
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:alex@pixafe.com] 
> Sent: 18 July 2009 21:54
> To: log4net-user@logging.apache.org
> 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.


RE: Wrapping Log4Net

Posted by James Green <Ja...@occam-dm.com>.
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:alex@pixafe.com] 
Sent: 18 July 2009 21:54
To: log4net-user@logging.apache.org
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]



Re: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
thanks Bruno, 
i think this is exactly what i need, i will have a closer look

Alex

Bruno Baia-2 wrote:
> 
> Hi,
> 
> Did you look at Common.Logging ?
> 
> http://netcommon.sourceforge.net/
> 
> 
> - Bruno
> 
> 

-- 
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24582013.html
Sent from the Log4net - Users mailing list archive at Nabble.com.


Re: Wrapping Log4Net

Posted by Bruno Baia <br...@gmail.com>.
Hi,

Did you look at Common.Logging ?

http://netcommon.sourceforge.net/


- Bruno

2009/7/20 xalex <al...@pixafe.com>

>
> Hi Peter, thanks for your reply.
>
> A - if wrapping is simply possible it offers flexibility: think of a large
> system landscape with hundrets of visual studio projects. If there is a
> change in the log4net version, you have to update all these references. If
> it is wrapped, you can do this once (if the interface stays stable, and it
> should do so!).
>
> B - I think I have to have a deeper look on LoggerWrapperImpl, this should
> help. The log4nt internal class LocationInfo walks the stack, so I dont
> want
> do this again, an i hope I dont need it
>
> C - I will tell you what was wrong, after fixing it :-)
>
> -Alex
>
> --
> View this message in context:
> http://www.nabble.com/Wrapping-Log4Net-tp24551728p24564232.html
> Sent from the Log4net - Users mailing list archive at Nabble.com.
>
>

Re: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
Hi Peter, thanks for your reply.

A - if wrapping is simply possible it offers flexibility: think of a large
system landscape with hundrets of visual studio projects. If there is a
change in the log4net version, you have to update all these references. If
it is wrapped, you can do this once (if the interface stays stable, and it
should do so!).

B - I think I have to have a deeper look on LoggerWrapperImpl, this should
help. The log4nt internal class LocationInfo walks the stack, so I dont want
do this again, an i hope I dont need it

C - I will tell you what was wrong, after fixing it :-)

-Alex

-- 
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24564232.html
Sent from the Log4net - Users mailing list archive at Nabble.com.


Re: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
Hi Daniel,

first of all, thank you for this hint. 
My goal is to use my simple ILog interface (as i sketched) from the
application code and to get the logger by calling ILog logger =
LogManager.GetLogger(typeof( typeof<current class>));
I would like to get this according to the current class because I want to
controll the logging intensity on namespace level. I also would like to
avoid the config-files / or use these only in case of problems for remote
debúgging.

I had a look at ILogger but I did not find out how to get this ILogger.
There is an interface to get a logger according to a string (name?) via
ILoggerRepository. But when I call LogManager.GetRepository and then
rep.GetCurrentLoggers() there are no loggers defined... The documentation
did not help me.

Thank you
Alex



Daniel Marohn wrote:
> 
>> private log4net.ILog _log;
> 
> I think this line is wrong. You use an Implementation of ILog for your
> wrapper. This implementation will do the same checks, your
> Implementation does and it sets the locationinfo onto your position
> (from the point of the _log instance, your code is doing the logging).
> Change the type to ILogger and log Messages like this:
> 
> private readonly static Type ThisDeclaringType = typeof(MyLog);
> 		virtual public void Debug(object message, Exception exception)
> 		{
> 			Logger.Log(ThisDeclaringType, m_levelDebug, message, exception);
> 		}
> 		virtual public void DebugFormat(string format, params object[] args)
> 		{
> 			if (IsDebugEnabled)
> 			{
> 				Logger.Log(ThisDeclaringType, m_levelDebug, new
> SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
> 			}
> 		}
> 
> 

-- 
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24580218.html
Sent from the Log4net - Users mailing list archive at Nabble.com.


Re: Wrapping Log4Net

Posted by Daniel Marohn <ma...@sipgate.de>.
Hi Alex,

> private log4net.ILog _log;

I think this line is wrong. You use an Implementation of ILog for your
wrapper. This implementation will do the same checks, your
Implementation does and it sets the locationinfo onto your position
(from the point of the _log instance, your code is doing the logging).
Change the type to ILogger and log Messages like this:

private readonly static Type ThisDeclaringType = typeof(MyLog);
		virtual public void Debug(object message, Exception exception)
		{
			Logger.Log(ThisDeclaringType, m_levelDebug, message, exception);
		}
		virtual public void DebugFormat(string format, params object[] args)
		{
			if (IsDebugEnabled)
			{
				Logger.Log(ThisDeclaringType, m_levelDebug, new
SystemStringFormat(CultureInfo.InvariantCulture, format, args), null);
			}
		}

I copied this code from LogImpl.cs and LoggerWrapperImpl.cs. It's a
damm good peace of code, and it's fun reading.

I hope this helps

Daniel

-- 
Daniel Marohn - marohn@sipgate.de
Telefon: +49 (0)211-63 55 55-0
Telefax: +49 (0)211-63 55 55-22
sipgate GmbH - Gladbacher Str. 74 - 40219 Düsseldorf
HRB Düsseldorf 39841 - Geschäftsführer: Thilo Salmon, Tim Mois
Steuernummer: 106/5724/7147, Umsatzsteuer-ID: DE219349391
www.sipgate.de - www.sipgate.at - www.sipgate.co.uk

RE: Wrapping Log4Net

Posted by Matt Lund <ml...@control4.com>.
Oops, I didn't quite finish one sentence below.  Meant to say "The
practical challenge was that I had to choose between only exposing
simple functionality in my wrapper to keep the coupling loose or
wrapping more of what NHibernate in order to take advantage of what it
offers but at the loss of loose coupling."

 

From: Matt Lund [mailto:mlund@control4.com] 
Sent: Saturday, July 18, 2009 3:20 PM
To: Log4NET User
Subject: RE: Wrapping Log4Net

 

This reminds me of my attempt to wrap our use of NHibernate.  I later
realized this was a bad idea for a practical reason and philosophical
reason.  The practical challenge was that I had to choose between only
exposing simple functionality in my wrapper to keep the coupling loose.
The philosophical epiphany we later had was that there is a difference
between services and frameworks.  Loosely coupling your program to
services is usually a good idea.  Loosely coupling your program to
frameworks is usually a bad idea.

 

In short, I'd reconsider wrapping it.

 

From: Peter Drier [mailto:peter.drier@gmail.com] 
Sent: Saturday, July 18, 2009 3:10 PM
To: Log4NET User
Subject: Re: Wrapping Log4Net

 

Because of "A", wrapping log4net is a bad idea.  It's a noble thought,
but in 10+ years of using log4net and having people around and above me
demand wrapping, I've never seen log4net replaced.   Given you can
always write an appender to output to any other system as necessary, the
"need" for wrapping is moot.  

B)  the only way to wrap it "better" would be to walk the stack
everytime something is logged to see who the calling method was..
Horribly slow, so I wouldn't call it better.

C) Some part of your config is wrong.  We log in release mode all the
time.   

-Peter



On Sat, Jul 18, 2009 at 4:53 PM, xalex <al...@pixafe.com> wrote:


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.

 


RE: Wrapping Log4Net

Posted by Matt Lund <ml...@control4.com>.
This reminds me of my attempt to wrap our use of NHibernate.  I later
realized this was a bad idea for a practical reason and philosophical
reason.  The practical challenge was that I had to choose between only
exposing simple functionality in my wrapper to keep the coupling loose.
The philosophical epiphany we later had was that there is a difference
between services and frameworks.  Loosely coupling your program to
services is usually a good idea.  Loosely coupling your program to
frameworks is usually a bad idea.

 

In short, I'd reconsider wrapping it.

 

From: Peter Drier [mailto:peter.drier@gmail.com] 
Sent: Saturday, July 18, 2009 3:10 PM
To: Log4NET User
Subject: Re: Wrapping Log4Net

 

Because of "A", wrapping log4net is a bad idea.  It's a noble thought,
but in 10+ years of using log4net and having people around and above me
demand wrapping, I've never seen log4net replaced.   Given you can
always write an appender to output to any other system as necessary, the
"need" for wrapping is moot.  

B)  the only way to wrap it "better" would be to walk the stack
everytime something is logged to see who the calling method was..
Horribly slow, so I wouldn't call it better.

C) Some part of your config is wrong.  We log in release mode all the
time.   

-Peter



On Sat, Jul 18, 2009 at 4:53 PM, xalex <al...@pixafe.com> wrote:


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.

 


Re: Wrapping Log4Net

Posted by Peter Drier <pe...@gmail.com>.
Because of "A", wrapping log4net is a bad idea.  It's a noble thought, but
in 10+ years of using log4net and having people around and above me demand
wrapping, I've never seen log4net replaced.   Given you can always write an
appender to output to any other system as necessary, the "need" for wrapping
is moot.

B)  the only way to wrap it "better" would be to walk the stack everytime
something is logged to see who the calling method was..  Horribly slow, so I
wouldn't call it better.

C) Some part of your config is wrong.  We log in release mode all the
time.

-Peter



On Sat, Jul 18, 2009 at 4:53 PM, xalex <al...@pixafe.com> wrote:

>
> 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.
>
>

Re: Wrapping Log4Net

Posted by Michael Schall <mi...@gmail.com>.
If configuring logging programatically is your need it is possible,
but you do loose the ability to change it on in a running process.  I
wouldn't give up the ability to modify loggers/appenders/log levels of
a running process without serious consideration.

2009/7/24 Radovan Raszka <ra...@hasam.cz>:
> Yes, it is possible to configure logging programatically. It was discussed here, see the archive:
> http://mail-archives.apache.org/mod_mbox/logging-log4net-user/200805.mbox/%3c2AD7ECA75635F84A87792C0B2F8692487DDC03@EXCH3.ads.bruker.de%3e
>
> How to get appenders (this example adds or removes file appender):
> private static void enableDebugLog(bool enable)
> {
>        RollingFileAppender rfa = null;
>        log4net.Repository.Hierarchy.Logger root = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root;
>        foreach (AppenderSkeleton appender in LogManager.GetRepository().GetAppenders())
>        {
>                rfa = appender as RollingFileAppender;
>                if (rfa != null) //file appender found!
>                        break;
>        }
>        if (enable)
>        {
>                if (rfa != null) return; // already exists, no need to add
>                RollingFileAppender debugLog = new RollingFileAppender();
>                debugLog.AppendToFile = true;
>                debugLog.File = "Log/Service.log";
>                debugLog.Layout = new log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
>                debugLog.RollingStyle = RollingFileAppender.RollingMode.Date;
>                debugLog.Threshold = log4net.Core.Level.Debug;
>                debugLog.ActivateOptions();
>
>                root.AddAppender(debugLog);
>        }
>        else
>        {
>                if (rfa == null) return; // already doesn't exist, no need to delete
>                root.RemoveAppender(rfa);
>                rfa.Close();
>        }
> }
>
> I think new log entries can not be added to the top of file.
> Radovan Raszka
>
> -----Původní zpráva-----
> Od: xalex [mailto:alex@pixafe.com]
> Odesláno: 23. července 2009 17:44
> Komu: log4net-user@logging.apache.org
> Předmět: Re: Wrapping Log4Net
>
>
> Hi,
>
> i did not find it in the documentation:
> Is it possible to configure appenders by coding without configfiles?
> How do i get the appenders which are currently configured? I would like to change the output destination file of a FileAppender.
> And last question: is it possible to configure a FileAppender so that the newest log entry is at top of the file and not at the bottom?
>
> Thank you in advance!
> Alex
>
> --
> View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24628718.html
> Sent from the Log4net - Users mailing list archive at Nabble.com.
>
>

RE: Wrapping Log4Net

Posted by Radovan Raszka <ra...@hasam.cz>.
Yes, it is possible to configure logging programatically. It was discussed here, see the archive:
http://mail-archives.apache.org/mod_mbox/logging-log4net-user/200805.mbox/%3c2AD7ECA75635F84A87792C0B2F8692487DDC03@EXCH3.ads.bruker.de%3e 

How to get appenders (this example adds or removes file appender):
private static void enableDebugLog(bool enable)
{
	RollingFileAppender rfa = null;
	log4net.Repository.Hierarchy.Logger root = ((log4net.Repository.Hierarchy.Hierarchy)LogManager.GetRepository()).Root;
	foreach (AppenderSkeleton appender in LogManager.GetRepository().GetAppenders())
	{
		rfa = appender as RollingFileAppender;
		if (rfa != null) //file appender found!
			break;
	}
	if (enable)
	{
		if (rfa != null) return; // already exists, no need to add
		RollingFileAppender debugLog = new RollingFileAppender();
		debugLog.AppendToFile = true;
		debugLog.File = "Log/Service.log";
		debugLog.Layout = new log4net.Layout.PatternLayout("%date{dd-MM-yyyy HH:mm:ss,fff} %5level [%2thread] %message (%logger{1}:%line)%n");
		debugLog.RollingStyle = RollingFileAppender.RollingMode.Date;
		debugLog.Threshold = log4net.Core.Level.Debug;
		debugLog.ActivateOptions();
		
		root.AddAppender(debugLog);
	}
	else
	{
		if (rfa == null) return; // already doesn't exist, no need to delete
		root.RemoveAppender(rfa);
		rfa.Close();
	}
}

I think new log entries can not be added to the top of file.
Radovan Raszka

-----Původní zpráva-----
Od: xalex [mailto:alex@pixafe.com] 
Odesláno: 23. července 2009 17:44
Komu: log4net-user@logging.apache.org
Předmět: Re: Wrapping Log4Net


Hi,

i did not find it in the documentation:
Is it possible to configure appenders by coding without configfiles?
How do i get the appenders which are currently configured? I would like to change the output destination file of a FileAppender.
And last question: is it possible to configure a FileAppender so that the newest log entry is at top of the file and not at the bottom?

Thank you in advance!
Alex

--
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24628718.html
Sent from the Log4net - Users mailing list archive at Nabble.com.


Re: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
Hi,

i did not find it in the documentation:
Is it possible to configure appenders by coding without configfiles?
How do i get the appenders which are currently configured? I would like to
change the output destination file of a FileAppender.
And last question: is it possible to configure a FileAppender so that the
newest log entry is at top of the file and not at the bottom?

Thank you in advance!
Alex

-- 
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24628718.html
Sent from the Log4net - Users mailing list archive at Nabble.com.


Re: Wrapping Log4Net

Posted by xalex <al...@pixafe.com>.
Hi,

first of all thanks to all the interesting input!

I want to clearify my requirements and intentions:
- the exchange of log4net is not really planned, it should be only possible
- references to the log4net assembly must be set to a single assembly which
is used in all of our projects
- the use of the logger should be extremely easy, the new interface should
expose only a subset of log4net methods
- we need to configure the levels of different appenders different depending
on the namespace

As shown before using my ILog and MyLog this is possible.
I had just one problem: the %method %line output was wrong, because the call
to the log4net logger was made by my wrapper. I have now implemented an
additional stack-grab which corrects this issue.

- Alex


-- 
View this message in context: http://www.nabble.com/Wrapping-Log4Net-tp24551728p24620454.html
Sent from the Log4net - Users mailing list archive at Nabble.com.