Подтвердить что ты не робот

Инструмент для извлечения трасс java стека из файлов журналов

Есть ли какой-нибудь инструмент, который может извлечь список следов стека, появляющихся в файле журнала, и, возможно, считать уникальными?

EDIT: я бы предпочел что-то, что не основано на графическом интерфейсе, и работать на фоновом режиме и возвращать какой-то отчет. У меня довольно много журналов, собранных из нескольких сред, и просто хочу получить быстрый обзор.

4b9b3361

Ответ 1

Я придумал следующее Groovy script. Это, конечно, очень приспособлено к моим потребностям, но я надеюсь, что это поможет кому-то.

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
}

Ответ 2

Вот быстрое и грязное выражение grep... если вы используете регистратор, такой как log4j, чем первая строка исключения, как правило, содержат WARN или ERROR, следующая строка будет содержать исключение имя и, возможно, сообщение, а затем последующая трассировка стека начнется с одного из следующих действий:

  • "\tat" (tab + at)
  • "Caused by: "
  • "\t... <some number> more" (это строки, которые указывают количество кадров в стеке, не отображаемое в исключении "Caused by" )
  • Имя исключения (и, возможно, сообщение) перед стекем

Мы хотим получить все вышеперечисленные строки, поэтому выражение grep:

grep -P "(WARN|ERROR|^\tat |Exception|^Caused by: |\t... \d+ more)"

Предполагается, что класс Exception всегда содержит слово Exception, которое может быть или не быть истинным, но это все-таки быстро и грязно.

При необходимости отрегулируйте свой конкретный случай.

Ответ 3

Вы можете написать это сами довольно легко. Вот шаблон:

  • Открыть файл
  • Найдите строку "\n\tat " (эта новая строка, вкладка, at, пусто). Это довольно необычная строка за пределами трассировки стека.

Теперь вам нужно найти первую строку, которая не начинается с \t, чтобы найти конец трассировки стека. Вы можете пропустить 1-3 строки после этого, чтобы поймать цепочки исключений.

Плюс добавьте пару строк (скажем, 10 или 50) перед первой строкой трассировки стека, чтобы получить некоторый контекст.

Ответ 4

Я написал инструмент в Python. Ему удается разделить две трассировки стека, даже если они идут сразу после друг друга в журнале.

#!/usr/bin/env python
#
# Extracts exceptions from log files.
#

import sys
import re
from collections import defaultdict

REGEX = re.compile("(^\tat |^Caused by: |^\t... \\d+ more)")
# Usually, all inner lines of a stack trace will be "at" or "Caused by" lines.
# With one exception: the line following a "nested exception is" line does not
# follow that convention. Due to that, this line is handled separately.
CONT = re.compile("; nested exception is: *$")

exceptions = defaultdict(int)

def registerException(exc):
  exceptions[exc] += 1

def processFile(fileName):
  with open(fileName, "r") as fh:
    currentMatch = None
    lastLine = None
    addNextLine = False
    for line in fh.readlines():
      if addNextLine and currentMatch != None:
        addNextLine = False
        currentMatch += line
        continue
      match = REGEX.search(line) != None
      if match and currentMatch != None:
        currentMatch += line
      elif match:
        currentMatch = lastLine + line
      else:
        if currentMatch != None:
          registerException(currentMatch)
        currentMatch = None
      lastLine = line
      addNextLine = CONT.search(line) != None
    # If last line in file was a stack trace
    if currentMatch != None:
      registerException(currentMatch)

for f in sys.argv[1:]:
  processFile(f)

for item in sorted(exceptions.items(), key=lambda e: e[1], reverse=True):
  print item[1], ":", item[0]

Ответ 5

Здесь хороший код, который делает то же самое - http://www.techiedelight.com/java-program-search-exceptions-huge-log-file-on-server/

Он в основном читает файл журнала по строкам и ищет ключевое слово "Исключение" в каждой строке. После этого он будет печатать следующие 10 строк (трассировка исключений) в отдельном выходном файле.

Ответ 6

Я использую Baretail.