Maneesh R
Maneesh R

Reputation: 13

Postsharp - Log external library, internal calls - c#

Console App A => References Class Library B

[assembly: LogExecutionTime(AttributePriority = 1,
AttributeTargetExternalTypeAttributes = MulticastAttributes.AnyAbstraction | MulticastAttributes.AnyVisibility | MulticastAttributes.AnyImplementation,
AttributeTargetElements = MulticastTargets.Method, AttributeTargetAssemblies = "MyClassLibrary")]

namespace MyConsoleApp
{       
    public class A
    {
        static void Main(string[] args)
        {
            B b1 = new B();
            b.Func1();
        }
    }
}
//class library referenced within same project
namespace MyClassLibrary
{
    public class B
    {
        public void Func1()
        {
            // Do something
            InternalFunc2();
        }

        public void InternalFunc2()
        {
            // Do something else
        }   
    }
}

This is utility method to log to console.

[Serializable]
public sealed class LogExecutionTimeAttribute : OnMethodBoundaryAspect
{
    private static readonly Stopwatch timer = new Stopwatch();

    public override void OnEntry(MethodExecutionArgs args)
    {
        args.MethodExecutionTag = Stopwatch.StartNew();
    }

    public override void OnExit(MethodExecutionArgs args)
    {
        var sw = (Stopwatch)args.MethodExecutionTag;
        sw.Stop();
        Console.WriteLine(args.Method.Name + ":" + sw.Elapsed.TotalMilliseconds);
    }
}

I get logging only for Func1, but not to "InternalFunc2". How do I enable logging to internal function calls within external library?

Thanks, Maneesh

Upvotes: 0

Views: 497

Answers (1)

There are two ways how PostSharp enhances methods.

1) If you apply an aspect to a method in the assembly, where the method is declared, the method itself gets enhanced and the enhancement then works anywhere you call the method, even when you call it from other assemblies.

2) If you apply an aspect to a method in an assembly, where the method is not declared, only the method calls in the assembly are enhanced, so if you call the same methods in other assemblies, where you did not apply the aspect, no enhancement happens.

So the reason of your issue is that the only assembly you are instrumenting is the Console App assembly. Therefore, PostSharp instruments only the external call to the Func1() method, not the method itself, neither any other method in other assemblies.

You have two options here:


a) If you have access to source code of the class library:

1) Have PostSharp NuGet package installed in the class library project.

2) The example in your question shows that you are applying your LogExecutionTime aspect to method calls from the console app to the class library. Remove this from the console app and apply in in the class library. It would look like this:

[assembly: LogExecutionTime(AttributePriority = 1,
   AttributeTargetExternalTypeAttributes = 
     MulticastAttributes.AnyAbstraction
      | MulticastAttributes.AnyVisibility
      | MulticastAttributes.AnyImplementation,
   AttributeTargetElements = MulticastTargets.Method)]

You don't need to specify the assembly here because you will have this code in the class library assembly.

Like this, PostSharp will enhance the methods of the class library, so the logging will happen anytime you call the methods, not only when you call them from the console app.


b) If you don't have the source code, you can still instrument the assembly of the class library using PostSharp Command Line Interface. (Only PostSharp 4.3 and later support this feature as described.)

Documentation: http://doc.postsharp.net/command-line

In your case:

1) Download PostSharp ZIP distribution (PostSharp-.zip) from https://www.postsharp.net/downloads/.

2) Create file postsharp.config with the following content:

<Project xmlns="http://schemas.postsharp.org/1.0/configuration">
  <Property Name="Input" Value="ClassLibraryB.dll" />
  <Property Name="Output" Value="ClassLibraryB.Instrumented.dll" />
  <SearchPath Path="C:\Path\MyAspects" />
  <Multicast>
    <LogExecutionTimeAttribute xmlns="clr-namespace:MyAspectsNS;assembly:MyAspects" />
  </Multicast>
</Project>

You need to edit the file according to your naming and paths.

  • ClassLibraryB.dll is the original assembly of your class library.
  • ClassLibraryB.Instrumented.dll will be the instrumented version of your class library assembly.
  • MyAspectsNS is the namespace where the LogExecutionTimeAttribute aspect is located.
  • MyAspects is the assembly name where the LogExecutionTimeAttribute aspect is located.
  • C:\Path\MyAspects is the directory where the MyAspects.dll assembly is located.

3) Execute tools\postsharp-net40-x86-native.exe postsharp.config. (This executable is found in the ZIP package from step 1.)

4) Replace ClassLibraryB.dll with the ClassLibraryB.Instrumented.dll and copy PostSharp.dll next to other assemblies of your project. You can find it in lib directory of the ZIP package from step 1.

Now all method calls of any method in the class library should be instrumented.

Please note, that PostSharp comes with a ready-made implementation of logging, so you don't need to write the logging logic yourself. See http://doc.postsharp.net/logging.

Upvotes: 2

Related Questions