﷽
→ 最新版本
→ 變更日誌
→ 樣品
概述 為什麼還要另一個圖書館 特點一覽 入門 下載 快速入門 安裝(可選) 設定應用程式參數 配置 等級 配置 使用設定檔 使用 el::Configurations 類別 使用串聯配置 預設配置 全域配置 記錄格式說明符 日期/時間格式說明符 自訂格式說明符 記錄標誌 應用參數 配置巨集 讀取配置 記錄 基本的 條件日誌記錄 偶爾記錄 printf 類似日誌記錄 網誌記錄 詳細日誌記錄 基本的 有條件和偶爾 詳細級別 檢查詳細日誌記錄是否已開啟 虛擬模組 註冊新記錄器 取消註冊記錄器 填充現有記錄器 ID 共享日誌儲存庫 額外功能 績效追蹤 條件績效追蹤 利用績效追蹤數據 日誌檔案輪換 碰撞處理 安裝自訂崩潰處理程序 堆疊追蹤 多執行緒 檢查宏 記錄 perror() 使用系統日誌 STL記錄 支援的模板 Qt 日誌記錄 增強日誌記錄 wxWidgets 日誌記錄 擴充庫 記錄自己的課程 記錄第三方類 手動刷新和滾動日誌文件 日誌調度回調 記錄器註冊回調 非同步日誌記錄 輔助類 貢獻 提交補丁 報告錯誤 相容性 建構矩陣 執照 免責聲明
Easylogging++ 是用於 C++ 應用程式的單頭高效能日誌庫。它非常強大、高度可擴展並且可根據使用者的要求進行配置。它提供了編寫自己的接收器的能力(透過稱為LogDispatchCallback
的功能)。該庫目前被 github 和其他開源原始碼控制管理網站上的數百個開源專案使用。
本手冊適用於 Easylogging++ v9.97.1。其他版本請參考github上對應的release。
您可能也對殘留日誌伺服器感興趣。
轉到頂部
如果您正在使用 C++ 開發小型實用程式或大型項目,這個程式庫會很方便。它基於單一標頭,只需要連結到單一來源檔案。 (最初它是僅標頭的,在問題 #445 中更改為使用原始檔。您仍然可以在 v9.89 中使用僅標頭)。
該庫的設計考慮了多種想法(即可移植性、性能、可用性、功能和易於設定)。
為什麼還要另一個圖書館?嗯,答案非常簡單,在編寫時使用它,這樣您就可以解決問題(如果有)或在 github 上提出問題。除此之外,我個人還沒有看到任何基於單頭的日誌庫具有這樣的設計,您可以在旅途中進行配置,將其擴展到您的需求並獲得快速的效能。我見過其他 C++ 的單頭日誌庫,但它們要么使用外部庫,例如 boost 或 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**)
函數的檔案中,就在最後一個包含語句之後。
如果您想在系統範圍內安裝此標頭,您可以透過以下方式執行此操作:
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++ 的某些功能要求您設定應用程式參數,例如,設定詳細程度或 vmodules 的詳細日誌記錄(稍後解釋)。為此,您可以使用輔助巨集或輔助類別;
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 | 尺寸_t | 如果對應等級的日誌檔案大小 >= 指定大小,則日誌檔案將會被截斷。 |
Log_Flush_Threshold | 尺寸_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 " );
上面的程式碼僅設定 Configurations 對象,您仍需要使用此組態重新配置記錄器。
轉到頂部
如果您希望對現有和未來的記錄器進行配置,可以使用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 | 月份 - 短期(一月、二月、三月、四月、五月、六月、七月、八月、九月、十月、十一月、十二月) |
%B | 月 - 長(一月、二月、三月、四月、五月、六月、七月、八月、九月、十月、十一月、十二月) |
%y | 年份 - 兩位數(13、14 等) |
%Y | 年份 - 四位數(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 並且未指定模組,則允許透過該模組進行詳細日誌記錄。假設參數為 -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) | 禁用 vmodules 的使用 |
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 | 啟動從 main 開始到等級 1 的檔案的詳細程度,其餘檔案取決於日誌記錄標誌AllowVerboseIfModuleNotSpecified 請參閱上面的日誌記錄標誌部分。兩個模組可以用逗號分隔。請注意,按照檢查詳細日誌記錄參數的優先順序,vmodules 排在最後,例如,如果應用程式參數中的 -v 位於 vmodules 之前,則 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 | 記錄時啟用 Unicode 支援。需要START_EASYLOGGINGPP |
ELPP_THREAD_SAFE | 啟用線程安全 - 確保 Linux 的 -lpthread 連結。 |
ELPP_FORCE_USE_STD_THREAD | 強制使用 C++ 標準函式庫進行執行緒處理(僅在使用ELPP_THREAD_SAFE 時才有用 |
ELPP_FEATURE_CRASH_LOG | 僅適用於海灣合作委員會。在應用程式崩潰時啟用堆疊追蹤 |
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 作為使用者名稱。 (請勿將此巨集與LD_PRELOAD 一起用於已經使用 Easylogging++ 的函式庫,否則您將最終導致進程堆疊溢位( 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,這將記錄到空設備。在其他平台上,您可能會收到錯誤,並且需要使用ELPP_DEFAULT_LOG_FILE 。 (歡迎其他平台空設備PR) |
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 時,強制使用winsock2.h 而不是winsock.h |
ELPP_CUSTOM_COUT (進階) | 解析為一個值,例如#define ELPP_CUSTOM_COUT qDebug() 或#define ELPP_CUSTOM_COUT std::cerr 。這將使用標準輸出的值(而不是使用std::cout |
ELPP_CUSTOM_COUT_LINE (進階) | 與ELPP_CUSTOM_COUT 一起使用來定義如何使用自訂 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 時間而不是本地時間(本質上使用gmtime 而不是localtime 和系列函數) |
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(自訂 LOG)中您指定記錄器 ID。對於級別,請參閱上面的配置 - 級別部分。根據您的需要,不同的記錄器可能有不同的配置,您也可以編寫自訂巨集來存取自訂記錄器。您還可以使用不同的巨集來進行詳細日誌記錄,這將在下面的部分中進行解釋。這是在初始化 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)"
相同的巨集可用於以V
開頭的詳細日誌記錄,即VLOG_IF
和CVLOG_IF
。有關詳細信息,請參閱下面的詳細日誌記錄部分。根據您的需要,您可以擁有任意複雜的條件。
轉到頂部
偶爾記錄日誌是使用 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}