[ 
https://issues.apache.org/jira/browse/LOG4NET-306?page=com.atlassian.jira.plugin.system.issuetabpanels:all-tabpanel
 ]

Jon Abaunza updated LOG4NET-306:
--------------------------------

    Description: 
There are several environments where it is required to develop a wrapper around 
Log4Net for backward compatibility with previous logging systems.

The problem comes when it is required to obtain the method name. The system 
goes up in the StackTrace and identifies the wrapper method as the first user 
method and therefore logs the name of the wrapper instead of the real caller 
method.

The solution would be as simple as creating a new MethodAtribute (lets say 
log4Net.SkipMethodForMethodLocation). I would be able to decorate my method 
with it and the MethodLocationPatternConverter would continue looking up in the 
stackTrace for the next user method.


Modifications made (just modified the constructor)

LocationInfo.cs

public class LocationInfo
{
                /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="callerStackBoundaryDeclaringType">The declaring type 
of the method that is
        /// the stack boundary into the logging system for this call.</param>
        /// <remarks>
        /// <para>
        /// Initializes a new instance of the <see cref="LocationInfo" />
        /// class based on the current thread.
        /// </para>
        /// </remarks>
        public LocationInfo(Type callerStackBoundaryDeclaringType) 
        {
                // Initialize all fields
                m_className = NA;
                m_fileName = NA;
                m_lineNumber = NA;
                m_methodName = NA;
                m_fullInfo = NA;
                m_assembly = NA;
#if !NETCF
                if (callerStackBoundaryDeclaringType != null)
                {
                        try
                        {
                                StackTrace st = new StackTrace(true);
                                int frameIndex = 0;
                                // skip frames not from fqnOfCallingClass
                                while (frameIndex < st.FrameCount)
                                {
                                        StackFrame frame = 
st.GetFrame(frameIndex);
                                        if (frame != null && 
frame.GetMethod().DeclaringType == callerStackBoundaryDeclaringType)
                                        {
                                                break;
                                        }
                                        frameIndex++;
                                }
                                // skip frames from fqnOfCallingClass
                                while (frameIndex < st.FrameCount)
                                {
                                        StackFrame frame = 
st.GetFrame(frameIndex);
                                        if (frame != null && 
frame.GetMethod().DeclaringType != callerStackBoundaryDeclaringType)
                                        {
                                                break;
                                        }
                                        frameIndex++;
                                }
                                while (frameIndex < st.FrameCount)
                                {
                                             // now frameIndex is the first 
'user' caller frame
                                        StackFrame locationFrame = 
st.GetFrame(frameIndex);
                                        if (locationFrame != null)
                                        {
                                                System.Reflection.MethodBase 
method = locationFrame.GetMethod();
                                        
                                                if (method != null)
                                                {
                                                        bool skip = false;
                                                                                
                                //NEW CHANGES:
                                                                                
                                //We look for the new Custom attribute 
SkipMethodInMethodLocationAttribute
                                                                                
                                //if the method is decorated with the attribute 
we will continue looking up in the stack
                                                        object[] 
customAttributes = 
method.GetCustomAttributes(typeof(SkipMethodInMethodLocationAttribute), false);
                                                        foreach (object 
customAttribute in customAttributes)
                                                        {
                                                                
SkipMethodInMethodLocationAttribute skipMethodAttribute = customAttribute as 
SkipMethodInMethodLocationAttribute;
                                                                if 
(skipMethodAttribute != null)
                                                                {
                                                                        skip = 
skipMethodAttribute.Skip;
                                                                }
                                                        }
                                                        //If the method was 
decorated with the attribute we continue looking up in the stack
                                                        if (!skip)
                                                        {
                                                                m_methodName = 
method.Name;
                                                                if 
(method.DeclaringType != null)
                                                                {
                                                                        
m_className = method.DeclaringType.FullName;
                                                                }
                                                                m_assembly = 
method.Module.Assembly.FullName;
                                                                m_fileName = 
locationFrame.GetFileName();
                                                                m_lineNumber = 
locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
                                                                // Combine all 
location info
                                                                m_fullInfo = 
m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + ')';
                                                                break;
                                                        }
                                                }                               
                        
                                        }
                                        frameIndex++;
                                }
                        }
                        catch(System.Security.SecurityException)
                        {
                                // This security exception will occur if the 
caller does not have 
                                // some undefined set of SecurityPermission 
flags.
                                LogLog.Debug("LocationInfo: Security exception 
while trying to get caller stack frame. Error Ignored. Location Information Not 
Available.");
                        }
                }
#endif
        }

        //.................End of modifications...............//

}


