ETW(Event Tracing for Windows)를 C#에서 사용하는 방법
윈도우 환경에서 사용할 수 있는 고속 로깅 방법이 있습니다.
Application Analysis with Event Tracing for Windows (ETW)
; http://www.codeproject.com/Articles/570690/Application-Analysis-with-Event-Tracing-for-Window
오늘은 위의 글을 따라하면서 ETW를 C#에서 어떻게 사용할 수 있는지 간략하게 정리해 보겠습니다. ^^
우선, ETW 이벤트를 생산하는 측(Producer)을 Provider라 하고, ETW 이벤트를 사용하는 측(Consumer)과 해당 공급자의 로깅 기능을 on/off하라는 지시를 내리는 Controller가 있습니다. 여기서 Provider 작성은 2가지로 나뉘는데,
- Classic provider: XP 윈도우도 지원
- Manifest-based provider: 비스타 이상에서만 지원
Writing Manifest-based Events
; https://learn.microsoft.com/en-us/windows/win32/etw/writing-manifest-based-events
이 글에서는 비스타 이상에서만 가능한 매니페스트 기반의 제공자(provider) 유형으로 ETW를 사용해 볼텐데, 그 전에 준비물은 다음과 같습니다.
- Visual Studio 2012 이상 (이 글에서는 2013으로 실습)
- Windows SDK 8.0 이상 (해당 SDK 내에 있는 Windows Performance Toolkit 설치)
자, 그럼 시작해 볼까요? ^^
우선, 우리가 실습할 ETW 이벤트 유형은 단순히 메서드의 수행 시간을 남기는 것으로 하겠습니다. 대략 로그에 남길 속성을 정의하면 이 정도입니다.
- [string] Context
- [string] MethodName
- [long] ExecutionTime
- [string] ParameterInfo
물론, 여러분 나름대로 더 정의해서 써도 됩니다.
로그를 남길 사양을 준비했으니, 이를 명시해 주는 "Manifest" 파일을 작성해야 합니다. 일반적으로 확장자가 man으로 지정하는 XML 유형의 파일인데, 이를 손쉽게 GUI 상에서 만들어 줄 수 있는 도구가 "Windows Performance Toolkit"에 ecmangen.exe(Instrumentation manifest generation tool) 파일로 포함되어 있습니다.
C:\Program Files (x86)\Windows Kits\8.1\bin\x64\ecmangen.exe
C:\Program Files (x86)\Windows Kits\8.1\bin\x86\ecmangen.exe
ecmangen 프로그램으로 만들어진 manifest 파일을 한번 보면 좀 더 이해가 빠를 수 있는데요. "
Application Analysis with Event Tracing for Windows (ETW)" 글의 소스코드를 다운로드 받고 "\appanalysis_src\appanalysis_src\Common" 폴더에 보면 "FirstETW.man" 파일이 있으므로 이것을 ecmangen.exe에 로드해서 살펴보면 됩니다.
ecmangen 프로그램에서 manifest 파일을 만드는 좀 더 자세한 설명은 그 프로그램의 "Help" / "Help Topic" 메뉴를 선택하면 "C:\Users\[사용자 계정]\AppData\Local\Temp\ECMangenReference.mht" 파일이 생성과 함께 열리면서 대략적인 실습 시나리오를 위주로 "Quick Start Guide"로 설명하고 있으니 이를 참고하시면 됩니다.
간단하게 우리가 원하는 메서드의 수행 시간을 로그로 남기는 manifest를 정의해 보면, "Events Section" 노드를 마우스 우측 버튼을 눌러 "New" / "Provider"를 선택해 다음의 정보를 입력합니다.
Name: MyETWSampleProvider
Symbol: Sample_Perf (여기 입력한 이름은 나중에 C# 클래스 명으로 사용됨)
GUID: [이 예제에서는 {223f223d-b390-4126-a1c8-3926d1e5b891} 사용]
Decoding file locations:
Resources: sample.exe
Messages: sample.exe
저장하면 다음과 같이 Provider노드가 생성되고,
생성된 "MyETWSampleProvider" 노드를 다시 마우스 우측 버튼을 눌러 "New" / "Template"을 선택해 다음의 정보를 입력하고 저장합니다.
Name: Template_MethodPerfTrace
Field attributes:
Name: Context
InType: win:UnicodeString
OutType: xs:string
Name: MethodName
InType: win:UnicodeString
OutType: xs:string
Name: ExecutionTime
InType: win:UInt64
OutType: xs:unsignedLong
Name: ParameterInfo
InType: win:UnicodeString
OutType: xs:string
템플릿을 만들었으니, 이에 기반한 이벤트를 만드는데 역시 "MyETWSampleProvider" 노드를 마우스 우측 버튼을 눌러 "New" / "Event"를 선택해 다음의 정보를 입력하고 저장합니다.
Symbol: Event_MethodPerfTrace
Event ID: (임의의 값: 여기서는 1을 입력)
Channel: [default 또는 적정한 값 선택, 예제에서는 default]
Level: [default 또는 적정한 값 선택, 예제에서는 Informational]
Task: [default 또는 적정한 값 선택, 예제에서는 default]
Opcode: [default 또는 적정한 값 선택, 예제에서는 default]
Template: [Provider에 포함된 Template 값, 여기서는 이전에 생성해 둔 Template_MethodPerfTrace 선택]
manifest에 정의될 수 있는 값들의 관계를 간단하게 정리해 보면,
- Provider 1개당 n개의 Template, Event 가능
- Event는 1:1로 Template과 매칭
- Event는 Template에 대한 매칭 뿐만 아니라, Channel, Level, Keywords, Opcodes를 할당할 수 있는데 그 정보들 역시 Provider에서 사용자 정의 가능
여기서는 실습을 간단히 하기 위해 Channel, Level, Keywords, Opcodes는 생략하고 최소 정보인 Template과 Event만 정의해 본 것입니다.
여기까지 실습하고 etw_sample.man 파일로 저장하면 다음의 내용이 포함됩니다.
<?xml version="1.0" encoding="UTF-16"?>
<instrumentationManifest xsi:schemaLocation="http://schemas.microsoft.com/win/2004/08/events eventman.xsd" xmlns="http://schemas.microsoft.com/win/2004/08/events" xmlns:win="http://manifests.microsoft.com/win/2004/08/windows/events" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xs="http://www.w3.org/2001/XMLSchema" xmlns:trace="http://schemas.microsoft.com/win/2004/08/events/trace">
<instrumentation>
<events>
<provider name="MyETWSampleProvider" guid="{223F223D-B390-4126-A1C8-3926D1E5B891}" symbol="Sample_Perf" resourceFileName="sample.exe" messageFileName="sample.exe">
<events>
<event symbol="Event_MethodPerfTrace" value="1" version="0" level="win:Informational" template="Template_MethodPerfTrace">
</event>
</events>
<levels>
</levels>
<templates>
<template tid="Template_MethodPerfTrace">
<data name="Context" inType="win:UnicodeString" outType="xs:string">
</data>
<data name="MethodName" inType="win:UnicodeString" outType="xs:string">
</data>
<data name="ExecutionTime" inType="win:UInt64" outType="xs:unsignedLong">
</data>
<data name="ParameterInfo" inType="win:UnicodeString" outType="xs:string">
</data>
</template>
</templates>
</provider>
</events>
</instrumentation>
<localization>
<resources culture="en-US">
<stringTable>
<string id="level.Informational" value="Information">
</string>
</stringTable>
</resources>
</localization>
</instrumentationManifest>
생성된 manifest 파일은 "Message Compiler"를 통해 컴파일할 수 있습니다.
mc etw_sample.man
위와 같이 실행하면, C/C++ 용의 헤더 파일과 함께 리소스 파일들이 생성됩니다.
etw_sample.h
etw_sample.rc
etw_sampleTEMP.BIN
MSG00001.bin
리소스 파일인 etw_sample.rc 파일은 내부적으로 etw_sampleTEMP.BIN, MSG00001.bin 파일을 포함합니다.
LANGUAGE 0x9,0x1
1 11 "MSG00001.bin"
1 WEVT_TEMPLATE "etw_sampleTEMP.BIN"
따라서, Resource Compiler를 이용해서 etw_sample.rc 파일을 컴파일하면 etw_sampleTEMP.BIN, MSG00001.bin 파일을 포함하는 바이너리 유형의 res 리소스 파일(여기서는 etw_sample.res)이 생성됩니다.
rc etw_sample.rc
하지만, 우리는 C/C++이 아닌 C#으로 실습할 것이기 때문에 "Message Compiler"에 "-css" 옵션을 추가해 C# 네임스페이스를 지정해 컴파일해 줍니다.
mc -css MyETWSampleProvider.PerfTrace etw_sample.man
그럼, etw_sample.h 파일 대신 etw_sample.cs 파일이 생성된다는 차이만 있을 뿐 그 외의 파일은 "-css" 옵션이 없을 때와 동일하게 생성됩니다.
etw_sample.cs
etw_sample.rc
etw_sampleTEMP.BIN
MSG00001.bin
생성된 cs 파일에는 친절하게도 ETW 로그를 남길 수 있는 public 접근 권한의 static 메서드를 포함하고 있습니다.
...[주석 영역 생략]...
namespace MyETWSampleProvider.PerfTrace
{
using System;
using System.Collections.Generic;
using System.Text;
using System.Diagnostics;
using System.Diagnostics.Eventing;
using Microsoft.Win32;
using System.Runtime.InteropServices;
using System.Security.Principal;
public static class Sample_Perf
{
//
// Provider MyETWSampleProvider Event Count 1
//
internal static EventProviderVersionTwo m_provider = new EventProviderVersionTwo(new Guid("223f223d-b390-4126-a1c8-3926d1e5b891"));
//
// Task : eventGUIDs
//
//
// Event Descriptors
//
private static EventDescriptor Event_MethodPerfTrace;
static Sample_Perf()
{
unchecked
{
Event_MethodPerfTrace = new EventDescriptor(0x1, 0x0, 0x0, 0x4, 0x0, 0x0, (long)0x0);
}
}
//
// Event method for Event_MethodPerfTrace
//
public static bool EventWriteEvent_MethodPerfTrace(string Context, string MethodName, ulong ExecutionTime, string ParameterInfo)
{
if (!m_provider.IsEnabled())
{
return true;
}
return m_provider.TemplateTemplate_MethodPerfTrace(ref Event_MethodPerfTrace, Context, MethodName, ExecutionTime, ParameterInfo);
}
}
internal class EventProviderVersionTwo : EventProvider
{
internal EventProviderVersionTwo(Guid id)
: base(id)
{}
[StructLayout(LayoutKind.Explicit, Size = 16)]
private struct EventData
{
[FieldOffset(0)]
internal UInt64 DataPointer;
[FieldOffset(8)]
internal uint Size;
[FieldOffset(12)]
internal int Reserved;
}
internal unsafe bool TemplateTemplate_MethodPerfTrace(
ref EventDescriptor eventDescriptor,
string Context,
string MethodName,
ulong ExecutionTime,
string ParameterInfo
)
{
int argumentCount = 4;
bool status = true;
if (IsEnabled(eventDescriptor.Level, eventDescriptor.Keywords))
{
byte* userData = stackalloc byte[sizeof(EventData) * argumentCount];
EventData* userDataPtr = (EventData*)userData;
userDataPtr[0].Size = (uint)(Context.Length + 1)*sizeof(char);
userDataPtr[1].Size = (uint)(MethodName.Length + 1)*sizeof(char);
userDataPtr[2].DataPointer = (UInt64)(&ExecutionTime);
userDataPtr[2].Size = (uint)(sizeof(long) );
userDataPtr[3].Size = (uint)(ParameterInfo.Length + 1)*sizeof(char);
fixed (char* a0 = Context, a1 = MethodName, a2 = ParameterInfo)
{
userDataPtr[0].DataPointer = (ulong)a0;
userDataPtr[1].DataPointer = (ulong)a1;
userDataPtr[3].DataPointer = (ulong)a2;
status = WriteEvent(ref eventDescriptor, argumentCount, (IntPtr)(userData));
}
}
return status;
}
}
}
생성된 코드에 unsafe 키워드가 있기 때문에 이 코드를 사용할 프로젝트의 속성 창에서 unsafe 예약어를 허용(Allow unsafe code)해야 합니다. 또한, 다음과 같이 리소스 파일로 etw_sample.res를 포함하는 것도 잊으면 안 됩니다.
이렇게 준비하면 남은 작업은 단지 로그를 남겨주는 정적 메서드를 호출하는 것으로 ETW 로깅을 수행할 수 있습니다.
using System;
using System.Diagnostics;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static void Main(string[] args)
{
CallTestMethod(2000);
CallTestMethod(300);
}
private static void CallTestMethod(int sleep)
{
Guid guidContext = Guid.NewGuid();
Stopwatch st = new Stopwatch();
st.Start();
try
{
Thread.Sleep(sleep);
}
finally
{
st.Stop();
Console.WriteLine(Thread.CurrentThread.ManagedThreadId + ", " + AppDomain.GetCurrentThreadId() + ", " + st.ElapsedMilliseconds);
MyETWSampleProvider.PerfTrace.Sample_Perf.EventWriteEvent_MethodPerfTrace(guidContext.ToString(), "CallTestMethod", (ulong)st.ElapsedMilliseconds, "");
}
}
}
}
이 상태에서 예제 프로젝트를 실행하면 MyETWSampleProvider.PerfTrace.Sample_Perf.EventWriteEvent_MethodPerfTrace의 코드에서 IsEnabled 메서드의 반환값이 false가 나오면서 아무런 이벤트도 기록하지 않습니다.
public static bool EventWriteEvent_MethodPerfTrace(string Context, string MethodName, ulong ExecutionTime, string ParameterInfo)
{
if (!m_provider.IsEnabled())
{
return true;
}
return m_provider.TemplateTemplate_MethodPerfTrace(ref Event_MethodPerfTrace, Context, MethodName, ExecutionTime, ParameterInfo);
}
즉, ETW 로깅 환경이 갖춰지지 않는 경우 응용 프로그램에 거의 부하가 없음을 의미합니다. ETW가 동작하려면 해당 EXE 프로그램이 동작하는 환경에 2가지 조건을 갖춰야 합니다.
우선, MyETWSampleProvider.PerfTrace.Sample_Perf 클래스를 사용하는 EXE 파일의 위치가 정확하게 설정된 etw_sample.man 파일이 필요합니다.
우선, etw_sample.rc 파일이 컴파일된 etw_sample.res 리소스를 포함하는 모듈의 위치가 정확하게 설정된 etw_sample.man 파일이 필요합니다. (이글에서는 etw_sample.res 리소스를 ConsoleApplication1.exe에 포함시켰기 때문에 그 파일의 경로를 지정합니다.)
<?xml version="1.0" encoding="UTF-16"?>
<instrumentationManifest ...[생략]...>
<instrumentation>
<events>
<provider name="MyETWSampleProvider" guid="{223F223D-B390-4126-A1C8-3926D1E5B891}" symbol="Sample_Perf"
resourceFileName="...[경로]\ConsoleApplication1.exe"
messageFileName="...[경로]\ConsoleApplication1.exe">
<events>
<event symbol="Event_MethodPerfTrace" value="1" version="0" level="win:Informational" template="Template_MethodPerfTrace">
</event>
</events>
...[생략]...
</provider>
</events>
</instrumentation>
...[생략]...
</instrumentationManifest>
ETW를 사용하는 프로그램은 설치 시에 man 파일을 보유하고 있다가 위의 resourceFileName/messageFileName의 값을 (리소스를 포함한) 모듈이 있는 경로로 바꿔준 후 (비스타 이후부터 기본 설치된) wevutil.exe 프로그램을 이용해 (관리자 권한으로) 다음과 같이 ETW Provider를 등록해야 합니다.
[등록]
wevtutil.exe im etw_sample.man
[확인]
xperf -providers | findstr "My"
223f223d-b390-4126-a1c8-3926d1e5b891 : MyETWSampleProvider
[제거]
wevtutil.exe um etw_sample.man
이렇게 등록해도 소스코드의 m_provider.IsEnabled는 여전히 false를 반환합니다. 왜냐하면 ETW는 해당 이벤트를 수집하도록 윈도우 시스템에 알려야 하기 때문입니다. 즉, ETW Controller가 Provider에게 로그를 남기라는 on/off 지시를 해야 하는 것입니다. 이를 위해 "Performance Analyzer"인 xperf.exe 프로그램을 다음과 같은 옵션으로 실행할 수 있습니다.
xperf.exe -start [원하는 이름] -on [NameOfYourRegisteredProvider]
E:\temp>xperf.exe -start MyETW -on MyETWSampleProvider
이렇게 시작하면 기본적으로 xperf.exe가 수행된 드라이브의 루트 드라이브에 user.etl 파일이 생성됩니다. (참고로, user.etl 파일은 잠기지 않습니다.) 기본 경로를 변경하고 싶다면, -f 옵션과 함께 명시할 수 있습니다.
xperf.exe -start MyETW -on MyETWSampleProvider -f E:\temp\etw\user.etl
이렇게까지 해줘야 이제 비로소 "m_provider.IsEnabled" 코드는 true를 반환하게 되고 ETW에 로그를 남기게 됩니다. 그리고, ETW 로깅이 필요없어지면 다음과 같이 윈도우 시스템에 그 사실을 알려줍니다.
E:\ConsoleApplication1\bin\Debug>xperf -stop MyETW
The trace you have just captured "E:\temp\etw\user.etl" may
contain personally identifiable information, including but not necessarily limit
ed to paths to files accessed, paths to registry accessed and process names. Exa
ct information depends on the events that were logged. Please be aware of this w
hen sharing out this trace with other people.
생성된 etl 파일은 wpa.exe, (C:\Program Files (x86)\Windows Kits\8.0\Windows Performance Toolkit 폴더에 있는) xperfview.exe 등을 이용해 볼 수 있습니다.
여기서는 PerfView.exe를 이용할 텐데요. 다음의 경로에서 다운로드 받을 수 있습니다. (단일 exe 프로그램이므로 설치가 필요없습니다.)
PerfView (1.7.0)
; http://www.microsoft.com/en-us/download/details.aspx?id=28567
실행하고 user.etl 파일을 열면 다음과 같이 예제 프로그램에서 남긴 ETW 로그를 확인할 수 있습니다. ^^
(
첨부 파일은 이 글의 실습 프로젝트를 포함합니다.)
기본 설치된 Vista 이상의 윈도우에는 xperf 프로그램이 없기 때문에, 이때는 간단하게 logman.exe를 사용할 수 있습니다. 다음은 logman.exe로 MyETWSampleProvider를 동작시키고 있습니다.
C:\>logman start my -p {223f223d-b390-4126-a1c8-3926d1e5b891} -o mytest.etl -ets
The command completed successfully.
끄는 건 이렇게 하고,
C:\>logman stop my -ets
The command completed successfully.
역시 기본 설치된 Vista 이상의 윈도우에는 wpa.exe나 perfview.exe가 없으므로 내장된 tracerpt.exe를 통해 다음과 같이 분석할 수 있습니다.
C:\temp>tracerpt mytest.etl
Input
----------------
File(s):
mytest.etl
100.00%
Output
----------------
DumpFile: dumpfile.xml
Summary: summary.txt
The command completed successfully.
그럼, 대략적인 정보를 알 수 있는 summary.txt와 모든 이벤트 로그를 포함한 dumpfile.xml이 생성됩니다.
(지금부터는 시행착오에 대한 내용입니다.)
ETW 코드를 호출하는 프로그램을 Windows Server 2003에서 실행하는 경우 다음과 같은 오류가 발생한다는 점을 잊으시면 안됩니다.
D:\temp>ConsoleApplication1.exe
1, 4948, 1988
Unhandled Exception: System.TypeInitializationException: The type initializer for 'MyETWSampleProvider.PerfTrace.Sample_Perf' threw an exception. ---> System.PlatformNotSupportedException: This functionality is only supported in Windows Vista and above.
at System.Diagnostics.Eventing.EventProvider.EtwRegister()
at System.Diagnostics.Eventing.EventProvider..ctor(Guid providerGuid)
at MyETWSampleProvider.PerfTrace.EventProviderVersionTwo..ctor(Guid id)
at MyETWSampleProvider.PerfTrace.Sample_Perf..cctor()
--- End of inner exception stack trace ---
at MyETWSampleProvider.PerfTrace.Sample_Perf.EventWriteEvent_MethodPerfTrace(String Context, String MethodName, UInt64 ExecutionTime, String ParameterInfo)
at ConsoleApplication1.Program.CallTestMethod(Int32 sleep)
at ConsoleApplication1.Program.Main(String[] args)
자동 생성 코드인 Sample_Perf 클래스의 정적 생성자(cctor)에서 오류가 발생하기 때문에 2003에서도 실행되어야 하는 프로그램이라면 아예 Sample_Perf 자체를 접근하지 않도록 하는 예비 코드가 필요합니다.
아울러, 자동 생성 코드의 기반 클래스인 EventProvider 타입의 공식 지원은 .NET Framework 3.5부터라는 점도 잊지 마시고!
.NET Framework
Supported in: 4.5, 4, 3.5
.NET Framework Client Profile
Supported in: 4, 3.5 SP1
PerfView.exe를 통해 etl 내용을 확인할 때 만약 다음과 같이 필드 값이 나오지 않는다면? (DataLength로만 사용자 로그 데이터의 길이를 보여주고 있습니다.)
이것은 "wevtutil.exe" 프로그램을 "im" 옵션으로 *.man 파일 등록 시 resourceFileName, messageFileName의 값에 리소스 파일이 포함된 모듈의 경로를 올바르지 않게 등록한 경우입니다.
참고로, etw_sample.cs 파일을 EXE 프로젝트가 아닌 DLL 유형의 클래스 라이브러리로 분리하는 경우라면 어떤 경로를 resourceFileName, messageFileName의 값에 설정해야 할까요? 이런 경우에도 여전히 중요한 경로는 EXE 파일입니다. 다른 경로를 적으시면 안됩니다. 즉, 여러분이 ETW를 사용한 라이브러리 성격의 프레임워크를 만들었다면 man 파일의 resourceFileName, messageFileName은 나중에 EXE를 만드는 개발자가 별도로 설정해 줘야 합니다.
간혹 ETW 로그를 남기는 ConsoleApplication1.exe 파일이 프로세스가 (비정상 종료된 경우) 종료되었는데도 불구하고 잠기는 경우가 있습니다. 왜냐하면, man 파일 내에 provider의 resource/message 파일명으로 해당 EXE를 지정했기 때문에 ETW 서비스는 이 EXE를 로드하기 때문입니다.
ETW를 관장하는 서비스 프로세스는 윈도우에서 사용되는 svchost.exe이기 때문에 구분이 어려운데 그중에서 "EventLog(Windows Event Log)" 서비스를 호스팅하는 것을 찾으면 됩니다. (Process Explorer에서 찾는다면, 자식 프로세스로 audiodg.exe가 등록된 svchost.exe입니다.) 물론, 작업 관리자에서 강제 종료하지 마시고 그냥 NT 서비스 관리자에서 "Windows Event Log"를 재시작하시면 됩니다.
xperf로 provider의 등록 여부를 "xperf -providers | findstr "My"와 같이 실행하면 된다고 했는데요. Vista에서는 xperf.exe가 기본적으로 없으므로 이때는 내장 프로그램인 wevtutil.exe를 gp 옵션으로 사용하면 됩니다. 그런데, 다음과 같이 "Failed to..." 메시지가 나오면 정상적으로 등록되지 않은 것입니다.
C:\Users\testusr> wevtutil gp MyETWSampleProvider
name: MyETWSampleProvider
guid: 223f223d-b390-4126-a1c8-3926d1e5b891
helpLink:
resourceFileName: c:\temp\bin\ConsoleApplication1.exe
messageFileName: c:\temp\bin\ConsoleApplication1.exe
Failed to get message property. The system cannot find the file specified.
즉, *.man 파일에 지정된 resourceFileName과 messageFileName의 파일명 경로가 잘못된 것입니다. 다시 잘 확인하고, "wevtutil.exe im ...." 옵션으로 등록해 주시면 됩니다.
그 외에 참고할만한 링크를 정리해 봤습니다.
man 파일의 경로를 EXE 프로젝트마다 바꿔주어야 하는 불편함이 있는데, 아래의 글에서는 msbuild에 이 과정을 자동화해주는 방법을 소개하고 있습니다.
Creating Strongly-Typed C# Event Tracing for Windows (ETW) Assemblies with Visual Studio
; http://maximelabelle.wordpress.com/2012/09/05/creating-strongly-typed-c-event-tracing-for-windows-etw-assemblies-with-visual-studio/
ETW가 매력적인 것은, 다른 ETW Provider와 조합해서 로깅 데이터를 분석할 수 있다는 점인데요. 이에 대한 간단한 실습 과정이 아래의 글에 나와 있습니다. 자신의 provider와 함께 .NET Framework의 clr 관련 ETW Provider를 이용해 로그를 남긴 것을 합쳐서 분석하는 과정을 보여주고 있습니다.
Using .NET 4.0 Event Tracing for Windows (ETW) along with application ETW
; http://naveensrinivasan.com/2010/03/17/using-clr-4-0-event-tracing-for-windows-etw-along-with-application-etw/
아울러, NuGet 패키지로 등록된 EventTraceWatcher 클래스를 이용해서,
EventTraceWatcher
; http://nugetmusthaves.com/Package/EventTraceWatcher
실시간으로 ETW 이벤트를 받아 처리할 수 있는 프로그램을 만드는 방법을 소개하고 있습니다.
How to consume ETW events from C# (내부 링크)
; https://learn.microsoft.com/en-us/archive/blogs/danielvl/how-to-consume-etw-events-from-c
이 글의 실습을 해보고 나서, 아래의 글에 실린 "그림 1 ETW 아키텍처"를 보니 이제 좀 이해가 되는군요. ^^
ETW를 사용한 디버깅 및 성능 조정 개선
; https://learn.microsoft.com/ko-kr/archive/msdn-magazine/2007/april/event-tracing-improve-debugging-and-performance-tuning-with-etw
[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]