Search code examples
.netlog4netpostsharp

Delete prefix in PostSharp log message


I use PostSharp LogAttribute and log4net to generate a trace for all methods called.

The output is good but I want to get rid of repeated label Entering: on each line:

17:48:34,694 [Main      ]       Entering: LoginPopUp.LoginClick() 
17:48:34,695 [Main      ]         Entering: UserRepository.GetUser() 
17:48:34,695 [Main      ]           Entering: UserRepository.IsAdmin() 
17:48:34,696 [Main      ]             Entering: SecurityManager.Encrypt() 

From this answer it's clear that PostSharp team is not going to add message format customization.

There is also an example of the custom TraceAttribute derived from OnMethodBoundaryAspect and it seems to be more flexible to customize. But the problem is that in this case I lose indents showing nesting level (which is more important for me than having the Entering word on every line).

The best solution would be to extend the LogAttribute just to customize the prefix but I don't know if it's possible.

So how can I delete the Entering: prefix?

Working code based on Peter answers

    static readonly Dictionary<Thread, int> DepthDictionary = new Dictionary<Thread, int>();

    // Invoked at runtime before that target method is invoked.
    public override void OnEntry(MethodExecutionArgs args)
    {
        int depth;
        DepthDictionary.TryGetValue(Thread.CurrentThread, out depth);
        Trace.WriteLine(getIndent(depth) + this.enteringMessage, this.category);
        DepthDictionary[Thread.CurrentThread] = depth+1;
    }

    // Invoked at runtime after the target method is invoked (in a finally block).
    public override void OnExit(MethodExecutionArgs args)
    {
        var depth = --DepthDictionary[Thread.CurrentThread];
        Trace.WriteLine(getIndent(depth) + this.exitingMessage, this.category);
    }

    private string getIndent(int depth)
    {
        string result = "";
        for (int i = 0; i < depth; i++) result += "    ";
        return result;
    }

Solution

  • When your solution is not multi threading you can just add the ident your self:

        // Invoked only once at runtime from the static constructor of type declaring the target method.
        public override void RuntimeInitialize(MethodBase method)
        {
            string methodName = method.DeclaringType.FullName + method.Name;
            this.enteringMessage = methodName;
            this.exitingMessage = methodName;
        }
    
        static int depth = 0; 
    
        // Invoked at runtime before that target method is invoked.
        public override void OnEntry(MethodExecutionArgs args)
        {
            Trace.WriteLine(getIndent()+this.enteringMessage, this.category);
            depth++;
        }
    
        // Invoked at runtime after the target method is invoked (in a finally block).
        public override void OnExit(MethodExecutionArgs args)
        {
            depth--;
            Trace.WriteLine(getIndent()+this.exitingMessage, this.category);
        }
    
        private string getIndent(){
            string result = "";
            for (int i = 0; i < depth;i++) result += "    ";
            return result;
        }
    

    example-trace