C# - (.NET Core 2.2부터 가능한) 프로세스 내부에서 CLR ETW 이벤트 수신
예전에도 ETW를 다뤄봤는데요,
C# - ETW 관련 Win32 API 사용 예제 코드 (4) CLR ETW Consumer
; https://www.sysnet.pe.kr/2/0/12300
ETW(Event Tracing for Windows)를 이용한 닷넷 프로그램의 내부 이벤트 활용
; https://www.sysnet.pe.kr/2/0/12244
저렇게 구현하는 것에 아쉬움이 있었다면 프로세스 외부에서 관리자 권한으로만 이벤트 수신이 가능하다는 점이었습니다. 게다가 in-proc 모니터링을 지원하는 Private Logger는,
C# - ETW 관련 Win32 API 사용 예제 코드 (5) - Private Logger
; https://www.sysnet.pe.kr/2/0/12302
로그 파일로만 출력할 수 있다는 제약이 있었고! 그런데, .NET Core 2.2부터 in-proc 모니터링이 가능하도록 만들었다는 것을 ^^; 이제서야 알게 되었습니다. (.NET Framework에선 4.8까지도 지원하지 않습니다.)
In-process CLR event listeners with .NET Core 2.2
; https://medium.com/criteo-labs/c-in-process-clr-event-listeners-with-net-core-2-2-ef4075c14e87
(그나저나, 전에도 criteo.com 자료였는데 이번에도 좋은 글을 썼군요. ^^)
게다가 소스 코드도 매우 간단합니다. 단순히 다음과 같이 EventListener를 상속받은 타입을 정의하는 것으로,
using System;
using System.Diagnostics.Tracing;
namespace ConsoleApp2
{
class Program
{
static MyEventListener _listener;
static Program()
{
_listener = new MyEventListener();
}
static void Main(string[] args)
{
Console.WriteLine("In-proc ETW Enabled on .NET Core 2.2 or later");
}
}
}
internal class MyEventListener : EventListener
{
protected override void OnEventSourceCreated(EventSource eventSource)
{
base.OnEventSourceCreated(eventSource);
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
}
}
뼈대가 완성됩니다. 이제 원하는 이벤트를 수신하도록 만들면 되는데요, 가령
"예외(Exception)" 이벤트를 수신하고 싶다면 다음과 같이 코드를 작성합니다.
internal class MyEventListener : EventListener
{
// CLR ETW Keywords and Levels
// https://learn.microsoft.com/en-us/dotnet/framework/performance/clr-etw-keywords-and-levels
private const int EXCEPTIONKEYWORD = 0x00008000;
protected override void OnEventSourceCreated(EventSource eventSource)
{
base.OnEventSourceCreated(eventSource);
if (eventSource.Name == "Microsoft-Windows-DotNETRuntime")
{
EnableEvents(eventSource, EventLevel.Verbose, (EventKeywords)EXCEPTIONKEYWORD);
}
}
protected override void OnEventWritten(EventWrittenEventArgs eventData)
{
if ((int)eventData.Keywords == EXCEPTIONKEYWORD)
{
Console.WriteLine($"{DateTime.Now}: {eventData.EventName}");
}
}
}
그럼 정말 잘 동작하는지 테스트를 해봐야겠죠? ^^
static void Main(string[] args)
{
while (true)
{
Console.ReadLine();
try
{
throw new ApplicationException("Exception-thrown");
}
catch (Exception e)
{
Console.WriteLine($"{DateTime.Now}: User-exception");
}
}
}
실행 후, 예외를 발생시키면 이제 화면에는 다음과 같은 출력 결과를 볼 수 있습니다.
2021-01-04 오후 5:23:57: User-exception
2021-01-04 오후 5:23:57: ExceptionThrown_V1
2021-01-04 오후 5:23:57: ExceptionCatchStart
2021-01-04 오후 5:23:57: ExceptionCatchStop
2021-01-04 오후 5:23:57: ExceptionThrownStop
시간을 보면 알 수 있듯이,
외부 프로세스에서 ETW 이벤트를 감시할 때는 시간차가 발생했던 것과는 달리 이제 실시간으로 이벤트를 수신하는 것을 확인할 수 있습니다.
.NET Core 2.2 이상에서만 지원한다는 사실만 제외하면, 모든 면에서 완벽한 CLR ETW 이벤트 수신 기능을 지원하고 있습니다. ^^
(
첨부 파일은 이 글의 예제 프로젝트를 포함합니다.)
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]