Skip to content

Instantly share code, notes, and snippets.

@linsea
Created August 10, 2018 09:34
Show Gist options
  • Save linsea/f7f7518016b17e4a0c79801b62854a0a to your computer and use it in GitHub Desktop.
Save linsea/f7f7518016b17e4a0c79801b62854a0a to your computer and use it in GitHub Desktop.
Log分析统计脚本
import java.io.File
import java.lang.System.exit
import java.text.SimpleDateFormat
import java.util.*
if (args.size != 3) {
println("使用方法: kotlinc -script logst.kts <input_log_file_path> <output_file_path> <regex_pattern>")
println("注意 <regex_pattern> 中的正则使用'|'分隔重点LOG行, 第一个和最后一个必须为一次统计的开始行和结束行正则, 否则无法分辨一次统计的起始点与终止点")
exit(1)
}
Loge(logFilePath = args[0], outputFilePath = args[1], regex = args[2]).execute()
class Loge(logFilePath: String, outputFilePath: String, val regex: String) {
private val logFile = File(logFilePath)
private val outputFile = File(outputFilePath)
private val regexList = regex.split("""|""").toList()
private val resultList = mutableListOf<MutableList<Element>>()
private var foundFirst = false
private var statis: MutableList<Element>? = null
private val dateFormat = SimpleDateFormat("HH:mm:ss.SSS")
fun execute() {
regexFind()
outputResult()
}
private fun extractDate(lineStr: String): Date {
val datetimeStr = lineStr.substring(0, 12)
return dateFormat.parse(datetimeStr)
}
private fun regexFind() {
val lines = logFile.readLines(Charsets.UTF_8)
lines.forEach { lineStr ->
if (lineStr.isNotEmpty()) {
regexList.forEachIndexed { idx, regStr ->
if (regStr.toRegex().containsMatchIn(lineStr)) {
if (idx == 0) {
foundFirst = true
statis = mutableListOf(Element(0, 0, extractDate(lineStr), lineStr, idx, null))
} else if (idx == regexList.lastIndex) {
if (foundFirst) {
statis?.also {
it.add(Element(0, 0, extractDate(lineStr), lineStr, idx, null))
resultList.add(it)
foundFirst = false
}
}
} else {
if (foundFirst) {//第一次匹配到的不是一次统计的日志开始点
val matchedElement = Element(0, 0, extractDate(lineStr), lineStr, idx, null)
statis!!.add(matchedElement)
}
}
}
}
}
}
}
private fun outputResult() {
resultList.forEach { innerList ->
innerList.forEachIndexed { idx, el ->
if (idx != 0) {
val pre = innerList[idx - 1]
el.execTime = el.time.time - pre.time.time
el.elapseTime = el.time.time - innerList[0].time.time
} else {
outputHeader()
}
outputContent(el.format())
}
}
outputAvg(resultList)
outputFooter()
}
private fun outputAvg(resultList: MutableList<MutableList<Element>>) {
var size = -1
resultList.forEachIndexed { idx, innerList -> //检查每个size是否相等
if (idx == 0) {
size = innerList.size
} else {
if (size == -1 || size != innerList.size) {
outputContent("=======================================================================")
outputContent("${idx+1}次统计时匹配到的所有行数与前一次不相等,无法计算平均值!请检查正则或自行查看筛选出的日志.")
return
}
}
}
for (i in 0 until size) { //检查所有统计的每一行匹配的正则是否相等
val regIdx = resultList[0][i].matchedRegIdx
resultList.forEachIndexed { index, innerList ->
if (index != 0) {
if (innerList[i].matchedRegIdx != regIdx) {
outputContent("=======================================================================")
outputContent("${i+1}次,有行匹配到相同的正则,但与前一次的内容不同,无法计算平均值!请检查正则或自行查看筛选出的日志.")
outputContent("匹配到的日志:${innerList[i].log}")
outputContent("使用的正则表达式:${regexList[innerList[i].matchedRegIdx]}")
return
}
}
}
}
outputContent("==========================================")
outputContent("平均 Exec ms | 平均 Elapse ms | 样例LOG")
for (i in 0 until size) {
var avgExecTime: Long = 0
var avgElapseTime: Long = 0
var sampleLog: String? = ""
resultList.forEach {
avgExecTime += it[i].execTime!!
avgElapseTime += it[i].elapseTime!!
sampleLog = it[i].log
}
avgExecTime /= resultList.size
avgElapseTime /= resultList.size
outputContent(String.format("%12d | %15d | %s", avgExecTime, avgElapseTime, sampleLog))
}
}
private fun outputHeader() {
outputContent("=================================")
outputContent("Exec ms | Elapse ms | Log Message")
outputContent("=================================")
}
private fun outputContent(s: String) {
println(s)
outputFile.appendText(s)
outputFile.appendText("\n")
}
private fun outputFooter() {
outputContent("=================================")
outputContent(" Regex: $regex ")
outputContent("Input Log File: ${logFile.absolutePath} ")
outputContent(" Output File: ${outputFile.absolutePath}")
outputContent("Output Success!")
}
}
data class Element(
var execTime: Long?,
var elapseTime: Long?,
val time: Date,
var log: String?,
var matchedRegIdx: Int,
var desc: String?) {
fun format(): String {
return String.format("%7d | %6d | %s", execTime, elapseTime, log)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment