﷽
→ 최신 릴리스
→ 변경 내역
→ 샘플
개요 왜 또 다른 도서관인가? 기능 개요 시작하기 다운로드 빠른 시작 설치(선택사항) 애플리케이션 인수 설정 구성 수준 구성 구성 파일 사용 el::Configurations 클래스 사용 인라인 구성 사용 기본 구성 글로벌 구성 로깅 형식 지정자 날짜/시간 형식 지정자 사용자 정의 형식 지정자 로깅 플래그 응용 인수 구성 매크로 구성 읽기 벌채 반출 기초적인 조건부 로깅 비정기적 로깅 printf 로깅과 유사함 네트워크 로깅 자세한 로깅 기초적인 조건부 및 비정기적 자세한 수준 자세한 로깅이 켜져 있는지 확인 V모듈 새로운 로거 등록 로거 등록 취소 기존 로거 ID 채우기 로깅 저장소 공유 추가 기능 성과 추적 조건부 성과 추적 성과 추적 데이터 활용 로그 파일 회전 충돌 처리 사용자 정의 충돌 처리기 설치 스택트레이스 멀티스레딩 매크로 확인 로깅 오류() Syslog 사용 STL 로깅 지원되는 템플릿 Qt 로깅 부스트 로깅 wxWidget 로깅 라이브러리 확장 나만의 수업 기록 타사 클래스 로깅 수동으로 로그 파일 플러시 및 롤링 로그 디스패치 콜백 로거 등록 콜백 비동기 로깅 도우미 클래스 기부금 패치 제출 버그 신고 호환성 매트릭스 구축 특허 부인 성명
Easylogging++는 C++ 애플리케이션을 위한 단일 헤더 효율적인 로깅 라이브러리입니다. 이는 매우 강력하고 확장성이 뛰어나며 사용자 요구 사항에 맞게 구성할 수 있습니다. LogDispatchCallback
이라는 기능을 통해 자신만의 싱크를 작성하는 기능을 제공합니다. 이 라이브러리는 현재 github 및 기타 오픈 소스 소스 제어 관리 사이트의 수백 개의 오픈 소스 프로젝트에서 사용됩니다.
이 매뉴얼은 Easylogging++ v9.97.1용입니다. 다른 버전은 github의 해당 릴리스를 참조하세요.
잔류물 로깅 서버에도 관심이 있으실 것입니다.
맨 위로 이동
C++로 작은 유틸리티나 대규모 프로젝트를 작업하는 경우 이 라이브러리가 유용할 수 있습니다. 단일 헤더를 기반으로 하며 단일 소스 파일에만 연결하면 됩니다. (원래는 헤더 전용이었는데 이슈 #445에서 소스 파일을 사용하도록 변경되었습니다. v9.89에서도 여전히 헤더 전용을 사용할 수 있습니다.)
이 라이브러리는 다양한 생각(예: 이식성, 성능, 유용성, 기능 및 설치 용이성)을 염두에 두고 설계되었습니다.
왜 또 다른 도서관이 있습니까? 글쎄요, 대답은 매우 간단합니다. 작성한 대로 사용하여 문제(있는 경우)를 수정하거나 github에 제기할 수 있습니다. 그 외에도 이동 중에도 구성하고 필요에 따라 확장하며 빠른 성능을 얻을 수 있는 단일 헤더 기반 로깅 라이브러리를 개인적으로 본 적이 없습니다. C++용 다른 단일 헤더 로깅 라이브러리를 본 적이 있지만 이들은 스레딩, 정규식 또는 날짜 등과 같은 특정 기능을 지원하기 위해 부스트 또는 Qt와 같은 외부 라이브러리를 사용합니다. 이 라이브러리에는 외부 라이브러리의 사용을 방지하기 위한 모든 것이 내장되어 있습니다. 나는 그 라이브러리를 좋아하지 않는다는 것이 아니라 사실 그것을 좋아합니다. 그러나 모든 프로젝트가 이 라이브러리를 사용하는 것은 아니기 때문에 나는 그 라이브러리에 의존할 위험을 감수할 수 없었습니다.
맨 위로 이동
Easylogging++는 소프트웨어를 작성하는 동안 일반 개발자와 고급 개발자 모두에게 필요한 많은 기능을 포함하는 풍부한 기능을 갖추고 있습니다.
맨 위로 이동
최신 릴리스에서 최신 버전을 다운로드하세요.
다른 릴리스에 대해서는 릴리스 페이지를 방문하십시오. 애플리케이션이 C++11을 지원하지 않는 경우 v8.91 사용을 고려해 보세요. 이것은 C++98 및 C++03의 안정적인 버전이지만 일부 기능이 부족합니다.
맨 위로 이동
Easylogging++를 시작하려면 다음 세 가지 쉬운 단계를 따르세요.
easylogging++.h
및 easylogging++.cc
)# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, char * argv[]) {
LOG (INFO) << " My first info log using default logger " ;
return 0 ;
}
이제 다음을 사용하여 컴파일하십시오.
g++ main.cc easylogging++.cc -o prog -std=c++11
간단해요! INITIALIZE_EASYLOGGINGPP
는 한 번만 사용해야 합니다. 그렇지 않으면 컴파일 오류가 발생하게 됩니다. 이것은 여러 extern
변수의 정의입니다. 즉, 애플리케이션당 한 번만 정의할 수 있습니다. 이 초기화 문을 배치하는 가장 좋은 위치는 int main(int, char**)
함수가 정의된 파일의 마지막 include 문 바로 뒤에 있습니다.
이 헤더를 시스템 전체에 설치하려면 다음을 통해 수행할 수 있습니다.
mkdir build
cd build
cmake -Dtest=ON ../
make
make test
make install
다음 옵션은 Easylogging++ cmake에서 지원되며 -D<option>=ON
사용하여 이러한 옵션을 켤 수 있습니다.
lib_utc_datetime
- ELPP_UTC_DATETIME
정의합니다.build_static_lib
- Easylogging++용 정적 라이브러리 빌드 그렇긴 하지만, 컴파일하려면 여전히 easylogging++.cc
파일이 필요합니다. 헤더에 대해서만 v9.89 이하를 확인하세요.
또는 vcpkg 종속성 관리자를 사용하여 easyloggingpp를 다운로드하고 설치할 수 있습니다.
git clone https://github.com/Microsoft/vcpkg.git
cd vcpkg
./bootstrap-vcpkg.sh
./vcpkg integrate install
./vcpkg install easyloggingpp
vcpkg의 easyloggingpp 포트는 Microsoft 팀 구성원과 커뮤니티 기여자가 최신 상태로 유지합니다. 버전이 오래된 경우 vcpkg 저장소에서 이슈 또는 풀 요청을 생성하세요.
맨 위로 이동
항상 Easylogging++에 애플리케이션 인수를 전달하는 것이 좋습니다. Easylogging++의 일부 기능을 사용하려면 응용 프로그램 인수를 설정해야 합니다(예: 자세한 수준 또는 vmodule을 설정하기 위한 자세한 로깅)(나중에 설명됨). 이를 위해 도우미 매크로나 도우미 클래스를 사용할 수 있습니다.
int main ( int argc, char * argv[]) {
START_EASYLOGGINGPP (argc, argv);
...
}
맨 위로 이동
로깅 라이브러리 구성을 시작하려면 심각도 수준을 이해해야 합니다. Easylogging++는 활성화된 것과 활성화되지 않은 것을 완전히 제어하기 위해 의도적으로 계층적 로깅을 사용하지 않습니다. 즉, LoggingFlag::HierarchicalLogging
사용하여 계층적 로깅을 사용하는 옵션이 여전히 있습니다. Easylogging++에는 다음과 같은 수준이 있습니다(계층적 수준에 따라 정렬됨).
수준 | 설명 |
---|---|
글로벌 | 모든 수준을 나타내는 일반 수준입니다. 모든 수준에 대한 전역 구성을 설정할 때 유용합니다. |
추적하다 | 특정 이벤트를 역추적하는 데 유용할 수 있는 정보 - 대부분 디버그 로그보다 유용합니다. |
디버그 | 개발자가 애플리케이션을 디버깅하는 데 가장 유용한 정보 이벤트입니다. NDEBUG가 정의되지 않은 경우(VC++가 아닌 경우) 또는 _DEBUG가 정의된 경우(VC++의 경우)에만 적용 가능합니다. |
치명적인 | 애플리케이션이 중단될 수 있는 매우 심각한 오류 이벤트입니다. |
오류 | 오류 정보가 있지만 계속 실행하려면 응용 프로그램을 계속 진행합니다. |
경고 | 응용 프로그램의 오류를 나타내는 정보이지만 응용 프로그램은 계속 실행됩니다. |
정보 | 주로 응용 프로그램의 현재 진행 상황을 나타내는 데 유용합니다. |
말 수가 많은 | 매우 유용할 수 있고 자세한 로깅 수준에 따라 달라질 수 있는 정보입니다. 자세한 로깅은 계층적 로깅에 적용할 수 없습니다. |
알려지지 않은 | 계층적 로깅에만 적용 가능하며 로깅을 완전히 끄는 데 사용됩니다. |
맨 위로 이동
Easylogging++는 구성이 쉽습니다. 그렇게 하는 방법에는 세 가지가 있습니다.
구성은 Configurations
클래스에 의해 런타임에 로드되는 파일로 수행될 수 있습니다. 이 파일의 형식은 다음과 같습니다.
* LEVEL:
CONFIGURATION NAME = "VALUE" ## Comment
ANOTHER CONFIG NAME = "VALUE"
레벨 이름은 별표(*)로 시작하고 콜론(:)으로 끝납니다. 파일에 지정되지 않은 구성이 자동으로 Global
의 구성을 사용하도록 구성 파일을 Global
수준으로 시작하는 것이 좋습니다. 예를 들어, Global
에서 Filename
설정하고 모든 레벨에서 동일한 파일 이름을 사용하려는 경우 각 레벨에 대해 명시적으로 설정하지 않으면 라이브러리가 자동으로 Global
의 구성 값을 사용합니다. 다음 표에는 구성 파일에서 지원하는 구성이 포함되어 있습니다.
구성 이름 | 유형 | 설명 |
---|---|---|
Enabled | 부울 | 해당 레벨의 로거 활성화 여부를 결정합니다. el::Level::Global 사용하여 모든 로그를 비활성화할 수 있습니다. |
To_File | 부울 | 해당 로그를 로그 파일에 기록할지 여부 |
To_Standard_Output | 부울 | 표준 출력(예: 터미널 또는 명령 프롬프트)에 로그를 쓸지 여부 |
Format | 숯* | 해당 레벨 및 로거에 대한 로깅 형식/패턴을 결정합니다. |
Filename | 숯* | 해당 레벨 및 로거에 대해 로그를 기록할 로그 파일(전체 경로)을 결정합니다. |
Subsecond_Precision | 단위 | 초 미만의 정밀도(이전에는 '밀리초 너비'라고 함)를 지정합니다. 너비는 범위(1-6) 내에 있을 수 있습니다. |
Performance_Tracking | 부울 | 성능 추적이 활성화되는지 여부를 결정합니다. 이는 로거나 레벨에 의존하지 않습니다. 성능 추적은 별도로 지정하지 않는 한 항상 '성능' 로거를 사용합니다. |
Max_Log_File_Size | size_t | 해당 레벨의 로그 파일 크기가 지정된 크기보다 크면 로그 파일이 잘립니다. |
Log_Flush_Threshold | size_t | 보류 중인 로그 데이터를 플러시할 때까지 보유할 로그 항목 수를 지정합니다. |
주석에 큰따옴표를 사용하지 마십시오. 예상치 못한 동작이 발생할 수 있습니다.
샘플 구성 파일
* GLOBAL:
FORMAT = "%datetime %msg"
FILENAME = "/tmp/logs/my.log"
ENABLED = true
TO_FILE = true
TO_STANDARD_OUTPUT = true
SUBSECOND_PRECISION = 6
PERFORMANCE_TRACKING = true
MAX_LOG_FILE_SIZE = 2097152 ## 2MB - Comment starts with two hashes (##)
LOG_FLUSH_THRESHOLD = 100 ## Flush after every 100 logs
* DEBUG:
FORMAT = "%datetime{%d/%M} %func %msg"
위 샘플의 구성 파일 내용은 간단합니다. 모든 레벨을 무시하기 위해 GLOBAL
레벨부터 시작합니다. 명시적으로 정의된 후속 레벨은 GLOBAL
의 구성을 대체합니다. 예를 들어 DEBUG
를 제외한 모든 레벨은 날짜/시간, 로그 메시지 형식으로 동일합니다. DEBUG
레벨의 경우 날짜(일 및 월 포함), 소스 함수 및 로그 메시지만 있습니다. DEBUG
의 나머지 구성은 GLOBAL
에서 사용됩니다. 또한 위 DEBUG
형식의 {%d/%M}
에 주목하세요. 날짜 형식을 지정하지 않으면 기본 형식이 사용됩니다. 날짜/시간의 기본값은 %d/%M/%Y %h:%m:%s,%g
입니다. 이러한 형식 지정자에 대한 자세한 내용은 아래 날짜/시간 형식 지정자 섹션을 참조하세요.
# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, const char ** argv) {
// Load configuration from file
el::Configurations conf ( " /path/to/my-conf.conf " );
// Reconfigure single logger
el::Loggers::reconfigureLogger ( " default " , conf);
// Actually reconfigure all loggers instead
el::Loggers::reconfigureAllLoggers (conf);
// Now all the loggers will use configuration from file
}
구성 파일은 필요할 때마다 사용할 수 있는
el::Configurations
객체(생성자 사용)로 변환될 수 있습니다(위의 예와 같이).
맨 위로 이동
구성을 설정하거나 구성을 재설정할 수 있습니다.
# include " easylogging++.h "
INITIALIZE_EASYLOGGINGPP
int main ( int argc, const char ** argv) {
el::Configurations defaultConf;
defaultConf. setToDefault ();
// Values are always std::string
defaultConf. set (el::Level::Info,
el::ConfigurationType::Format, " %datetime %level %msg " );
// default logger uses default configurations
el::Loggers::reconfigureLogger ( " default " , defaultConf);
LOG (INFO) << " Log using default file " ;
// To set GLOBAL configurations you may use
defaultConf. setGlobally (
el::ConfigurationType::Format, " %date %msg " );
el::Loggers::reconfigureLogger ( " default " , defaultConf);
return 0 ;
}
구성은 한 번만 설정하면 됩니다. 기본 구성에 만족한다면 이를 사용해도 됩니다.
맨 위로 이동
인라인 구성은 std::string
에서 구성을 설정할 수 있지만 새 줄 문자 등을 모두 추가해야 함을 의미합니다. 이는 항상 지저분하기 때문에 권장되지 않습니다.
el::Configurations c;
c.setToDefault();
c.parseFromText( " *GLOBAL: n FORMAT = %level %msg " );
위의 코드는 구성 개체만 설정하므로 이 구성을 사용하여 로거를 다시 구성해야 합니다.
맨 위로 이동
기존 및 향후 로거에 대한 구성을 원할 경우 el::Loggers::setDefaultConfigurations(el::Configurations& configurations, bool configureExistingLoggers = false)
사용할 수 있습니다. 이는 상당히 큰 규모로 작업하거나 이미 Easylogging++를 사용하고 있는 타사 라이브러리를 사용할 때 유용합니다. 새로 생성된 로거는 기본 구성을 사용합니다. 기존 로거도 구성하려면 두 번째 인수를 true
로 설정할 수 있습니다(기본값은 false
).
맨 위로 이동
Level::Global
전역 구성과 아무 관련이 없으며, 전체/또는 일부 로거에 대한 구성을 등록하고 구성 파일을 사용하여 새 로거를 등록할 수도 있는 개념입니다. 구성 파일의 구문은 다음과 같습니다.
-- LOGGER ID ## Case sensitive
## Everything else is same as configuration file
-- ANOTHER LOGGER ID
## Configuration for this logger
로거 ID는 두 개의 대시로 시작됩니다. 전역 구성 파일을 작성한 후에는 단일 기능을 사용하여 모든 로거를 구성하고 새 로거를 등록할 수 있습니다.
int main ( void ) {
// Registers new and configures it or
// configures existing logger - everything in global.conf
el::Loggers::configureFromGlobal ( " global.conf " );
// .. Your prog
return 0 ;
}
구성을 정의하지 않고 전역 구성을 사용하여 새 로거를 등록하는 것은 불가능하다는 점에 유의하십시오. 최소한 단일 구성을 정의해야 합니다. 로거를 등록하는 다른 방법은 아래 로깅 섹션에서 설명합니다.
맨 위로 이동
다음 지정자를 사용하여 로깅 형식을 사용자 정의할 수 있습니다.
지정자 | 대체자 |
---|---|
%logger | 로거 ID |
%thread | 스레드 ID - 사용 가능한 경우 std::thread를 사용하고, 그렇지 않으면 Windows에서 GetCurrentThreadId()를 사용합니다. |
%thread_name | Helpers::setThreadName 사용하여 현재 스레드의 이름을 설정합니다( setThreadName 실행하는 위치). 스레드 이름 샘플을 참조하세요. |
%level | 심각도 수준(정보, 디버그, 오류, 경고, 치명적, 자세한 정보, 추적) |
%levshort | 심각도 수준(짧은 버전, 즉 정보의 경우 I, 각각 D, E, W, F, V, T) |
%vlevel | 상세 수준(상세 로깅에 적용 가능) |
%datetime | 날짜 및/또는 시간 - 패턴을 사용자 정의할 수 있습니다. 아래 날짜/시간 형식 지정자를 참조하세요. |
%user | 현재 애플리케이션을 실행 중인 사용자 |
%host | 컴퓨터 이름 응용 프로그램이 실행 중입니다. |
%file * | 소스 파일의 파일 이름(전체 경로) - 이 기능은 컴파일러의 __FILE__ 매크로 사용 가능 여부에 따라 달라집니다. |
%fbase * | 소스 파일의 파일 이름(기본 이름만) |
%line * | 소스 줄 번호 - 이 기능은 컴파일의 __LINE__ 매크로 사용 여부에 따라 달라집니다. |
%func * | 로깅 기능 |
%loc * | 소스 파일 이름 및 로깅 줄 번호(콜론으로 구분) |
%msg | 실제 로그 메시지 |
% | 이스케이프 문자(예: %%level은 %level을 씁니다) |
__LINE__
, __FILE__
등)의 컴파일러 가용성에 따라 달라집니다. 맨 위로 이동
다음 지정자를 사용하여 날짜/시간 형식을 사용자 정의할 수 있습니다.
지정자 | 대체자 |
---|---|
%d | 날짜(제로 패딩) |
%a | 요일 - 짧게(월,화,수,목,금,토,일) |
%A | 요일 - 장기(월요일, 화요일, 수요일, 목요일, 금요일, 토요일, 일요일) |
%M | 월(제로 패딩) |
%b | 월 - 단기(1월, 2월, 3월, 4월, 5월, 6월, 7월, 8월, 9월, 10월, 11월, 12월) |
%B | 월 - 장기(1월, 2월, 3월, 4월, 5월, 6월, 7월, 8월, 9월, 10월, 11월, 12월) |
%y | 연도 - 두 자리 숫자(13, 14 등) |
%Y | 연도 - 4자리(2013, 2014 등) |
%h | 시(12시간 형식) |
%H | 시간(24시간 형식) |
%m | 분(제로 패딩) |
%s | 두 번째(제로 패딩됨) |
%g | 하위 초 부분(정밀도는 ConfigurationType::SubsecondPrecision에 의해 구성됨) |
%F | 오전/오후 지정 |
% | 이스케이프 문자 |
날짜/시간은 최대 30
자로 제한됩니다.
맨 위로 이동
자신만의 형식 지정자를 지정할 수도 있습니다. 이를 위해 el::Helpers::installCustomFormatSpecifier
사용할 수 있습니다. 완벽한 예는 TCP 서버 애플리케이션의 %ip_addr
입니다.
const char * getIp ( const el::LogMessage*) {
return " 192.168.1.1 " ;
}
int main ( void ) {
el::Helpers::installCustomFormatSpecifier ( el::CustomFormatSpecifier ( " %ip_addr " , getIp));
el::Loggers::reconfigureAllLoggers (el::ConfigurationType::Format, " %datetime %level %ip_addr : %msg " );
LOG (INFO) << " This is request from client " ;
return 0 ;
}
맨 위로 이동
로깅의 일부를 구성하면 로깅 플래그를 설정할 수 있습니다. 지원되는 플래그는 다음과 같습니다.
깃발 | 설명 |
---|---|
NewLineForContainer (1) | 각 컨테이너 로그 항목에 대해 새 줄이 있는지 확인합니다. |
AllowVerboseIfModuleNotSpecified (2) | -vmodule이 사용되고 모듈을 지정하지 않은 경우 해당 모듈을 통해 자세한 로깅이 허용되는지 확인합니다. param이 -vmodule=main*=3이고 Something.cpp라는 파일에서 자세한 로그가 기록되고 있다고 가정하고 이 플래그가 활성화되면 로그가 기록되고 그렇지 않으면 허용되지 않습니다. 참고: 이렇게 하면 -vmodule의 목적이 무효화됩니다. |
LogDetailedCrashReason (4) | 기본적으로 충돌을 처리할 때 자세한 충돌 이유도 기록됩니다(기본적으로 비활성화됨)(문제 #90) |
DisableApplicationAbortOnFatalLog (8) | FATAL 수준을 사용하여 기록할 때 애플리케이션 중단을 비활성화할 수 있습니다. 충돌 신호가 처리된 후에 애플리케이션이 중단되어야 하므로 이는 기본 충돌 처리기에는 적용되지 않습니다. (기본적으로 추가되지 않음) (문제 #119) |
ImmediateFlush (16) | 모든 로그 항목마다 로그 플러시(성능에 민감) - 기본적으로 비활성화됨 |
StrictLogFileSizeCheck (32) | 모든 로그에서 로그 파일 크기를 확인합니다. |
ColoredTerminalOutput (64) | 터미널에서 지원하는 경우 터미널 출력이 다채롭게 표시됩니다. |
MultiLoggerSupport (128) | 단일 메시지를 기록하기 위해 여러 로거를 사용하는 지원을 활성화합니다. (예: CLOG(INFO, "default", "network") << This will be logged using default and network loggers; ) |
DisablePerformanceTrackingCheckpointComparison (256) | 체크포인트 비교를 비활성화합니다. |
DisableVModules (512) | vmodule 사용을 비활성화합니다. |
DisableVModulesExtensions (1024) | vmodules 확장을 비활성화합니다. 즉, vmodule -vmodule=main*=4 가 있으면 main으로 시작하는 모든 항목을 다루고, 이를 정의하지 않은 것처럼 main으로 시작하고 다음 확장자 중 하나로 끝나는 모든 파일을 다룹니다. .h .c .cpp .cc .cxx .-inl-.h .hxx .hpp. 다음 vmodule은 올바르지 않습니다. -vmodule=main.=4 이 매크로는 정의되지 않았습니다. 이는 main..c를 확인하므로 이중 점에 유의하세요. 이것이 유효하도록 하려면 위의 로깅 플래그를 살펴보십시오. AllowVerboseIfModuleNotSpecified '?' 및 '' 와일드카드가 지원됩니다. |
HierarchicalLogging (2048) | 계층적 로깅을 활성화합니다. 이는 자세한 로깅에는 적용되지 않습니다. |
CreateLoggerAutomatically (4096) | 사용할 수 없는 경우 자동으로 로거를 생성합니다. |
AutoSpacing (8192) | 자동으로 공백을 추가합니다. 예: LOG(INFO) << "DODGE" << "THIS!"; "DODGE THIS!"가 출력됩니다. |
FixedTimeFormat (16384) | 성능 추적에만 적용 가능합니다. 이렇게 하면 포맷 시간이 단축됩니다. 예를 들어 1001 ms 1.01 sec 형식화하는 대신 있는 그대로 기록됩니다. |
IgnoreSigInt (32768) | 응용 프로그램이 충돌할 때 중단 신호를 무시합니다. |
static el::Loggers::addFlag
및 el::Loggers::removeFlag
사용하여 이러한 플래그를 설정/설정 해제할 수 있습니다. el::Loggers::hasFlag
사용하여 특정 플래그를 사용할 수 있는지 확인할 수 있습니다. 이러한 모든 함수는 강력한 유형의 열거형 el::LoggingFlag
사용합니다.
--logging-flags
명령줄 인수를 사용하여 이러한 플래그를 설정할 수 있습니다. 매크로ELPP_LOGGING_FLAGS_FROM_ARG
정의하여 이 기능을 활성화해야 합니다(인수를 구성하려면START_EASYLOGGINGPP(argc, argv)
사용해야 합니다).
ELPP_DEFAULT_LOGGING_FLAGS
사용하여 기본(초기) 플래그를 설정하고 초기 플래그에 대한 숫자 값을 설정할 수도 있습니다.
맨 위로 이동
다음 표에서는 특정 동작을 정의하는 데 사용할 수 있는 모든 명령줄 인수를 설명합니다. main(int, char**)
함수에서 START_EASYLOGGINGPP(argc, argv)
사용하여 애플리케이션 인수를 초기화해야 합니다.
논쟁 | 설명 |
---|---|
-v | 최대 자세한 정보를 활성화합니다. |
--v=2 | 자세한 정보 표시 수준을 2까지 활성화합니다(유효 범위: 0-9). |
--verbose | 최대 자세한 정보를 활성화합니다. |
-vmodule=MODULE_NAME | 기본에서 레벨 1까지 시작하는 파일에 대해 자세한 정보를 활성화하고 나머지 파일은 로깅 플래그에 따라 달라집니다. AllowVerboseIfModuleNotSpecified 위의 로깅 플래그 섹션을 참조하십시오. 두 모듈은 쉼표로 구분할 수 있습니다. vmodules는 자세한 로깅에 대한 인수 확인 우선 순위의 마지막 순서입니다. 예를 들어 vmodules 이전에 애플리케이션 인수에 -v가 있는 경우 vmodules는 무시됩니다. |
--logging-flags=3 | 로깅 플래그를 설정합니다. 예를 ie, 3 에서는 로깅 플래그를 NewLineForContainer 및 AllowVerboseIfModuleNotSpecified 로 설정합니다. 자세한 내용과 값은 위의 로깅 플래그 섹션을 참조하세요. 이 기능을 비활성화하려면 매크로 섹션을 참조하세요. |
--default-log-file=FILE | 기존 및 향후 로거에 대한 기본 로그 파일을 설정합니다. 사전 처리 중에 기본 빈 로그 파일이 생성되지 않도록 ELPP_NO_DEFAULT_LOG_FILE 정의를 고려할 수 있습니다. 이 기능을 비활성화하려면 매크로 섹션을 참조하세요. |
맨 위로 이동
일부 로깅 옵션은 매크로로 설정할 수 있습니다. 이는 신중한 결정입니다. 예를 들어 ELPP_THREAD_SAFE
정의한 경우 모든 스레드 안전 기능은 활성화되고 그렇지 않으면 비활성화됩니다(스레드 안전에 대한 오버헤드도 함께 수행되는지 확인). 쉽게 기억하고 충돌 가능성을 방지하기 위해 모든 매크로는 ELPP_
로 시작합니다.
참고: 모든 매크로는 다음 방법 중 하나로 정의할 수 있습니다.
컴파일러의 -D
옵션을 사용하여 매크로를 정의합니다. 예를 들어 g++
의 경우 g++ source.cpp ... -DELPP_SYSLOG -DELPP_THREAD_SAFE ...
( 권장 방법 )을 수행합니다.
"easylogging++.h"
내에 매크로를 정의하세요. (다른 파일에 매크로를 정의하면 작동하지 않습니다.)
매크로 이름 | 설명 |
---|---|
ELPP_DEBUG_ASSERT_FAILURE | 첫 번째 어설션이 실패하면 애플리케이션을 중단합니다. 이 어설션은 잘못된 입력(예: 잘못된 구성 파일 등)으로 인해 발생합니다. |
ELPP_UNICODE | 로깅 시 유니코드 지원을 활성화합니다. START_EASYLOGGINGPP 필요 |
ELPP_THREAD_SAFE | 스레드 안전성을 활성화합니다. Linux의 경우 -lpthread 연결을 확인하세요. |
ELPP_FORCE_USE_STD_THREAD | 스레딩을 위해 C++ 표준 라이브러리를 강제로 사용합니다( ELPP_THREAD_SAFE 사용할 때만 유용함) |
ELPP_FEATURE_CRASH_LOG | GCC에만 적용됩니다. 애플리케이션 충돌 시 스택 추적을 활성화합니다. |
ELPP_DISABLE_DEFAULT_CRASH_HANDLING | 기본 충돌 처리를 비활성화합니다. el::Helpers::setCrashHandler를 사용하여 자체 핸들러를 사용할 수 있습니다. |
ELPP_DISABLE_LOGS | 모든 로그 비활성화 - (전처리) |
ELPP_DISABLE_DEBUG_LOGS | 디버그 로그 비활성화 - (전처리) |
ELPP_DISABLE_INFO_LOGS | 정보 로그를 비활성화합니다 - (전처리) |
ELPP_DISABLE_WARNING_LOGS | 경고 로그 비활성화 - (전처리) |
ELPP_DISABLE_ERROR_LOGS | 오류 로그 비활성화 - (전처리) |
ELPP_DISABLE_FATAL_LOGS | 치명적인 로그를 비활성화합니다 - (전처리) |
ELPP_DISABLE_VERBOSE_LOGS | 자세한 로그를 비활성화합니다 - (전처리) |
ELPP_DISABLE_TRACE_LOGS | 추적 로그 비활성화 - (전처리) |
ELPP_FORCE_ENV_VAR_FROM_BASH | 환경 변수를 찾을 수 없는 경우 대체 bash 명령을 강제로 사용하여 값을 찾습니다(예: 사용자 이름에 대해 whoami ). (이미 Easylogging++를 사용하고 있는 라이브러리에 대해 LD_PRELOAD 와 함께 이 매크로를 사용하지 마십시오. 그렇지 않으면 프로세스( popen )에 대한 스택 오버플로가 발생하게 됩니다(자세한 내용은 문제 #87 참조). |
ELPP_DEFAULT_LOG_FILE | 초기 파일을 생성할 전체 파일 이름입니다. 이 매크로의 값을 따옴표와 함께 포함해야 합니다(예: -DELPP_DEFAULT_LOG_FILE='"logs/el.gtest.log"' 작은 따옴표 안의 큰 따옴표, 큰 따옴표는 const char* 의 값이고 작은 따옴표는 다음 값을 지정합니다). 매크로 |
ELPP_NO_LOG_TO_FILE | 처음에는 파일에 대한 로깅을 비활성화합니다. |
ELPP_NO_DEFAULT_LOG_FILE | 기본 로그 파일로 라이브러리를 초기화하지 않으려면 이 매크로를 정의하십시오. Unix 및 Windows의 경우 null 장치에 기록됩니다. 다른 플랫폼에서는 오류가 발생할 수 있으므로 ELPP_DEFAULT_LOG_FILE 사용해야 합니다. (다른 플랫폼의 null 장치에 대한 홍보는 환영합니다) |
ELPP_FRESH_LOG_FILE | 로그 파일이 생성될 때마다 로그 파일을 추가하지 않습니다. (일부 사용자에게는 예상치 못한 결과가 발생할 수 있으므로 주의해서 사용하십시오.) |
ELPP_DEBUG_ERRORS | 구성이나 다른 이유로 인해 Easylogging++에서 발생한 내부 오류를 찾으려면 이 매크로를 정의하여 활성화할 수 있습니다. 표준 출력(예: 터미널 또는 명령 프롬프트)에 오류가 표시됩니다. |
ELPP_DISABLE_CUSTOM_FORMAT_SPECIFIERS | 사용자 정의 형식 지정자를 강제로 비활성화합니다. |
ELPP_DISABLE_LOGGING_FLAGS_FROM_ARG | 명령줄 인수를 사용하여 로깅 플래그를 설정하는 기능을 강제로 비활성화합니다. |
ELPP_DISABLE_LOG_FILE_FROM_ARG | 명령줄 인수에서 기본 로그 파일을 설정하는 기능을 강제로 비활성화합니다. |
ELPP_WINSOCK2 | Windows 시스템에서는 WIN32_LEAN_AND_MEAN 이 정의된 경우 winsock.h 대신 winsock2.h 강제로 사용합니다. |
ELPP_CUSTOM_COUT (고급) | 예를 들어 #define ELPP_CUSTOM_COUT qDebug() 또는 #define ELPP_CUSTOM_COUT std::cerr 값으로 확인됩니다. 이것은 std::cout 사용하는 대신 표준 출력 값을 사용합니다. |
ELPP_CUSTOM_COUT_LINE (고급) | 사용자 정의 cout으로 로그 줄을 작성하는 방법을 정의하기 위해 ELPP_CUSTOM_COUT 과 함께 사용됩니다. 예: #define ELPP_CUSTOM_COUT_LINE(msg) QString::fromStdString(msg).trimmed() |
ELPP_NO_CHECK_MACROS | CHECK 매크로를 정의하지 마세요. |
ELPP_NO_DEBUG_MACROS | DEBUG 매크로를 정의하지 마세요. |
ELPP_UTC_DATETIME | 현지 시간 대신 UTC 시간을 사용합니다(기본적으로 localtime 및 가족 기능 대신 gmtime 사용합니다). |
ELPP_NO_GLOBAL_LOCK | 배송 시 전체 저장소를 잠그지 마십시오. 이는 주의해서 사용해야 합니다. 문제 #580 참조 |
맨 위로 이동
특정 로거의 구성을 읽으려면 Logger 클래스의 typedConfigurations()
함수를 사용하면 됩니다.
el::Logger* l = el::Loggers::getLogger( " default " );
bool enabled = l-> typedConfigurations ()->enabled(el::Level::Info);
// Or to read log format/pattern
std::string format =
l-> typedConfigurations ()->logFormat(el::Level::Info).format();
맨 위로 이동
easylogging++ 로그인은 매크로 모음을 사용하여 수행됩니다. 이는 사용자가 더 쉽게 작업을 수행하는 방법에 대해 불필요하게 자세한 내용을 알 수 없도록 하기 위한 것입니다.
로그를 작성하는 데 사용할 수 있는 두 가지 기본 매크로가 제공됩니다.
LOG(LEVEL)
CLOG(LEVEL, logger ID)
LOG
'기본' 로거를 사용하는 반면 CLOG(Custom LOG)에서는 로거 ID를 지정합니다. LEVEL에 대해서는 위의 구성 - 레벨 섹션을 참조하세요. 필요에 따라 다양한 로거의 구성이 다를 수 있으며, 사용자 정의 로거에 액세스하기 위해 사용자 정의 매크로를 작성할 수도 있습니다. 아래 섹션에서 설명하는 자세한 로깅을 위한 다양한 매크로도 있습니다. 다음은 easylogging++를 초기화한 후 이러한 매크로를 사용하는 매우 간단한 예입니다.
LOG (INFO) << "This is info log";
CLOG (ERROR, " performance " ) << "This is info log using performance logger";
동일한 매크로, 즉 LOG
(및 관련 매크로)를 사용하는 또 다른 방법이 있습니다. 이는 이미 등록된 로거 ID로 ELPP_DEFAULT_LOGGER
, ELPP_DEFAULT_PERFORMANCE_LOGGER
매크로를 정의하고, 이제 LOG
매크로를 사용하면 default
로거 대신 지정된 로거를 자동으로 사용하게 된다는 것입니다. 헤더 파일이 아닌 소스 파일에 정의해야 한다는 점에 유의하세요. 이는 헤더를 포함할 때 실수로 잘못된 로거를 사용하지 않도록 하기 위한 것입니다.
간단한 예는 여기에 있습니다.
# ifndef ELPP_DEFAULT_LOGGER
# define ELPP_DEFAULT_LOGGER " update_manager "
# endif
# ifndef ELPP_DEFAULT_PERFORMANCE_LOGGER
# define ELPP_DEFAULT_PERFORMANCE_LOGGER ELPP_DEFAULT_LOGGER
# endif
# include " easylogging++.h "
UpdateManager::UpdateManager {
_TRACE; // Logs using LOG(TRACE) provided logger is already registered - i.e, update_manager
LOG (INFO) << " This will log using update_manager logger as well " ;
}
# include " easylogging++.h "
UpdateManager::UpdateManager {
_TRACE; // Logs using LOG(TRACE) using default logger because no `ELPP_DEFAULT_LOGGER` is defined unless you have it in makefile
}
Logger
클래스를 직접 사용하여 로그를 작성할 수도 있습니다. 이 기능은 가변 템플릿을 지원하는 컴파일러에서 사용할 수 있습니다.samples/STL/logger-log-functions.cpp
를 보면 더 많은 내용을 살펴볼 수 있습니다.
맨 위로 이동
Easylogging++는 로깅의 특정 측면을 제공합니다. 이러한 측면 중 하나는 조건부 로깅입니다. 즉, 특정 조건이 충족되는 경우에만 로그가 기록됩니다. 이는 어떤 상황에서는 매우 유용합니다. 도우미 매크로는 _IF로 끝납니다.
LOG_IF(condition, LEVEL)
CLOG_IF(condition, LEVEL, logger ID)
LOG_IF (condition, INFO) << "Logged if condition is true";
LOG_IF ( false , WARNING) << "Never logged";
CLOG_IF ( true , INFO, " performance " ) << "Always logged (performance logger)"
VLOG_IF
및 CVLOG_IF
와 같이 처음에 V
사용한 자세한 로깅에도 동일한 매크로를 사용할 수 있습니다. 자세한 내용은 아래의 자세한 로깅 섹션을 참조하세요. 필요에 따라 원하는 만큼 복잡한 조건을 가질 수도 있습니다.
맨 위로 이동
비정기적 로깅은 Easylogging++를 사용한 로깅의 또 다른 유용한 측면입니다. 즉, 특정 횟수 또는 특정 시간의 일부에 도달하면 로그가 기록됩니다(예: 10번째 히트, 100번째 히트 또는 2번째 히트마다). 도우미 매크로는 _EVERY_N
으로 끝납니다.
LOG_EVERY_N(n, LEVEL)
CLOG_EVERY_N(n, LEVEL, logger ID)
적중 횟수를 기반으로 로깅하는 다른 방법도 있습니다. 유용한 매크로는 다음과 같습니다.
LOG_AFTER_N(n, LEVEL)
; 적중 횟수 n
에 도달한 경우에만 기록합니다.LOG_N_TIMES(n, LEVEL)
; n번 기록 for ( int i = 1 ; i <= 10 ; ++i) {
LOG_EVERY_N ( 2 , INFO) << " Logged every second iter " ;
}
// 5 logs written; 2, 4, 6, 7, 10
for ( int i = 1 ; i <= 10 ; ++i) {
LOG_AFTER_N ( 2 , INFO) << " Log after 2 hits; " << i;
}
// 8 logs written; 3, 4, 5, 6, 7, 8, 9, 10
for ( int i = 1 ; i <= 100 ; ++i) {
LOG_N_TIMES ( 3 , INFO) << " Log only 3 times; " << i;
}
// 3 logs writter; 1, 2, 3
DEBUG
전용 모드에서는 동일한 버전의 매크로를 사용할 수 있습니다. 이러한 매크로는D
(디버그용)로 시작하고 뒤에 동일한 이름이 옵니다. 예를 들어 디버그 모드에서만 기록하는DLOG
(즉,_DEBUG
정의되거나NDEBUG
정의되지 않은 경우)
맨 위로 이동
printf
로깅과 유사함 C++11의 가변 템플릿을 지원하는 컴파일러의 경우 "printf"와 같은 로그 기능을 사용할 수 있습니다. 이는 Logger
클래스를 사용하여 수행됩니다. 이 기능은 스레드 및 유형에 안전합니다( LOG(INFO)
등과 같은 매크로를 사용하지 않기 때문에).
이 작업은 두 단계로 수행됩니다.
el::Loggers::getLogger(<logger_id>);
printf
와의 유일한 차이점은 이러한 함수를 사용하여 로깅하려면 각 인수에 대해 %v
필요하다는 것입니다(이는 유형 안전성을 위한 것입니다). 사용자 정의 형식 지정자 대신. %%v
로 이 문제를 피할 수 있습니다.
다음은 다양한 함수 서명입니다.
info(const char*, const T&, const Args&...)
warn(const char*, const T&, const Args&...)
error(const char*, const T&, const Args&...)
debug(const char*, const T&, const Args&...)
fatal(const char*, const T&, const Args&...)
trace(const char*, const T&, const Args&...)
verbose(int vlevel, const char*, const T&, const Args&...)
// Use default logger
el::Logger* defaultLogger = el::Loggers::getLogger( " default " );
// STL logging (`ELPP_STL_LOGGING` should be defined)
std::vector< int > i;
i.push_back( 1 );
defaultLogger-> warn ( " My first ultimate log message %v %v %v " , 123 , 222 , i);
// Escaping
defaultLogger-> info ( " My first ultimate log message %% %%v %v %v " , 123 , 222 );
%file
,%func
%line
및%loc
형식 지정자는 로깅과 같은printf
에서 작동하지 않습니다.
맨 위로 이동
네트워크로 메시지를 보낼 수 있습니다. 하지만 로그 디스패처 API를 사용하여 자신만의 방식을 구현해야 합니다. 우리는 이 목적을 위해 완전히 작동하는 샘플을 작성했습니다. 네트워크로 보내기 샘플을 참조하세요.
맨 위로 이동
자세한 로깅은 모든 소프트웨어에서 평소보다 더 많은 정보를 기록하는 데 유용합니다. 문제 해결에 매우 유용합니다. 다음은 자세한 로깅 관련 매크로입니다.
VLOG(verbose-level)
CVLOG(verbose-level, logger ID)
맨 위로 이동
자세한 로깅에는 조건부 및 비정기적 로깅 측면도 있습니다.
VLOG_IF(condition, verbose-level)
CVLOG_IF(condition, verbose-level, loggerID)
VLOG_EVERY_N(n, verbose-level)
CVLOG_EVERY_N(n, verbose-level, loggerID)
VLOG_AFTER_N(n, verbose-level)
CVLOG_AFTER_N(n, verbose-level, loggerID)
VLOG_N_TIMES(n, verbose-level)
CVLOG_N_TIMES(n, verbose-level, loggerID)
맨 위로 이동
자세한 수준은 1-9 범위를 가질 수 있는 자세한 수준입니다. 응용 프로그램 인수를 설정하지 않으면 상세 수준이 활성화되지 않습니다. 자세한 로깅에 대해 자세히 알아보려면 애플리케이션 인수 섹션을 읽어보세요.
상세 수준을 즉시 변경하려면 Loggers::setVerboseLevel(base::type::VerboseLevel)
(일명 Loggers::setVerboseLevel(int)
함수)을 사용하세요. (현재 자세한 수준은 Loggers::verboseLevel()
로 확인할 수 있습니다.
맨 위로 이동
매크로 VLOG_IS_ON(verbose-level)
사용하여 지정된 상세 수준의 소스 파일에 대해 특정 로깅이 켜져 있는지 확인할 수 있습니다. 이는 if 조건에 포함할 수 있는 부울을 반환합니다.
if (VLOG_IS_ON( 2 )) {
// Verbosity level 2 is on for this file
}
맨 위로 이동
VModule은 모듈/소스 파일별로 자세한 정도를 지정할 수 있는 자세한 로깅(위 표에 언급됨)을 위한 기능입니다. 다음은 설명이 포함된 몇 가지 예입니다. 아래의 모든 vmodule은 -vmodule=
로 시작하고 LoggingFlag::DisableVModulesExtensions
플래그가 설정되지 않았습니다. LoggingFlag::DisableVModules
플래그를 추가하면 Vmodule을 완전히 비활성화할 수 있습니다.
LoggingFlag::AllowVerboseIfModuleNotSpecified
플래그의 예;
main=3,parser*=4
:
main{.h, .c, .cpp, .cc, .cxx, -inl.h, .hxx, .hpp}
parser{.h, .c, .cpp, .cc, .cxx, -inl.h, .hxx, .hpp}