当前位置:网站首页>服务器日志分析工具(识别,提取,合并,统计异常信息)
服务器日志分析工具(识别,提取,合并,统计异常信息)
2022-04-23 14:03:00 【洒了脱】
需求: 今天需要查看昨天的日志,并关注其中的异常,以便处理其中的某些问题。
人工阅读花费的时间会很长,一般一天的日志文件有十几个,不可能一个一个去看,并且大量的日志信息都是info信息,不需要关注。所以实现了一个小工具自动读取所有的日志文件,提取其中的异常信息,对于业务异常相同的合并在一起,这样只需要查看生成的异常信息文件即可,大大节约了时间。以下是代码实现:
import com.google.common.collect.Maps;
import org.springframework.util.CollectionUtils;
import java.io.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.zip.GZIPInputStream;
/** * @author visy.wang * @desc 日志读取 * @date 2020/11/25 10:39 */
public class LogReader {
//提取异常信息的关键字
private static final String[] KEY_WORDS = {
"xception", "at "};
//保存业务异常的统计次数
private static Map<String, Integer> errMap = Maps.newHashMap();
/** * 读取异常信息 * @param folder 文件夹路径 * @param ignores 忽略的关键字(含有其中发关键字则跳过) */
private static void readException(String folder, String... ignores) throws Exception{
File dir = new File(folder);
File[] fileArr = dir.listFiles();
if(fileArr==null || fileArr.length==0){
System.out.println("文件夹为空");
return;
}
//解压
for(File in: fileArr){
if(!in.isDirectory() && in.getName().endsWith(".gz")){
unGzip(in);
}
}
//过滤&排序
List<File> files = Arrays.stream(fileArr).filter(f -> {
String name = f.getName();
//只处理debug.*.log文件,可修改
return !f.isDirectory() && name.startsWith("debug") && name.endsWith(".log");
}).sorted(Comparator.comparing(f->{
//文件排序, 无需排序可删除这部分代码,或者修改别的排序规则
//名称示例:debug.2020-11-24.1.log,提取数字1用于排序
String name = f.getName();
int secondIndex = name.indexOf(".",name.indexOf(".")+1);
String index = name.substring(secondIndex+1, name.lastIndexOf("."));
return Integer.parseInt(index);
})).collect(Collectors.toList());
if(CollectionUtils.isEmpty(files)){
System.out.println("未找到日志文件");
return;
}
//创建输出文件
String yesterday = LocalDate.now().minusDays(1).format(DateTimeFormatter.ofPattern("yyyy-MM-dd"));
String outputFileName = "exceptions."+ yesterday +".log";
File outputFile = new File(folder+"\\"+outputFileName);
if(!outputFile.exists()){
if(!outputFile.createNewFile()){
System.out.println(outputFileName+"创建失败!!!");
}
}
FileWriter writer = new FileWriter(outputFile);
for(File file: files){
String fileName = file.getName();
System.out.println("正在读取:"+fileName+" ...");
writer.write("LOG_FILE_NAME-------------------->"+ fileName+"\n");
String tempStr;
BufferedReader reader = new BufferedReader(new FileReader(file));
boolean flag = false;
while ((tempStr = reader.readLine()) != null) {
if(isIncludes(tempStr, KEY_WORDS) && !isIncludes(tempStr, ignores)){
//控制业务异常只打印一遍(合并)
//ServiceException是我项目的自定义的业务异常名,可根据自己的名称修改
if(tempStr.contains("ServiceException:")){
String errMsg = tempStr.substring(tempStr.indexOf(":")+1).trim();
Integer count;
if((count=errMap.get(errMsg))==null){
errMap.put(errMsg, 1);
flag = false;
}else{
errMap.put(errMsg, count+1);
flag = true;
continue;
}
}else{
if(tempStr.contains("at ")){
if(flag){
continue;
}
}else{
flag = false;
}
}
writer.write(tempStr+"\n");
}
}
reader.close();
}
writer.write("\n\n--------------业务异常统计信息-------------------\n");
for(String k : errMap.keySet()){
writer.write(k+": "+ errMap.get(k)+"次\n");
}
writer.close();
System.out.println("异常文件生成完毕!!!");
}
//是否查找到关键字
private static boolean isIncludes(String tempStr, String[] keyWords){
for(String keyWord: keyWords){
if(tempStr.contains(keyWord)){
return true;
}
}
return false;
}
//解压
private static void unGzip(File inFile) throws Exception{
System.out.println("正在解压:"+ inFile.getName() + "...");
//建立gzip压缩文件输入流
FileInputStream fin = new FileInputStream(inFile);
//建立gzip解压工作流
GZIPInputStream gzin = new GZIPInputStream(fin);
//建立解压文件输出流
String path = inFile.getAbsolutePath();
String outPath = path.substring(0, path.lastIndexOf('.'));
FileOutputStream fout = new FileOutputStream(outPath);
int num;
byte[] buf=new byte[1024];
while ((num = gzin.read(buf,0,buf.length)) != -1) {
fout.write(buf,0,num);
}
gzin.close();
fout.close();
fin.close();
//删除源文件
inFile.delete();
}
public static void main(String[] args) throws Exception{
//把要分析的日志文件全部放到桌面logs文件夹下,文件须是解压后的.log文件
//分析完毕后会在logs文件夹下生成exceptions.yyyy-MM-dd.log文件,查看即可
//所有业务异常只会打印一遍异常信息,在文件末尾有各异常发生的次数
readException("C:\\Users\\admin\\Desktop\\logs", "aaa", "bbb");
}
}
版权声明
本文为[洒了脱]所创,转载请带上原文链接,感谢
https://blog.csdn.net/xhom_w/article/details/110234225
边栏推荐
- 记录一个奇怪的bug:缓存组件跳转之后出现组件复制
- PySide2
- Logging模块
- Nodejs安装及环境配置
- 联想产品经理林林:天津当地网络运营商网络故障 ZUI系统后台服务器暂时无法正常工作
- 理解虚基类、虚函数与纯虚函数的概念(转)
- org.apache.parquet.schema.InvalidSchemaException: A group type can not be empty. Parquet does not su
- _模_板_
- nodejs通过require读取本地json文件出现Unexpected token / in JSON at position
- JS brain burning interview question reward
猜你喜欢
freeCodeCamp----arithmetic_ Arranger exercise
Intégration de Clusters CDH Phoenix basée sur la gestion cm
Check in system based on ibeacons
Business case | how to promote the activity of sports and health app users? It is enough to do these points well
基础知识学习记录
Autumn recruitment in 2021, salary ranking No
MYSQL 主从同步避坑版教程
微信小程序进行蓝牙初始化、搜索附近蓝牙设备及连接指定蓝牙(一)
基于ibeacons签到系统
室内外地图切换(室内基于ibeacons三点定位)
随机推荐
Android: answers to the recruitment and interview of intermediate Android Development Agency in early 2019 (medium)
趣谈网络协议
org.apache.parquet.schema.InvalidSchemaException: A group type can not be empty. Parquet does not su
visio安装报错 1:1935 2:{XXXXXXXX...
微信小程序与低功耗蓝牙通信-接受硬件端发送来的数据(四)
烟雾传感器(mq-2)使用详细教程(基于树莓派3b+实现)
scikit-learn構建模型的萬能模板
L2-024 tribe (25 points)
go 语言 数组,字符串,切片
微信小程序通过低功耗蓝牙设备进行定位及测距(二)
1256:献给阿尔吉侬的花束
Scientists say Australian plan to cull up to 10,000 wild horses doesn’t go far enough
VsCode-Go
Oracle alarm log alert Chinese trace and trace files
JS brain burning interview question reward
centOS下mysql主从配置
STM32 learning record 0007 - new project (based on register version)
Quartus prime hardware experimental development (de2-115 board) experiment II function adjustable comprehensive timer design
微信小程序基于udp协议与esp8266进行通信
DeepinV20安装Mariadb