最近工作中有项工作做的劳神不说,更少眼睛累…于是写了下面的工具帮忙干活.
工作内容,查看日志,将执行存在异常的组件找出来,说明白点就是看组件开始时间,结束时间,比对看哪个组件执行费时…,从而改进程序
之前是日志在服务器上,使用vi看
日志文件xxx.log
2018-09-07 16:58:01.343 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 不定长通讯组件
2018-09-07 16:58:01.344 DEBUG TEST_C-00000174 [AbstractComm ] 通讯组件 @ 使用接入适配器
2018-09-07 16:58:01.345 INFO TEST_C-00000174 [AbstractComm ] 通讯组件 @ 接收数据[4408],报文数据不记录
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ 不定长通讯组件
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 拆包组件
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [MessageUnpack ] 报文拆包组件 @ 使用报文'test/message/req.rcd',拆包变量名'recv'
...
...
2018-09-07 16:58:01.347 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ 拆包组件
2018-09-07 16:58:01.347 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ groovy脚本组件
...
...
2018-09-07 16:58:01.348 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ groovy脚本组件
2018-09-07 16:58:01.348 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 拼包组件
2018-09-07 16:58:01.349 DEBUG TEST_C-00000174 [MessagePack ] 报文拼包组件 @ 使用报文'test/message/res_dc.rcd',拼包变量名'send'
...
...
2018-09-07 16:58:01.354 DEBUG TEST_C-00000174 [MessagePack ] 报文拼包组件 @ 拼包后报文为[4408]:
2018-09-07 16:58:01.356 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ 拼包组件
2018-09-07 16:58:01.356 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 服务网关SDK发送组件
组件执行是严格按照流程,一个执行完才能进入下一个…
但是日志是异步输出的,导致日志输出的顺序与组件执行的顺序没有必然关系,就是会出现后面执行的组件日志中出现在文件的靠前的位置,添加了工作的难度…
预处理–>src.txt
使用shell命令将满足条件的日志行输出到指定文件中,src.txt,作为解析的源文件
grep 组件 ../TEST_C.log | grep TEST_C-00000174 > src.txt
这句意思是,从TEST_C.log日志中搜索 包含TEST_C-00000174的行中含有组件两个字的行内容输出到src.txt中.>代表输出
2018-09-07 16:58:01.343 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 不定长通讯组件
2018-09-07 16:58:01.344 DEBUG TEST_C-00000174 [AbstractComm ] 通讯组件 @ 使用接入适配器
2018-09-07 16:58:01.345 INFO TEST_C-00000174 [AbstractComm ] 通讯组件 @ 接收数据[24],报文数据不记录
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ 不定长通讯组件
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ 拆包组件
2018-09-07 16:58:01.346 DEBUG TEST_C-00000174 [MessageUnpack ] 报文拆包组件 @ 使用报文'test/message/req.rcd',拆包变量名'recv'
2018-09-07 16:58:01.347 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ 拆包组件
2018-09-07 16:58:01.347 DEBUG TEST_C-00000174 [AbstractComponent ] 组件开始 @ groovy脚本组件
2018-09-07 16:58:01.348 DEBUG TEST_C-00000174 [AbstractComponent ] 组件结束 @ groovy脚本组件
...
使用工具将其拉到本地,或者之后的操作也在服务器上就行了,将dos脚本,编写成shell脚本即可,上面的shell脚本作为参考
处理目标–>dest.xlsx
时间 | 分秒的毫秒数 | 时差 | 日志级别 | 流水 | 组件名称 | 内容 |
---|---|---|---|---|---|---|
2018-09-07 16:58:01.343 | 1343 | 1343 | DEBUG | TEST_C-00000174 | 组件开始 | 不定长通讯组件 |
2018-09-07 16:58:01.343 | 1343 | 0 | DEBUG | TEST_C-00000174 | 组件开始 | 不定长通讯组件 |
2018-09-07 16:58:01.344 | 1344 | 1 | DEBUG | TEST_C-00000174 | 通讯组件 | 使用接入适配器 |
2018-09-07 16:58:01.345 | 1345 | 1 | INFO | TEST_C-00000174 | 通讯组件 | 接收数据[4408],报文数据不记录 |
2018-09-07 16:58:01.346 | 1346 | 1 | DEBUG | TEST_C-00000174 | 组件开始 | 拆包组件 |
2018-09-07 16:58:01.346 | 1346 | 0 | DEBUG | TEST_C-00000174 | 组件结束 | 不定长通讯组件 |
… |
使用到的jar包
dom4j-1.6.1.jar
poi-3.9.jar
poi-ooxml-3.9.jar
poi-ooxml-schemas-3.9.jar
xmlbeans-2.3.0.jar
代码
注:从当前目录的src.txt读取文件内容,处理后放入到当前目录的dest.xlsx文件中
源文件与目标文件路径可以在配置文件txt2excel.properties中修改.
这里只是用POI操作.xlsx的,
package com.yangxuan.excel;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collections;
import java.util.List;
import java.util.Properties;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xssf.usermodel.XSSFRow;
import org.apache.poi.xssf.usermodel.XSSFSheet;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
public class TXT2Excel {
private static String srcPath;
private static String destPath;
static{
Properties prop = new Properties();
try {
//读取配置文件.properties中的信息
prop.load(new FileInputStream(new File("txt2excel.properties")));
srcPath = prop.getProperty("srcPath");
destPath = prop.getProperty("destPath");
} catch (Exception e) {
e.printStackTrace();
}
}
public static void write(String destPath,List<String> fileContent) throws IOException, ParseException{
//ArrayList<String> row = new ArrayList<String>();
XSSFWorkbook xssfwb = new XSSFWorkbook();
XSSFSheet xssfSheet = xssfwb.createSheet("sheet111");
XSSFRow xssfRow = null;
//读取文件内容
long old = 0L;
//处理文本数据
String content = "";
for (int i = 0; i < fileContent.size(); i++) {
content = fileContent.get(i);
String cell1 = content.substring(0, 23).trim();
long cell2 = dateFormat(cell1);
xssfRow = xssfSheet.createRow(i);
xssfRow.createCell(0).setCellValue(cell1);
xssfRow.createCell(1).setCellValue(cell2);
xssfRow.createCell(2).setCellValue(cell2-old);
old=cell2;
xssfRow.createCell(3).setCellValue(content.substring(23, 30).trim());
xssfRow.createCell(4).setCellValue(content.substring(30, 46).trim());
String[] split2 = content.substring(70).split("@");
if(split2.length==2){
xssfRow.createCell(5).setCellValue(split2[0].trim());
xssfRow.createCell(6).setCellValue(split2[1].trim());
}else{
xssfRow.createCell(5).setCellValue(content.substring(70).trim());
}
}
FileOutputStream fos = new FileOutputStream(new File(destPath));
xssfwb.write(fos);
}
/**
* 将字符串数据转化为毫秒数
* @return 分+秒+毫秒位的毫秒数
* @throws ParseException
*/
public static long dateFormat(String dateString) throws ParseException{
String sub = dateString.substring(0,16);
Calendar c = Calendar.getInstance();
//2018-09-07 16
c.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm").parse(sub));
long timeInMillis1 = c.getTimeInMillis();
//2018-09-07 16:58:01.343
c.setTime(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS").parse(dateString));
long timeInMillis2 = c.getTimeInMillis();
return timeInMillis2-timeInMillis1;
}
/**
* 获取文件内容
* @param srcPath
* @return List<String>
* @throws IOException
*/
public static final List<String> getFileContent(String srcPath) throws IOException
{
List<String> fileContent = new ArrayList<String>();
try {
File f = new File(srcPath);
if (f.exists()) {
FileReader fr = new FileReader(srcPath);
BufferedReader br = new BufferedReader(fr); // 建立BufferedReader对象,并实例化为br
String line = br.readLine(); // 从文件读取一行字符串
// 判断读取到的字符串是否不为空
while (line != null) {
if(line.length()>0){
fileContent.add(line);
}
line = br.readLine(); // 从文件中继续读取一行数据
}
//排序
Collections.sort(fileContent);
br.close(); // 关闭BufferedReader对象
fr.close(); // 关闭文件
}
} catch (IOException e) {
throw e;
}
return fileContent;
}
public static void main(String[] args) throws IOException, InvalidFormatException, ParseException {
List<String> fileContent = getFileContent(srcPath);
TXT2Excel.write(destPath,fileContent);
}
}
配置文件txt2excel.properties
放在txt2excel.jar包同级目录中
#\u6E90\u6587\u4EF6
srcPath=src.txt
#\u76EE\u6807\u6587\u4EF6
destPath=dest.xlsx
前提,组件执行按照流程,一个结束流程后的另一个才会开始,日志记录了组件执行时间戳,只是由于日志的异步输出导致日志内容更流程所示内容有差异
这里对读取到的文件行内容进行排序处理
写入excel前做时差计算,方便查看
eclipse打jar包为可执行jar
file–>Export–>java–>Runnable JAR File–>Next
Launch configuration:TXT2Excel - txt2excel
类名-工程名
这里是下拉框选择的,前提TXT2Excel类中必须有main方法作为程序入口,- Export destination:H:\utils\txt2excel.jar
这一步是指定打包到哪个目录下,并指定打包成的包名 - Library handing:
Extract required libraries into generated JAR:将依赖的jar解压出来变成class丢进你生成的jar里面;
Package required libraries into generated JAR:将依赖的jar不解压,直接放进你生成的jar里面;
Copy required libraries into a sub-folder next to the generated JAR:将依赖的jar放到你生成jar的同级目录下的”xxx_lib”文件夹里面。
我选的是第三个. - 完成Finish
执行完H:\utils\目录下生成的文件
txt2excel_lib
dom4j-1.6.1.jar
poi-3.9.jar
poi-ooxml-3.9.jar
poi-ooxml-schemas-3.9.jar
xmlbeans-2.3.0.jar
txt2excel.jar
将需要解析的文本文件src.txt放入到H:\utils\目录下,这里工具里面写死了,只会读取src.txt文件
- win+r–>cmd:
- java -jar txt2excel.jar
会生成目标文件dest.xlsx,查看日志方便多了,
DOS脚本
但是每次都使用dos命令操作,还是有点麻烦,这里就写一个DOS脚本文件.之后双击它就可以了
H:\utils\目录下新建txt2excel.bat,文本方式编辑,保存,内容如下:
@echo off
rem 这是注释
rem @echo off 第一行的意思是不显示后续命令行及当前命令行
rem title 名称 这个名称会显示在窗口的左上角,打开多个dos窗口时,这个就有用了
title txt2excel
rem echo 在dos窗口中输入一行内容
echo txt2excel Starting......
rem 执行我们要运行的命令
java -jar txt2excel.jar
echo txt2excel end......
rem pause 暂停,等待按键继续,这个方便我们在报错后查看报错信息,不写这个的话,dos窗口一闪即逝,没法看
pause