class Fluent::ExceptionDetector
State machine that consumes individual log lines and detects multi-line stack traces.
Public Class Methods
new(*languages)
click to toggle source
# File lib/fluent/plugin/exception_detector.rb, line 114 def initialize(*languages) @state = :start_state @rules = Hash.new { |h, k| h[k] = [] } languages = [:all] if languages.empty? languages.each do |lang| rule_config = ExceptionDetectorConfig::RULES_BY_LANG.fetch(lang.downcase) do |_k| raise ArgumentError, "Unknown language: #{lang}" end rule_config.each do |r| target = ExceptionDetectorConfig::RuleTarget.new(r[:pattern], r[:to_state]) @rules[r[:from_state]] << target end end @rules.each_value(&:uniq!) end
Public Instance Methods
reset()
click to toggle source
# File lib/fluent/plugin/exception_detector.rb, line 162 def reset @state = :start_state end
update(line)
click to toggle source
Updates the state machine and returns the trace detection status:
-
no_trace: ‘line’ does not belong to an exception trace,
-
start_trace: ‘line’ starts a detected exception trace,
-
inside: ‘line’ is part of a detected exception trace,
-
end: the detected exception trace ends after ‘line’.
# File lib/fluent/plugin/exception_detector.rb, line 141 def update(line) trace_seen_before = transition(line) # If the state machine fell back to the start state because there is no # defined transition for 'line', trigger another state transition because # 'line' may contain the beginning of another exception. transition(line) unless trace_seen_before new_state = @state trace_seen_after = new_state != :start_state case [trace_seen_before, trace_seen_after] when [true, true] :inside_trace when [true, false] :end_trace when [false, true] :start_trace else :no_trace end end
Private Instance Methods
transition(line)
click to toggle source
Executes a transition of the state machine for the given line. Returns false if the line does not match any transition rule and the state machine was reset to the initial state.
# File lib/fluent/plugin/exception_detector.rb, line 171 def transition(line) @rules[@state].each do |r| next unless line =~ r.pattern @state = r.to_state return true end @state = :start_state false end