  was:
There are several environments where it is required to develop a wrapper around 
Log4Net for backward compatibility with previous logging systems.

The problem comes when it is required to obtain the method name. The system 
goes up in the StackTrace and identifies the wrapper method as the first user 
method and therefore logs the name of the wrapper instead of the real caller 
method.

The solution would be as simple as creating a new MethodAtribute (lets say 
log4Net.SkipMethodForMethodLocation). I would be able to decorate my method 
with it and the MethodLocationPatternConverter would continue looking up in the 
stackTrace for the next user method.



> Allowing the MethodLocationPatternConverter to skip certain methods from the 
> call stack when trying to log the caller method (Solution for Log4Net 
> wrappers)
> ------------------------------------------------------------------------------------------------------------------------------------------------------------
>
>                 Key: LOG4NET-306
>                 URL: https://issues.apache.org/jira/browse/LOG4NET-306
>             Project: Log4net
>          Issue Type: Improvement
>          Components: Other
>    Affects Versions: 1.2.9, 1.2.10
>            Reporter: Jon Abaunza
>            Priority: Blocker
>
> There are several environments where it is required to develop a wrapper 
> around Log4Net for backward compatibility with previous logging systems.
> The problem comes when it is required to obtain the method name. The system 
> goes up in the StackTrace and identifies the wrapper method as the first user 
> method and therefore logs the name of the wrapper instead of the real caller 
> method.
> The solution would be as simple as creating a new MethodAtribute (lets say 
> log4Net.SkipMethodForMethodLocation). I would be able to decorate my method 
> with it and the MethodLocationPatternConverter would continue looking up in 
> the stackTrace for the next user method.
> Modifications made (just modified the constructor)
> LocationInfo.cs
> public class LocationInfo
> {
>               /// <summary>
>       /// Constructor
>       /// </summary>
>       /// <param name="callerStackBoundaryDeclaringType">The declaring type 
> of the method that is
>       /// the stack boundary into the logging system for this call.</param>
>       /// <remarks>
>       /// <para>
>       /// Initializes a new instance of the <see cref="LocationInfo" />
>       /// class based on the current thread.
>       /// </para>
>       /// </remarks>
>       public LocationInfo(Type callerStackBoundaryDeclaringType) 
>       {
>               // Initialize all fields
>               m_className = NA;
>               m_fileName = NA;
>               m_lineNumber = NA;
>               m_methodName = NA;
>               m_fullInfo = NA;
>               m_assembly = NA;
> #if !NETCF
>               if (callerStackBoundaryDeclaringType != null)
>               {
>                       try
>                       {
>                               StackTrace st = new StackTrace(true);
>                               int frameIndex = 0;
>                               // skip frames not from fqnOfCallingClass
>                               while (frameIndex < st.FrameCount)
>                               {
>                                       StackFrame frame = 
> st.GetFrame(frameIndex);
>                                       if (frame != null && 
> frame.GetMethod().DeclaringType == callerStackBoundaryDeclaringType)
>                                       {
>                                               break;
>                                       }
>                                       frameIndex++;
>                               }
>                               // skip frames from fqnOfCallingClass
>                               while (frameIndex < st.FrameCount)
>                               {
>                                       StackFrame frame = 
> st.GetFrame(frameIndex);
>                                       if (frame != null && 
> frame.GetMethod().DeclaringType != callerStackBoundaryDeclaringType)
>                                       {
>                                               break;
>                                       }
>                                       frameIndex++;
>                               }
>                               while (frameIndex < st.FrameCount)
>                               {
>                                            // now frameIndex is the first 
> 'user' caller frame
>                                       StackFrame locationFrame = 
> st.GetFrame(frameIndex);
>                                       if (locationFrame != null)
>                                       {
>                                               System.Reflection.MethodBase 
> method = locationFrame.GetMethod();
>                                       
>                                               if (method != null)
>                                               {
>                                                       bool skip = false;
>                                                                               
>                                   //NEW CHANGES:
>                                                                               
>                                   //We look for the new Custom attribute 
> SkipMethodInMethodLocationAttribute
>                                                                               
>                                   //if the method is decorated with the 
> attribute we will continue looking up in the stack
>                                                       object[] 
> customAttributes = 
> method.GetCustomAttributes(typeof(SkipMethodInMethodLocationAttribute), 
> false);
>                                                       foreach (object 
> customAttribute in customAttributes)
>                                                       {
>                                                               
> SkipMethodInMethodLocationAttribute skipMethodAttribute = customAttribute as 
> SkipMethodInMethodLocationAttribute;
>                                                               if 
> (skipMethodAttribute != null)
>                                                               {
>                                                                       skip = 
> skipMethodAttribute.Skip;
>                                                               }
>                                                       }
>                                                       //If the method was 
> decorated with the attribute we continue looking up in the stack
>                                                       if (!skip)
>                                                       {
>                                                               m_methodName = 
> method.Name;
>                                                               if 
> (method.DeclaringType != null)
>                                                               {
>                                                                       
> m_className = method.DeclaringType.FullName;
>                                                               }
>                                                               m_assembly = 
> method.Module.Assembly.FullName;
>                                                               m_fileName = 
> locationFrame.GetFileName();
>                                                               m_lineNumber = 
> locationFrame.GetFileLineNumber().ToString(System.Globalization.NumberFormatInfo.InvariantInfo);
>                                                               // Combine all 
> location info
>                                                               m_fullInfo = 
> m_className + '.' + m_methodName + '(' + m_fileName + ':' + m_lineNumber + 
> ')';
>                                                               break;
>                                                       }
>                                               }                               
>                         
>                                       }
>                                       frameIndex++;
>                               }
>                       }
>                       catch(System.Security.SecurityException)
>                       {
>                               // This security exception will occur if the 
> caller does not have 
>                               // some undefined set of SecurityPermission 
> flags.
>                               LogLog.Debug("LocationInfo: Security exception 
> while trying to get caller stack frame. Error Ignored. Location Information 
> Not Available.");
>                       }
>               }
> #endif
>       }
>       //.................End of modifications...............//
> }

--
This message is automatically generated by JIRA.
For more information on JIRA, see: http://www.atlassian.com/software/jira

        

Reply via email to