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.
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 }