当前位置:网站首页>服务器日志分析工具(识别,提取,合并,统计异常信息)
服务器日志分析工具(识别,提取,合并,统计异常信息)
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
边栏推荐
- JDBC入门
- freeCodeCamp----time_ Calculator exercise
- 多重继承虚基类习题
- 微信小程序获取登录用户信息、openid和access_token
- Quartus Prime硬件实验开发(DE2-115板)实验二功能可调综合计时器设计
- 快捷键(多行)
- freeCodeCamp----arithmetic_ Arranger exercise
- Haruki Murakami -- Excerpt from "what do I talk about when I talk about running"
- org.apache.parquet.schema.InvalidSchemaException: A group type can not be empty. Parquet does not su
- MySQL 修改主数据库
猜你喜欢
Intégration de Clusters CDH Phoenix basée sur la gestion cm
微信小程序setInterval定时函数使用详细教程
Qt Designer怎样加入资源文件
Nifi 快速安装及文件同步操作
What is the difference between blue-green publishing, rolling publishing and gray publishing?
微信小程序通过低功耗蓝牙设备进行定位及测距(二)
JS brain burning interview question reward
Chrome插件 之 Selenium IDE、XPath 安装
基于ibeacons签到系统
Promtail + Loki + Grafana 日志监控系统搭建
随机推荐
groutine
JS brain burning interview question reward
多线程 @Async 线程池
DDT+Excel进行接口测试
Basic knowledge learning record
FBS(fman build system)打包
Elmo (bilstm-crf + Elmo) (conll-2003 named entity recognition NER)
Universal template for scikit learn model construction
编程旅行之函数
mysql通过binlog文件恢复数据
Force deduction brush question 101 Symmetric binary tree
SQL: How to parse Microsoft Transact-SQL Statements in C# and to match the column aliases of a view
Pytorch 经典卷积神经网络 LeNet
MySQL 修改主数据库
switch使用(微信小程序)
分库分表 & ShardingSphere
JS force deduction brush question 103 Zigzag sequence traversal of binary tree
基於CM管理的CDH集群集成Phoenix
What is the difference between blue-green publishing, rolling publishing and gray publishing?
DeepinV20安装Mariadb