Uploaded image for project: 'Log4net'
  1. Log4net
  2. LOG4NET-306

Allowing the MethodLocationPatternConverter to skip certain methods from the call stack when trying to log the caller method (Solution for Log4Net wrappers)

    XMLWordPrintableJSON

Details

    • New Feature
    • Status: Closed
    • Minor
    • Resolution: Not A Problem
    • 1.2.9, 1.2.10
    • None
    • Other
    • None

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

      }

      Attachments

        Activity

          People

            Unassigned Unassigned
            abuntxa Jon Abaunza
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

            Dates

              Created:
              Updated:
              Resolved: