Class: Chainsaw::Filter

Inherits:
Object
  • Object
show all
Defined in:
lib/chainsaw/filter.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(logfile, range, options = OpenStruct.new) ⇒ Filter

Initialize a Filter instance. We read the logfile here and attempt to detect what type of logfile it is.

logfile - the String path of the logfile to be filtered range - the “time” range to filter through (Time or Range) options - an OpenStruct representing the options

Returns the Filter instance



13
14
15
16
17
18
19
20
21
# File 'lib/chainsaw/filter.rb', line 13

def initialize(logfile, range, options = OpenStruct.new)
  @logfile    = logfile
  @range      = range
  @options    = options
  @log        = File.open(@logfile)
  @line_count = 0

  self
end

Instance Attribute Details

#line_countObject (readonly)

Returns the value of attribute line_count.



3
4
5
# File 'lib/chainsaw/filter.rb', line 3

def line_count
  @line_count
end

Class Method Details

.filter(*args) ⇒ Object

A convinence method to initialize a Filter object using the given args and start filtering it



110
111
112
# File 'lib/chainsaw/filter.rb', line 110

def self.filter(*args)
  new(*args).start
end

.parse_timestamp(timestamp, time_format) ⇒ Object

Parse a timestamp using the given time_format.

timestamp - the String timestamp time_format - the String time format used to parse

Returns a parsed Time object



101
102
103
104
105
# File 'lib/chainsaw/filter.rb', line 101

def self.parse_timestamp(timestamp, time_format)
  dt = DateTime.strptime(timestamp, time_format)

  Time.local(dt.year, dt.month, dt.day, dt.hour, dt.min, dt.sec)
end

Instance Method Details

#found(line, timestamp) ⇒ Object

A matching line was found, set @outputting incase we run into lines that aren’t timestamped.

line - the String logline timestamp - the String timestamp from the logline



72
73
74
75
76
77
78
79
# File 'lib/chainsaw/filter.rb', line 72

def found(line, timestamp)
  @outputting = true
  @line_count += 1

  out(line, timestamp)

  STDIN.gets if @options.interactive && !@options.output_file
end

#out(line, timestamp = nil) ⇒ Object

Output the logline to STDOUT or File. We also colorize if requested.

line - the String logline timestamp - the String timestamp from the logline



85
86
87
88
89
90
91
92
93
# File 'lib/chainsaw/filter.rb', line 85

def out(line, timestamp = nil)
  if @options.output_file
    File.open(@options.output_file, 'a') { |f| f.write(line) }
  elsif @options.colorize && timestamp
    puts line.sub(timestamp, "\033[32m#{timestamp}\033[0m")
  else
    puts line
  end
end

#startObject

Start iterating through the log lines and filtering them accordingly.



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
# File 'lib/chainsaw/filter.rb', line 24

def start
  @ofilter = @options.filter

  File.open(@logfile).each do |line|
    if !@detected && @format = Detector.detect(line)
      @detected = true
      @log.rewind
    elsif @format.nil?
      next
    end

    begin
      match = line.match(@format.pattern)
    rescue ArgumentError
      line.encode!("UTF-8", "UTF-8", :invalid => :replace, :undef => :replace, :replace => '?')
      redo
    end

    if match
      timestamp = match[1]
      time      = Filter.parse_timestamp(timestamp, @format.time_format)
    else
      timestamp = time = nil
    end

    # a match was found if we are filtering additional text, check that too
    if match && @range.cover?(time) && ( !@ofilter || @ofilter && line.include?(@ofilter) )
      found(line, timestamp)
    # a match was found and we are outputting non-timestamped lines
    elsif match && @outputting
      @outputting = false
    # outputting non-timestamped lines
    elsif @outputting
      out(line)
    end
  end

  unless @options.output_file
    hind = (@line_count.zero? || @line_count > 1) ? 's' : ''
    puts "\n\033[33mFound #{@line_count} line#{hind} \033[0m"
  end
end