Microsoft MVP성태의 닷넷 이야기
.NET Framework: 483. 코드로 살펴 보는 ETW의 활성화 시점 [링크 복사], [링크+제목 복사],
조회: 18760
글쓴 사람
정성태 (techsharer at outlook.com)
홈페이지
첨부 파일
 

(시리즈 글이 11개 있습니다.)
.NET Framework: 475. ETW(Event Tracing for Windows)를 C#에서 사용하는 방법
; https://www.sysnet.pe.kr/2/0/1804

.NET Framework: 483. 코드로 살펴 보는 ETW의 활성화 시점
; https://www.sysnet.pe.kr/2/0/1815

.NET Framework: 915. ETW(Event Tracing for Windows)를 이용한 닷넷 프로그램의 내부 이벤트 활용
; https://www.sysnet.pe.kr/2/0/12244

.NET Framework: 923. C# - ETW(Event Tracing for Windows)를 이용한 Finalizer 실행 감시
; https://www.sysnet.pe.kr/2/0/12255

.NET Framework: 932. C# - ETW 관련 Win32 API 사용 예제 코드 (1)
; https://www.sysnet.pe.kr/2/0/12292

.NET Framework: 933. C# - ETW 관련 Win32 API 사용 예제 코드 (2) NT Kernel Logger
; https://www.sysnet.pe.kr/2/0/12296

.NET Framework: 934. C# - ETW 관련 Win32 API 사용 예제 코드 (3) ETW Consumer 구현
; https://www.sysnet.pe.kr/2/0/12299

.NET Framework: 935. C# - ETW 관련 Win32 API 사용 예제 코드 (4) CLR ETW Consumer
; https://www.sysnet.pe.kr/2/0/12300

.NET Framework: 936. C# - ETW 관련 Win32 API 사용 예제 코드 (5) - Private Logger
; https://www.sysnet.pe.kr/2/0/12302

개발 환경 구성: 504. ETW - 닷넷 프레임워크 기반의 응용 프로그램을 위한 명령행 도구 etrace 소개
; https://www.sysnet.pe.kr/2/0/12303

.NET Framework: 994. C# - (.NET Core 2.2부터 가능한) 프로세스 내부에서 CLR ETW 이벤트 수신
; https://www.sysnet.pe.kr/2/0/12474




코드로 살펴 보는 ETW의 활성화 시점

전에 소개해 드린 ETW를 사용하는 과정에,

ETW(Event Tracing for Windows)를 C#에서 사용하는 방법
; https://www.sysnet.pe.kr/2/0/1804

문득, 궁금한 점이 생겼습니다. 자동 생성된 코드를 보면,

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);
}

m_provider.IsEnabled 호출로 활성/비활성 여부에 따라 ETW 로그 작업이 이뤄지게 되는데요. 혹시 IsEnabled 코드가 무겁진 않을까 하는... 걱정인 것이죠. ^^

그래서 확인해 보았습니다. IsEnabled는 자동 생성된 코드가 상속받는 (System.Core 어셈블리의) System.Diagnostics.Eventing.EventProvider 타입에 미리 구현되어 있습니다.

public bool IsEnabled()
{
    if (this.m_enabled == 0)
    {
        return false;
    }
    return true;
}

단순한 필드 조회로 봐서는 다행히 IsEnabled 코드가 빠르게 실행될 것이므로 일단 안심입니다. 그렇다면 m_enabled 값은 언제 지정되는 것일까요? 이 값이 설정되는 코드를 찾아보면 callback 메서드가 나오는데,

[SecurityCritical]
private unsafe void EtwEnableCallBack([In] ref Guid sourceId, [In] int isEnabled, [In] byte setLevel, [In] long anyKeyword, [In] long allKeyword, [In] void* filterData, [In] void* callbackContext)
{
    this.m_enabled = isEnabled;
    this.m_level = setLevel;
    this.m_anyKeywordMask = anyKeyword;
    this.m_allKeywordMask = allKeyword;
}

이 메서드는 다시 EtwRegister 메서드에서 UnsafeNativeMethods.EventRegister Win32 API를 통해 윈도우 시스템에 콜백으로 등록됩니다.

[DllImport("advapi32.dll", CharSet=CharSet.Unicode, ExactSpelling=true)]
internal static extern unsafe uint EventRegister([In] ref Guid providerId, [In] EtwEnableCallback enableCallback, [In] void* callbackContext, [In, Out] ref long registrationHandle);

[SecurityCritical]
private void EtwRegister()
{
    if (s_platformNotSupported)
    {
        throw new PlatformNotSupportedException(SR.GetString("NotSupported_DownLevelVista"));
    }
    this.m_etwCallback = new UnsafeNativeMethods.EtwEnableCallback(this.EtwEnableCallBack);
    uint num = UnsafeNativeMethods.EventRegister(ref this.m_providerId, this.m_etwCallback, null, ref this.m_regHandle);
    if (num != 0)
    {
        throw new Win32Exception((int) num);
    }
}

그리고 EtwRegister 메서드가 수행되는 시점은 System.Diagnostics.Eventing.EventProvider의 생성자입니다.

[SecurityCritical, PermissionSet(SecurityAction.Demand, Unrestricted=true)]
public EventProvider(Guid providerGuid)
{
    this.m_providerId = providerGuid;
    s_returnCodeSlot = Thread.AllocateDataSlot();
    Thread.SetData(s_returnCodeSlot, 0);
    this.EtwRegister();
}

오~~~ 아주 똑똑하게 설계되어 있군요. ^^ 외부에서 logman.exe를 통해 ETW Provider를 활성화시키게 되면 우리가 등록한 EtwEnableCallBack 메서드가 그 순간 불려지게 되고 이후로 호출되는 EventWriteEvent_MethodPerfTrace 메서드는 IsEnabled == true여서 m_provider.TemplateTemplate_MethodPerfTrace까지 이어지게 됩니다. (물론, 다시 logman.exe로 ETW Provider를 중지시키면 IsEnabled는 false를 반환하게 됩니다.)

