본문으로 건너뛰기

소개

아키텍처 개요

  1. 프로파일러(네이티브): Exem.DotNet.Profiler.so — CoreCLR Profiling API 사용, IL Rewriting(Probe 삽입).
  2. Startup Hook (Managed bootstrap): Exem.DotNet.Startup.Hook.dll — 프로세스 초기화 시 Agent assembly 로딩 보조. (Exem.DotNet.Agent.dll 로드 및 Exem.DotNet.Agent.dll 에서 사용하는 외부 라이브러리 로드)
  3. Managed Agent: Exem.DotNet.Agent.dllXmBridge, XmNetAgent 등 수집·가공·전송 로직 수행.

프로세스 흐름: 프로세스 시작 → Profiler 로드 및 ICorProfilerCallback 이벤트 구독(메서드 weave 준비) → Startup Hook 실행 → JIT 컴파일 시점에 ICorProfilerCallback 호출로 IL Rewrite (메서드 weave) → 어플리케이션 프로세스 시작 → 모니터링 대상 메서드 최초 호출 시 Exem.DotNet.Agent.dll 로드

지원 환경

  • Linux 환경에서 동작하는 .NET 6.0 이상 ASP.NET Core (Kestrel 서버) 어플리케이션

주요 환경변수 (필수)

  • CORECLR_ENABLE_PROFILING=1 — Profiling 활성화 (없으면 Profiler 미로드).
  • CORECLR_PROFILER={GUID} — Profiler 식별자(CLSID).
  • EXEM_DOTNET_HOME=/.../exem/dotnet — DotNet Agent 루트(설정/로그/ dll 탐색 기준).
  • CORECLR_PROFILER_PATH=/.../Exem.DotNet.Profiler.so — 네이티브 Profiler 경로.
  • DOTNET_STARTUP_HOOKS=/.../Exem.DotNet.Startup.Hook.dll — Startup Hook 경로.
  • EXEM_DOTNET_PROFILE_TARGET_PROCESS=<app>.dll — 프로파일링 대상 프로세스 명시(또는 실행 인자 검사).
  • EXEM_DOTNET_DEBUG2=true — 디버그 로그 활성화(선택).

DLL 탐색/해결(Resolver) 동작

  • Profiler의 주 역할은 CoreCLR 이벤트를 받고 IL을 수정해 메서드 호출을 삽입하는 것
  • Profiler가 직접 managed assembly를 로드하지 않기 때문에, 메서드가 호출될 때 Exem.DotNet.Agent.dll 및 의존 DLL을 별도로 찾고 로드할 장치가 필요
  • Startup HookAgent 내부 resolver는 기본 로드 실패 시 아래 경로를 차례대로 탐색:
    • $EXEM_DOTNET_HOME/binary/{AssemblyName}.dll
    • $EXEM_DOTNET_HOME/binary/libs/{AssemblyName}.dll

동작 원리

  • IL Rewrite: Profiler가 메서드 IL을 수정하여 XmBridge.TraceEnter*, TraceLeave*, TraceThrow* 호출을 삽입. 이를 통해 메서드 시작/종료/예외 시점을 추적.
  • Probe → XmBridge → Handler: Probe가 호출되면 XmBridge가 현재 수집 가능 상태인지 검사한 뒤 적절한 handler로 분기(Txn, SQL, Exception, RemoteCall 등).
  • 전송: XmNetAgent가 주기적 전송 task를 관리하고 Collector로 패킷 전송(패킷 구조: XmTcpReqAgentInfo, XmTcpWasStat 등).