Is there any tool that can extract a list of stack traces appearing in the log file and probably count unique ones?
EDIT: I would preffer something that is not GUI-based and be run on the background and give some kind of report back. I have quite many logs gathered from several environments and just would like to get quick overview.
Advertisement
Answer
I have come up with the following Groovy script. It is, of course, very much adjusted to my needs, but I hope it helps someone.
JavaScript
x
def traceMap = [:]
// Number of lines to keep in buffer
def BUFFER_SIZE = 100
// Pattern for stack trace line
def TRACE_LINE_PATTERN = '^[\s\t]+at .*$'
// Log line pattern between which we try to capture full trace
def LOG_LINE_PATTERN = '^([<#][^/]|\d\d).*$'
// List of patterns to replace in final captured stack trace line
// (e.g. replace date and transaction information that may make similar traces to look as different)
def REPLACE_PATTERNS = [
'^\d+-\d+\@.*?tksId: [^\]]+\]',
'^<\w+ \d+, \d+ [^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <',
'^####<[^>]+?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <[^>]*?> <',
'<([\w:]+)?TransaktionsID>[^<]+?</([\w:]+)?TransaktionsID>',
'<([\w:]+)?TransaktionsTid>[^<]+?</([\w:]+)?TransaktionsTid>'
]
new File('.').eachFile { File file ->
if (file.name.contains('.log') || file.name.contains('.out')) {
def bufferLines = []
file.withReader { Reader reader ->
while (reader.ready()) {
def String line = reader.readLine()
if (line.matches(TRACE_LINE_PATTERN)) {
def trace = []
for(def i = bufferLines.size() - 1; i >= 0; i--) {
if (!bufferLines[i].matches(LOG_LINE_PATTERN)) {
trace.add(0, bufferLines[i])
} else {
trace.add(0, bufferLines[i])
break
}
}
trace.add(line)
if (reader.ready()) {
line = reader.readLine()
while (!line.matches(LOG_LINE_PATTERN)) {
trace.add(line)
if (reader.ready()) {
line = reader.readLine()
} else {
break;
}
}
}
def traceString = trace.join("n")
REPLACE_PATTERNS.each { pattern ->
traceString = traceString.replaceAll(pattern, '')
}
if (traceMap.containsKey(traceString)) {
traceMap.put(traceString, traceMap.get(traceString) + 1)
} else {
traceMap.put(traceString, 1)
}
}
// Keep the buffer of last lines.
bufferLines.add(line)
if (bufferLines.size() > BUFFER_SIZE) {
bufferLines.remove(0)
}
}
}
}
}
traceMap = traceMap.sort { it.value }
traceMap.reverseEach { trace, number ->
println "-- Occured $number times -----------------------------------------"
println trace
}