실행 시에 아무런 부하 없이 로그에 대한 on/off를 할 수 있으니, 생각했던 것보다 괜찮군요. ^^ 어찌 보면, 어설픈 로그 시스템을 만들기 보다는 차라리 ETW를 이용해 로그를 남기는 것을 고려해봐도 좋겠습니다. ^^




[이 글에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]







[최초 등록일: ]
[최종 수정일: 8/19/2020]

Creative Commons License
이 저작물은 크리에이티브 커먼즈 코리아 저작자표시-비영리-변경금지 2.0 대한민국 라이센스에 따라 이용하실 수 있습니다.
by SeongTae Jeong, mailto:techsharer at outlook.com

비밀번호

댓글 작성자
 



2014-11-19 12시07분
[ryujh] 안녕하세요.

ETW 를 그대로 사용할 수 있다면 좋겠지만, ETW 뿐만 아니라 다른 것을 그대로 사용하지 못하는 경우가 문제인것 같습니다.

제목을 볼때는 ETW가 신제품처럼 출시 후 사람들이 많이 사용하길 바라는 듯한 뜻으로 착각했는데
내용을 보니 더 중요하군요. 어떻게 설계하면 되는지 소스 분석으로 보여주니 말입니다.


[guest]
2014-11-19 12시35분
그렇게 보니, 제목에 그런 어감이 좀 있군요. ^^ (제목 변경했습니다.)
정성태

... 61  62  [63]  64  65  66  67  68  69  70  71  72  73  74  75  ...
NoWriterDateCnt.TitleFile(s)
12364정성태10/11/202019494.NET Framework: 948. C# 9.0 - (2) localsinit 플래그 내보내기 무시(Suppress emitting localsinit flag)파일 다운로드1
12363정성태10/11/202021175.NET Framework: 947. C# 9.0 - (1) 대상으로 형식화된 new 식(Target-typed new expressions) [2]파일 다운로드1
12362정성태10/11/202017748VS.NET IDE: 151. Visual Studio 2019에 .NET 5 rc/preview 적용하는 방법
12361정성태10/11/202019782.NET Framework: 946. C# 9.0을 위한 개발 환경 구성
12360정성태10/8/202014965오류 유형: 666. The type or namespace name '...' does not exist in the namespace 'Microsoft.VisualStudio.TestTools' (are you missing an assembly reference?)
12359정성태10/7/202017210오류 유형: 665. Windows - 재부팅 후 iSCSI 연결이 끊기는 문제
12358정성태10/7/202018097오류 유형: 664. Web Deploy 설치 시 "A newer version of Microsoft Web Deploy 3.6 was found on this machine." 오류 [3]
12357정성태10/7/202015749오류 유형: 663. 이벤트 로그 - The storage optimizer couldn't complete retrim on New Volume
12356정성태10/7/202031339오류 유형: 662. ASP.NET Core와 500.19, 500.21 오류 (0x8007000d)
12355정성태10/3/202014882오류 유형: 661. Hyper-V Linux VM의 Internal 유형의 가상 Switch에 대한 IP 연결이 되지 않는 경우
12354정성태10/2/202028907오류 유형: 660. Web Deploy (msdeploy.axd) 실행 시 오류 기록 [1]
12353정성태10/2/202018351개발 환경 구성: 518. 비주얼 스튜디오에서 IIS 웹 서버로 "Web Deploy"를 이용해 배포하는 방법
12352정성태10/2/202019592개발 환경 구성: 517. Hyper-V Internal 네트워크에 NAT을 이용한 인터넷 연결 제공
12351정성태10/2/202018043오류 유형: 659. Nox 실행이 안 되는 경우 - Unable to bind to the underlying transport for ...
12350정성태9/25/202022480Windows: 175. 윈도우 환경에서 클라이언트 소켓의 최대 접속 수 [2]파일 다운로드1
12349정성태9/25/202016643Linux: 32. Ubuntu 20.04 - docker를 위한 tcp 바인딩 추가
12348정성태9/25/202017644오류 유형: 658. 리눅스 docker - Got permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock
12347정성태9/25/202033189Windows: 174. WSL 2의 네트워크 통신 방법 [4]
12346정성태9/25/202016648오류 유형: 657. IIS - http://localhost 방문 시 Service Unavailable 503 오류 발생
12345정성태9/25/202016233오류 유형: 656. iisreset 실행 시 "Restart attempt failed." 오류가 발생하지만 웹 서비스는 정상적인 경우파일 다운로드1
12344정성태9/25/202018135Windows: 173. 서비스 관리자에 "IIS Admin Service"가 등록되어 있지 않다면?
12343정성태9/24/202029190.NET Framework: 945. C# - 닷넷 응용 프로그램에서 메모리 누수가 발생할 수 있는 패턴 [5]
12342정성태9/24/202019166디버깅 기술: 171. windbg - 인스턴스가 살아 있어 메모리 누수가 발생하고 있는지 확인하는 방법
12341정성태9/23/202017224.NET Framework: 944. C# - 인스턴스가 살아 있어 메모리 누수가 발생하고 있는지 확인하는 방법파일 다운로드1
12340정성태9/23/202016882.NET Framework: 943. WPF - WindowsFormsHost를 담은 윈도우 생성 시 메모리 누수
12339정성태9/21/202017054오류 유형: 655. 코어 모드의 윈도우는 GUI 모드의 윈도우로 교체가 안 됩니다.
... 61  62  [63]  64  65  66  67  68  69  70  71  72  73  74  75  ...