호드는 언리얼 엔진 및 툴의 구조화된 로깅 출력을 많이 사용하며, 이는 일반적으로 일반 텍스트 로그에서 가능한 것보다 더 많은 컨텍스트별 정보를 제공합니다.
호드에서 구조화된 로깅을 사용하는 방법을 이해하려면 자동화된 프로세스에서 진단을 통해 얻고자 하는 일종의 정보를 고려해 보는 것이 도움이 됩니다.
- 인간이 판독 가능한 메시지
- 진단 소스(컴파일러, 링커 등)
- 오류를 트리거한 파일(로컬 경로, 버전 관리 내 경로)
- 줄 번호
- 심각도
- 오류 코드
- 기타 컨텍스트별 정보
이상적으로는 소스에서 오류를 태그하고 가능한 한 많은 컨텍스트별 정보를 추가하고자 합니다. 로그 프래그먼트의 예를 들면 다음과 같습니다.
NVENC_EncoderH264.cpp (0:05.95 at +16:18)
d:\build\AutoSDK\Sync\HostWin64\Win64\Windows Kits\10\include\10.0.18362.0\um\winnt.h(603): error C2220: the following warning is treated as an error
d:\build\AutoSDK\Sync\HostWin64\Win64\Windows Kits\10\include\10.0.18362.0\um\winnt.h(603): warning C4005: 'TEXT': macro redefinition
Engine\Source\Runtime\Core\Public\HAL\Platform.h(1081): note: see previous definition of 'TEXT'
이는 다음과 같은 정보를 제공합니다.
- 컴파일 오류가 발생했습니다.
- 이 오류는
NVENC_EncoderH264.cpp를 컴파일하는 동안winnt.h(603번 줄) 및Platform.h(1081번 줄)에서 정의된 매크로 간의 상충으로 인해 발생했습니다. NVENC_EncoderH264.cpp및Platform.h를 소스 컨트롤의 파일에 매핑하고 리비전 히스토리를 확인할 수 있습니다.- 경고 번호는
C4005이며, 이는 오류C2220으로 간주됩니다. - 파일을 컴파일하는 데 5.95초가 소요되었습니다.
로그 이벤트에 일반 텍스트를 출력하기보다는, 포맷 스트링과 실행인자를 보존하여 나중에 렌더링합니다. 이를 통해 파악하는 타입에 따라 이러한 실행인자를 다르게 렌더링하고, 해당 필드를 기반으로 로그를 인덱싱 및 검색할 수 있습니다.
호드는 구조화된 로그 이벤트를 네이티브로 지원하며, 이는 소스 파일을 P4V 타임랩스 뷰에 연결된 링크로 렌더링하고 오류 코드를 MSDN에 연결된 링크로 렌더링하는 등의 작업에 사용합니다. 또한 소스 컨트롤에서 경로를 히스토리에 다시 매핑할 수 있습니다. 이는 호드의 빌드 상태 시스템을 통해 누가 빌드를 손상시켰는지 알아내는 데 사용합니다.
구조화된 로그 이벤트를 직접 출력하는 경우 호드가 더 이상 오류인지 아닌지 여부를 추측할 필요가 없으므로, 스트링 'error:'가 포함된 모든 로그 줄을 오류로 취급하는 빌드 시스템에 봉착했던 사람이라면 환호할 것입니다.
포맷 지정
언리얼 엔진은 표준 메시지 템플릿 구문을 사용하여 오류를 작성합니다. 예를 들면 다음과 같습니다.
Logger.LogInformation("Hello {Text}", "world");
특히 다음 사항에 유의하세요.
- 포맷 스트링의 모든 파라미터는 숫자 자리표시자를 사용하지 말고 이름을 지어야 합니다(즉, {0}, {1} 등이 아닌 {Text}). 이러한 식별자는 구조화된 로그 이벤트에서 프로퍼티를 명명하는 데 사용되며, Splunk와 Datadog 같은 툴을 통해 인덱싱하고 검색할 수 있습니다.
- 포맷 스트링은 보간되거나 연결된 스트링을 사용하는 것이 아니라 상수여야 합니다. 이를 통해 로거 구현이 메시지 간 파싱된 포맷 스트링을 캐싱하고 재사용할 수 있습니다.
로그 이벤트는 콘솔에 즉시 표시하기 위해 일반 텍스트 로그로 렌더링하거나, JSONL 파일 내에 구조화된 형식으로 보존할 수 있습니다.
C#에서 이벤트 작성하기
자동화 툴(AutomationTool) 및 언리얼 빌드 툴(UnrealBuildTool)은 NET ILogger API를 사용한 로그 이벤트 작성을 지원합니다.
모든 로깅은 레거시 Log.TraceInformation 및 다른 스태틱 메서드를 통해 전달되는 것이 아니라 Microsoft.Extensions.Logging 네임스페이스에서 정의된 ILogger 인스턴스를 통해 이루어져야 합니다.
C++에서 이벤트 작성하기
언리얼 엔진 런타임은 UE_LOGFMT 매크로를 사용한 구조화된 로그 이벤트 작성을 지원합니다.
출력 캡처하기
호드는 UE_LOG_JSON_TO_STDOUT 환경 변수를 설정합니다. 이 환경 변수는 자동화 툴 등의 툴이 호드가 대시보드에서 렌더링하기 위해 수집하고 저장하는 JSON을 stdout으로 직접 출력하도록 지시합니다.
레거시 로그 출력
구조화된 로그를 지원하지 않는 외부 툴(예: 컴파일러 등)의 경우, 일반 텍스트 출력에서 실행되고 해당 출력에서 구조화된 로그 이벤트를 생성하는 정규 표현식 라이브러리가 있습니다. 일부는 UBT에 있으며(Engine/Source/Programs/UnrealBuildTool/Matchers/...) 일부는 UAT에 있습니다(Engine/Source/Programs/AutomationTool/AutomationUtils/Matchers/...). 이는 EpicGames.Core의 LogEventParser 클래스에서 사용됩니다.
일반 텍스트 로그 출력에 새로 일치하는 요소를 구현하기 위해, EpicGames.Core 에서 ILogEventMatcher 인터페이스를 구현하는 클래스를 생성하고 등록되었는지 확인합니다.
로그 파서를 추가하거나 수정하는 경우 다른 핸들러와의 상호작용을 확인하기 위해 UnrealBuildTool.Tests 및 HordeAgent.Tests 프로젝트에서 테스트를 실행하고 작성할 것을 적극 권장합니다.