syslog日志系統——日志采集


摘自:https://blog.csdn.net/hunkcai/article/details/83859172

日志采集的流程

 

 

客戶端埋點

客戶端埋點就是在客戶系統植入日志發送的代碼,可以是前端頁面、app界面、后端服務等,把需要的日志信息發送到指定的日志采集接口。
日志的發送應該采用異步方式,這樣不會對客戶系統代碼的執行造成影響。

日志采集


日志采集接口把接收過來的日志數據寫入到日志文件,日志文件以天為單位進行存儲。

日志采集接口代碼


接口采用@IgnoreToken標記不需要進行令牌校驗。
采用@CrossOrigin標記,讓接口能夠跨域訪問,支持AJAX跨域請求。

@ApiOperation(value = "提交日志")
@ApiImplicitParams({
@ApiImplicitParam(name = "logData", value = "日志數據", dataType = "LogData", paramType = "body")
})
@RequestMapping(path = "/log/add", method = RequestMethod.POST, produces = "application/json;charset=UTF-8")
@IgnoreToken
@CrossOrigin
public ResponseData addLog(@RequestBody LogData logData) {

String logID = logService.logToFile(logData);

return ResponseData.success(logID);
}

 

日志文件格式的設計


日志以文本格式保存,每條日志按行寫入。
日志行的格式如下:

時間戳|日志ID|日志數據JSON

 

 

 

日志按行保存的好處是,可以利用BufferedReader的readLine方法進行日志的按行讀取。
日志按行保存,要對日志數據JSON部分進行處理,把換行符替換掉。

日志按行保存的主要代碼

public String logToFile(LogData logData){
LogGroupData groupData = getLogGroup(logData.getKey());
logData.setGroupID(groupData.getGroupID());

String date = ConvertUtil.formatDate(new Date(), "yyyyMMdd");
String path = PathUtil.combine(logFolder, "LOG" + date + ".log");

String uuid = UUID.randomUUID().toString();
String json = JSON.toJSONString(logData);

StringBuilder sb = new StringBuilder();
sb.append("[" + ConvertUtil.formatDate(new Date()) + "]|");
sb.append(uuid + "|");
for (int i = 0; i < json.length(); i++) {
char c = json.charAt(i);
if (c == '\r' || c == '\n')//換行符替換為空格
sb.append(" ");
else
sb.append(c);
}

FileUtil.appendLine(path, sb.toString());

return uuid;
}

 

日志寫入文件的主要代碼


利用RandomAccessFile類寫入,用文件瑣控制並發。如果是海量日志的場合,可以部署多幾個采集點。

public static void appendLine(String path, String line) {

RandomAccessFile fout = null;
FileChannel channel = null;
try {
File file = new File(path);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
}
byte[] bytes = line.getBytes("utf-8");
fout = new RandomAccessFile(file, "rw");
long filelength = fout.length();//獲取文件的長度
fout.seek(filelength);//將文件的讀寫指針定位到文件的末尾
channel = fout.getChannel();//打開文件通道
FileLock fileLock = null;
while (true) {
try {
fileLock = channel.tryLock();//不斷的請求鎖,如果請求不到,等一秒再請求
break;
} catch (Exception e) {
logger.error("[FileUtil.appendLine]請求瑣失敗。");
Thread.sleep(1000);
}
}
fout.write(bytes);
fout.writeChar('\n');
fileLock.release();
channel.close();
fout.close();

} catch (Exception e1) {
logger.error(e1.getMessage(), e1);
} finally {
IOUtil.close(channel);
IOUtil.close(fout);
}
}

日志匯總


通過定時任務,把各個采集點的日志文本導入數據庫/大數據存儲。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM