Linux中的日志插件詳解
一、日志文件的重要性
- 故障排查與問題定位
快速發(fā)現(xiàn)問題:日志能夠?qū)崟r記錄系統(tǒng)運(yùn)行過程中的各種事件和狀態(tài)信息,當(dāng)系統(tǒng)出現(xiàn)故障或異常時,通過查看日志可以快速察覺到問題的發(fā)生,例如,服務(wù)器突然崩潰,日志中可能會記錄下崩潰前的錯誤信息、異常堆棧,幫助運(yùn)維人員第一時間得知系統(tǒng)出現(xiàn)了故障
精準(zhǔn)定位根源:詳細(xì)的日志可以提供問題發(fā)生時的上下文信息,如函數(shù)調(diào)用順序、變量值等,以數(shù)據(jù)庫連接失敗為例,日志可能會記錄下數(shù)據(jù)庫的連接地址、端口、用戶名、密碼驗(yàn)證情況等,幫助開發(fā)人員精準(zhǔn)定位是配置問題、網(wǎng)絡(luò)問題還是數(shù)據(jù)庫本身的問題
- 系統(tǒng)監(jiān)控與性能分析
監(jiān)控系統(tǒng)狀態(tài):通過對日志的實(shí)時分析,可以監(jiān)控系統(tǒng)的運(yùn)行狀態(tài),例如,記錄系統(tǒng)的 CPU 使用率、內(nèi)存占用情況、網(wǎng)絡(luò)流量等信息,一旦這些指標(biāo)超出正常范圍,日志會及時反映出來,以便管理員采取相應(yīng)的措施,如增加服務(wù)器資源、優(yōu)化代碼等
性能瓶頸分析:日志可以記錄每個操作的執(zhí)行時間,通過對這些時間數(shù)據(jù)的分析,可以找出系統(tǒng)的性能瓶頸,比如,在一個 Web 應(yīng)用中,通過日志可以發(fā)現(xiàn)某個 API 接口的響應(yīng)時間過長,進(jìn)而對該接口的代碼進(jìn)行優(yōu)化,提高系統(tǒng)的整體性能
- 安全審計(jì)與合規(guī)性
安全事件追蹤:日志能夠記錄用戶的操作行為,包括登錄、數(shù)據(jù)訪問、權(quán)限變更等,當(dāng)發(fā)生安全事件,如數(shù)據(jù)泄露、非法登錄時,可以通過查看日志追蹤事件的源頭和過程,確定是否存在內(nèi)部人員違規(guī)操作或外部攻擊
滿足合規(guī)要求:許多行業(yè)和地區(qū)都有相關(guān)的法規(guī)和標(biāo)準(zhǔn)要求企業(yè)對系統(tǒng)操作和數(shù)據(jù)進(jìn)行記錄和審計(jì),例如,金融行業(yè)的 PCI-DSS 標(biāo)準(zhǔn)、醫(yī)療行業(yè)的 HIPAA 法規(guī)等,詳細(xì)的日志記錄可以幫助企業(yè)滿足這些合規(guī)要求,避免因違規(guī)而面臨的法律風(fēng)險
二、日志文件的簡單實(shí)現(xiàn)
1、comm.hpp
comm.hpp用來建立信道,Init類用于建立命名管道和退出時自動銷毀命名管道
#pragma once #include <iostream> #include <string> #include <cerrno> #include <cstring> #include <cstdlib> #include <sys/types.h> #include <sys/stat.h> #include <unistd.h> #include <fcntl.h> //命名管道文件路徑 #define FIFO_FILE "./myfifo" //文件權(quán)限 #define MODE 0664 //枚舉命名管道錯誤 enum { FIFO_CREATE_ERR = 1, FIFO_DELETE_ERR, FIFO_OPEN_ERR }; class Init { public: Init() { // 創(chuàng)建命名管道 int n = mkfifo(FIFO_FILE, MODE); if (n == -1) { perror("mkfifo"); exit(FIFO_CREATE_ERR); } } ~Init() { //銷毀命名管道 int m = unlink(FIFO_FILE); if (m == -1) { perror("unlink"); exit(FIFO_DELETE_ERR); } } };
2、log.hpp
log.hpp
中存放的是日志真正的實(shí)現(xiàn),將來我們可以在寫代碼的過程中使用這個文件來打印錯誤信息到日志上
#pragma once #include <iostream> #include <time.h> #include <stdarg.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> #include <stdlib.h> #define SIZE 1024 //錯誤等級 #define Info 0 //無錯誤 #define Debug 1 //需調(diào)試 #define Warning 2 //警告 #define Error 3 //錯誤 #define Fatal 4 //危險 //打印信息放到哪 #define Screen 1 //屏幕 #define Onefile 2 //一個文件 #define Classfile 3 //多個文件 #define LogFile "log.txt" class Log { public: Log() { //初始狀態(tài)下我們把日志打印到屏幕上 printMethod = Screen; path = "./log/"; } //可以通過該函數(shù)對日志打印模式改變 void Enable(int method) { printMethod = method; } //將上面的錯誤等級轉(zhuǎn)化為字符串 std::string levelToString(int level) { switch (level) { case Info: return "Info"; case Debug: return "Debug"; case Warning: return "Warning"; case Error: return "Error"; case Fatal: return "Fatal"; default: return "None"; } } //日志打印函數(shù) void printLog(int level, const std::string &logtxt) { //選擇打印模式 switch (printMethod) { //選擇屏幕就把信息打印出來 case Screen: std::cout << logtxt << std::endl; break; //選擇一個文件就把日志全部打印到一個文件當(dāng)中 case Onefile: printOneFile(LogFile, logtxt); break; //按照等級打印到不同文件中,每個文件對應(yīng)一個等級 case Classfile: printClassFile(level, logtxt); break; default: break; } } //打印到一個文件中 void printOneFile(const std::string &logname, const std::string &logtxt) { //將路徑與文件名稱結(jié)合起來就可以用open打開文件 std::string _logname = path + logname; int fd = open(_logname.c_str(), O_WRONLY | O_CREAT | O_APPEND, 0666); if (fd < 0) return; //將日志信息logtxt寫到文件當(dāng)中 write(fd, logtxt.c_str(), logtxt.size()); close(fd); } //打印到多個文件中 void printClassFile(int level, const std::string &logtxt) { //將文件按照錯誤等級分出來再復(fù)用一個文件的方法寫入每個文件 std::string filename = LogFile; filename += "."; filename += levelToString(level); printOneFile(filename, logtxt); } //析構(gòu)函數(shù),全在棧上就不用寫 ~Log() { } //運(yùn)算符重載,可變參數(shù)列表 void operator()(int level, const char *format, ...) { //獲取本地時間 time_t t = time(nullptr); struct tm *ctime = localtime(&t); //生成日志的時間戳和日志級別 char leftbuffer[SIZE]; snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%d-%d-%d %d:%d:%d]", levelToString(level).c_str(), ctime->tm_year + 1900, ctime->tm_mon + 1, ctime->tm_mday, ctime->tm_hour, ctime->tm_min, ctime->tm_sec); //va_list用于處理可變參數(shù)列表 va_list s; //初始化s,使其指向可變參數(shù)列表第一個參數(shù),format是可變參數(shù)列表前面那個參數(shù) va_start(s, format); char rightbuffer[SIZE]; //將可變參數(shù)按照format字符串的格式寫入rightbuffer中 vsnprintf(rightbuffer, sizeof(rightbuffer), format, s); //結(jié)束對可變參數(shù)列表的訪問 va_end(s); // 格式:默認(rèn)部分+自定義部分 //定義一個數(shù)組logtxt,用于存儲完整的日志信息 char logtxt[SIZE * 2]; //將日志左側(cè)部分也就是時間戳與等級部分(默認(rèn)部分) //和右側(cè)部分也就是自定義部分組合成一條完整的日志信息 snprintf(logtxt, sizeof(logtxt), "%s %s\n", leftbuffer, rightbuffer); //將日志信息輸出 printLog(level, logtxt); } private: int printMethod;//打印模式 std::string path;//路徑 };
三、測試用例
#include "log.hpp" #include <cstdlib> #include <unistd.h> int main() { Log log; int cnt = 10; log.Enable(Onefile); while (cnt--) { log.printOneFile("log","i am super little monster\n"); log.printClassFile(0,"this is 1\n"); log.printClassFile(1,"this is 2\n"); log.printClassFile(2,"this is 3\n"); log.printClassFile(3,"this is 4\n"); log.printClassFile(4,"this is 5\n"); } return 0; }
總結(jié)
以上為個人經(jīng)驗(yàn),希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
linux實(shí)現(xiàn)對上傳文件的定時備份、增量備份的方法
這篇文章主要介紹了linux實(shí)現(xiàn)對上傳文件的定時備份、增量備份的方法,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-04-04linux查看防火墻狀態(tài)與開啟關(guān)閉命令詳解
linux查看防火墻狀態(tài)與開啟關(guān)閉命令常用的有以下兩種方式,大家可以參考一下2018-03-03linux?和?dockerfile?中配置環(huán)境變量的方式總結(jié)
要熟悉?dockerfile?配置?linux?的知識不能少,所以本文將給大家總結(jié)?linux?與?dockerfile?中各種環(huán)境變量,需要的朋友可以參考下2023-07-07CentOS7安裝PHP7 Redis擴(kuò)展的方法步驟
這篇文章主要介紹了CentOS7安裝PHP7 Redis擴(kuò)展的方法步驟,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2019-04-04bug分支和feature分支_動力節(jié)點(diǎn)Java學(xué)院整理
這篇文章主要介紹了bug分支和feature分支,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-08-08