class FingerPrinter

Constants

LANG_JAVA
LANG_NODEJS
LANG_PYTHON
REASON_MULTIPLE_EXCEPTION_NAMES
REASON_NOT_A_STACKTRACE
REASON_NO_EXCEPTION_NAME

Public Instance Methods

fingerprint_error(lang, reason, message) click to toggle source
# File lib/fluent/plugin/fingerprinter.rb, line 31
def fingerprint_error(lang, reason, message)
    log = Syslog::Logger.new 'finger_printer'
    error_message = 'Error fingerprinting [lang:%s] [reason:%s] message:\n%s' % [lang, reason, message]
    log.error error_message
    return nil
end
fingerprint_java(message) click to toggle source
# File lib/fluent/plugin/fingerprinter.rb, line 113
def fingerprint_java(message)
        message = message.gsub(/\\n/, "\n")
        message = message.gsub(/\\t/, "\t")
        matches = message.scan(/^[ \t]*([^ \t]+)[:\r\n]/)
        if matches.length == 1
            err_name = matches[0][0]
        else
            heuristic_message = heuristic_search_java_stack_trace(message)
            if heuristic_message != nil
                err_name = heuristic_message[3]
                message = heuristic_message[2]
            else
                return fingerprint_error(LANG_JAVA, REASON_NO_EXCEPTION_NAME, message)
            end
        end
        clean_message = message
        clean_message = clean_message.gsub(/\A\s*([^:\s]*).*/, '\1')
        clean_message = clean_message.gsub(/(Caused by: [^:\s]*).*/, '\1')
        clean_message = clean_message.gsub(/[ \t]*at[ \t]+([^(]+).*/, "\tat "+'\1')
        clean_message = clean_message.gsub(/at sun\.reflect\.NativeMethodAccessorImpl\.invoke0/, "\n")
        clean_message = clean_message.gsub(/at sun\.reflect\.NativeMethodAccessorImpl(\.[^.\s]+)/, 'at sun.reflect.$$MethodAccessor$$\1')
        clean_message = clean_message.gsub(/at sun\.reflect\.GeneratedMethodAccessor.*(\.[^.\s]+)/, 'at sun.reflect.$$MethodAccessor$$\1')
        clean_message = clean_message.gsub(/at com\.sun\.proxy\.\$Proxy.*\.([^.]+)/, 'at com.sun.proxy.$Proxy$$')
        clean_message = clean_message.gsub(/^((?!(Caused by:|Suppressed:|(\s*at ))).)*$/,'')
        clean_message = clean_message.gsub(/\A^/,err_name)
        clean_message = clean_message.gsub(/([\r\n]\s*[\r\n])+/, "\n").strip

        stack = Array.new
        cur_stack = Array.new
        stack_matches = clean_message.scan(/(Caused by:|Suppressed:)|(at\s+(.+)\.([^.\s]+))/)
        for stack_match in stack_matches do
            if stack_match[0]
                stack = cur_stack + stack
                cur_stack.clear
            else
                cur_stack << [stack_match[2], stack_match[3]]
            end
        end
        if stack
            stack = cur_stack + stack
        else
            stack = cur_stack
        end
        fingerprint = Digest::SHA1.hexdigest clean_message
        return err_name, fingerprint, clean_message, stack
end
fingerprint_nodejs(message) click to toggle source
# File lib/fluent/plugin/fingerprinter.rb, line 77
def fingerprint_nodejs(message)
      json_stack_matches = message.scan(/"stack"\s*:\s*"([^\"]*)"/)
      if json_stack_matches.length > 0
          clean_message = json_stack_matches[0].to_s
          clean_message = clean_message[2..clean_message.length-3]
          clean_message = clean_message.gsub(/\s+at\s+/, "\n--- at ")
      else
          clean_message = message.gsub('---', "\n---")
      end
      matches = clean_message.scan(/\s*at[^(]*([^)]*\.js:[0-9]+:[0-9]+)/)
      if matches.length < 1
          return fingerprint_error(LANG_NODEJS, REASON_NOT_A_STACKTRACE, clean_message)
      end
      matches = clean_message.scan(/\s*([a-zA-Z]+)(:\s|(\s*$))/)
      if matches.length > 0
          err_name = matches[0][0]
          matches = clean_message.scan(/(^|\n)---\s*at\s*(.*)/)
          lines = ""
          for parts in matches do
              frame = parts[1].strip
              lines = "%sat %s\n" % [lines, frame]
          end
          clean_message = "%s\n%s" % [err_name,lines]
          clean_message = clean_message.gsub(/:[0-9]+:[0-9]+/, ":*:*")
          fingerprint = Digest::SHA1.hexdigest clean_message
          stack = []
          stack_matches = clean_message.scan(/at\s+((.+)\s+\()?([^:]*).*/)
          for stack_match in stack_matches do
              stack << [stack_match[1], stack_match[2]]
          end
          return err_name, fingerprint, clean_message, stack
      else
          return fingerprint_error(LANG_NODEJS, REASON_NO_EXCEPTION_NAME, message)
      end
end
fingerprint_python(message) click to toggle source
# File lib/fluent/plugin/fingerprinter.rb, line 38
def fingerprint_python(message)
        clean_message = message
        idx = clean_message.index("Traceback (most recent call last)")
        if idx == -1
            return fingerprint_error(LANG_PYTHON, REASON_NOT_A_STACKTRACE, clean_message)
        end
        clean_message = clean_message[idx..-1]
        clean_message = clean_message.gsub('---', "\n---")
        clean_message = clean_message.gsub(/---\s*$/, "")
        t = clean_message.index(/Traceback \(most recent call last\)/)
        clean_message = clean_message[t..-1]
        dup = clean_message.index("Traceback (most recent call last)", idx+1)
        if dup != nil
            clean_message = clean_message[0..dup]
        end
        check_format = clean_message.scan(/---\s/)
        if check_format.length == 0
            clean_message = clean_message.gsub("\n", "\n--- ")
        end
        matches = clean_message.scan(/---\s([a-zA-Z_]+)(:|(\s*$))/)
        if matches.length == 1
            err_name = matches[0][0]
            clean_message = clean_message.gsub(/,\s*line\s*[0-9]*\s*,/, ", line *,")
            clean_message = clean_message.gsub(/---\s*((?!File).)*(\n|$)/, '')
            clean_message = "%s--- %s" % [clean_message, err_name]
            fingerprint = Digest::SHA1.hexdigest clean_message
            stack = Array.new
            stack_matches = clean_message.scan(/---\s+File\s+"([^"]*)".*\s+in\s+([^\s]*)/)
            for stack_match in stack_matches do
                stack << [stack_match[0], stack_match[1]]
            end
            return err_name, fingerprint, clean_message, stack
        elsif matches.length == 0
            return fingerprint_error(LANG_PYTHON, REASON_NO_EXCEPTION_NAME, message)
        else
            return fingerprint_error(LANG_PYTHON, REASON_MULTIPLE_EXCEPTION_NAMES, message)
        end
end
heuristic_search_java_stack_trace(log_message) click to toggle source
# File lib/fluent/plugin/fingerprinter.rb, line 160
def heuristic_search_java_stack_trace(log_message)
    matches = /(^|[\r\n])((([\w_$][\w_$]*\.)*[\w_$][\w_$]*)([\r\\n]|:[^\r\\n]*).*\s*at\s+[^\s]+\(.*)/m.match(log_message)
    if matches != nil
        return matches
    else
        return nil
    end
end