using PostSharp.Aspects; using PostSharp.Aspects.Advices; using PostSharp.Serialization; using System.Reflection; namespace PostSharp.Samples.Profiling { [PSerializable] public sealed class ProfileAttribute : MethodLevelAspect { MetricMetadata _metadata; public override void RuntimeInitialize(MethodBase method) { this._metadata = ProfilingServices.Collector.RegisterMethod(method); } [OnMethodEntryAdvice, SelfPointcut] public void OnEntry([State(StateScope.MethodInvocation)] out MethodCallData callData) { callData = default; if (ProfilingServices.IsEnabled) { callData.Start(this._metadata); } } [OnMethodSuccessAdvice(Master = nameof(OnEntry))] public static void OnSuccess([State(StateScope.MethodInvocation)] ref MethodCallData callData) { if (!callData.IsNull) { callData.Stop(); Publish(callData); } } [OnMethodExceptionAdvice(Master = nameof(OnEntry))] public static void OnException([State(StateScope.MethodInvocation)] ref MethodCallData callData) { if (!callData.IsNull) { callData.AddException(); callData.Stop(); Publish(callData); } } [OnMethodYieldAdvice(Master = nameof(OnEntry))] public static void OnYield([State(StateScope.MethodInvocation)] ref MethodCallData callData) { if (!callData.IsNull) { callData.Pause(); } } [OnMethodResumeAdvice(Master = nameof(OnEntry))] public static void OnResume([State(StateScope.MethodInvocation)] ref MethodCallData callData) { if (!callData.IsNull) { callData.Resume(); } } private static void Publish(in MethodCallData data) { ProfilingServices.Collector.GetThreadLocalCollector().AddSample(data.Metadata, data.MetricData); } } }