A little bit of a progress update:
Let’s say I have my MonoBehaviour
and I want to know how long it took to execute:
public class MyMonoBehaviour : MonoBehaviour
{
private void Awake()
{
Debug.Log("This is an Awake call!");
}
}
then with Sentry I could create spans and surround my code like like so:
public class MyMonoBehaviour : MonoBehaviour
{
private void Awake()
{
SentrySdk.GetSpan()?.StartChild("awake", $"MyMonoBehaviour on {gameObject.name}");
Debug.Log("This is an Awake call!");
SentrySdk.GetSpan()?.Finish(SpanStatus.Ok);
}
}
Now having to do that manually is very cumbersome so the idea is to do that automatically. Ideally, you would not have to think about it and it’s part of the build process.
So for that, I’m using something called IL weaving. During the build process, I grab the compiled Assembly-CSharp.dll
and I look for all classes that inherit from MonoBehaviour
. I then check if they implement the Awake
and if they do I’ll add the span calls.
This is what the original IL looks like:
.method private hidebysig
instance void Awake () cil managed
{
// Method begins at RVA 0x2120
// Header size: 1
// Code size: 11 (0xb)
.maxstack 8
// Debug.Log("This is an Awake call!");
IL_0000: ldstr "This is an Awake call!"
IL_0005: call void [UnityEngine.CoreModule]UnityEngine.Debug::Log(object)
// }
IL_000a: ret
} // end of method MyMonoBehaviour::Awake
and with the automatic instrumentation we end up with this:
.method private hidebysig
instance void Awake () cil managed
{
// Method begins at RVA 0x22b7
// Header size: 1
// Code size: 32 (0x20)
.maxstack 8
// SentryMonoBehaviour.Instance.StartAwakeSpan(this);
IL_0000: call class [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour::get_Instance()
IL_0005: ldarg.0
IL_0006: callvirt instance void [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour::StartAwakeSpan(class [UnityEngine]UnityEngine.MonoBehaviour)
// Debug.Log("This is an Awake call!");
IL_000b: ldstr "This is an Awake call!"
IL_0010: call void [UnityEngine.CoreModule]UnityEngine.Debug::Log(object)
// SentryMonoBehaviour.Instance.FinishAwakeSpan();
IL_0015: call class [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour::get_Instance()
IL_001a: call instance void [Sentry.Unity]Sentry.Unity.SentryMonoBehaviour::FinishAwakeSpan()
// }
IL_001f: ret
} // end of method MyMonoBehaviour::Awake
To note is that I’m using a static helper here instead of directly recreating the call in IL simply because it’s a lot more readable and maintainable to keep as much in C# as possible.
If you want to take a look at it yourself you can check out the PR here: feat: Auto Instrumentation for Awake by bitsandfoxes · Pull Request #998 · getsentry/sentry-unity · GitHub