tailstrom 0.0.4 → 0.0.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d6fec2ff65f0328d66e043a18c115cd3015b9caf
4
- data.tar.gz: 647ff07f72e2450bc69405fb2705a3996c040e78
3
+ metadata.gz: e2084969ae138b43205364ee1c78bbe4af7e3288
4
+ data.tar.gz: b9bf1f575d1c915c2ae185d38d40acabb27341d6
5
5
  SHA512:
6
- metadata.gz: c557df7bb847da8d28c3f0f95193719bd65a0c1222e4f18fc2d0ea724c378ce6b8de4d1ece305ec969090b9cfe8dd704d79466d8e0ccb4b25ad544467a5dd135
7
- data.tar.gz: 8f0edf474fee9be1783f114287826bd5ecc6c641825bdc372b9a292c9ce3e68e81f3dfc630e43d397418986b89ef50512f2f47db39df2da2572835afc34c034d
6
+ metadata.gz: 3b960f9634555b00cedf6cb08d2e4449b1f13dc5e40b956b2734bd59547d0207c427e63111ee47ef7b90d239c252703e789748e699f6b93e363431dd1939096b
7
+ data.tar.gz: bc421512afa39984806754b237e6096df8fb7c4ae31a6f78504ef3f82a055b2bceb055956d5af312fbbd23ca7afa503323fd0e2c907705f5327bcd3ac2b55a01
data/bin/tailstrom CHANGED
@@ -1,24 +1,53 @@
1
1
  #!/usr/bin/env ruby
2
+ $: << File.expand_path('../../lib', __FILE__)
2
3
  require 'optparse'
3
4
 
5
+ def file_or_string(value)
6
+ File.exist?(value) ? File.read(value) : value
7
+ end
8
+
4
9
  options = {
5
10
  :delimiter => "\t",
6
11
  :interval => 1,
7
- :mode => :stat
12
+ :mode => :stat,
13
+ :order => :desc
8
14
  }
9
15
  OptionParser.new(ARGV) {|opt|
10
- opt.banner = "tail -f access.log | #{$0} <OPTIONS>"
11
- opt.on('-f [num]', Integer, 'value field') {|v| options[:field] = v }
12
- opt.on('-k [num]', Integer, 'key field') {|v| options[:key] = v }
13
- opt.on('-d [delimiter]', String) {|v| options[:delimiter] = v }
14
- opt.on('-i [interval]', Integer, 'interval for stat mode') {|v| options[:interval] = v }
15
- opt.on('-e [filter]', String) {|v| options[:filter] = v }
16
- opt.on('--map [file]', String, 'mapping file') {|v| options[:map] = File.read(v) }
16
+ opt.banner = <<-END
17
+ tail -f access.log | #{$0} [OPTIONS]
18
+ #{$0} [OPTIONS] [file]
19
+ END
20
+ opt.on('-f num', Integer, 'value field') {|v| options[:field] = v }
21
+ opt.on('-k num', Integer, 'key field') {|v| options[:key] = v }
22
+ opt.on('-d delimiter', String, 'delimiter') {|v| options[:delimiter] = v }
23
+ opt.on('-i interval', Integer, 'interval for stat mode') {|v| options[:interval] = v }
24
+ opt.on('-e file_or_string', '--in-filter file_or_string', String, 'input filtering') do |v|
25
+ options[:in_filter] = file_or_string v
26
+ end
27
+ opt.on('--map file_or_string', String, 'input mapping') do |v|
28
+ options[:map] = file_or_string v
29
+ end
30
+ opt.on('--out-filter file_or_string', String, 'output filtering') do |v|
31
+ options[:out_filter] = file_or_string v
32
+ end
33
+ opt.on('--sort file_or_string', String, 'output sorting') do |v|
34
+ options[:sort] = file_or_string v
35
+ end
36
+ opt.on('--order desc|asc', String, 'sorting order (default=desc)') do |v|
37
+ options[:order] = v.to_s.downcase == 'asc' ? :asc : :desc
38
+ end
17
39
  opt.on('--stat', 'statistics mode (default)') { options[:mode] = :stat }
18
40
  opt.on('--print', 'print line mode') { options[:mode] = :print }
19
- }.parse!
41
+ opt.on('--version', 'show version') do
42
+ require 'tailstrom/version'
43
+ puts Tailstrom::VERSION
44
+ exit 0
45
+ end
46
+ }.order!
47
+ if infile = ARGV.shift
48
+ options[:static_infile] = open(infile, 'r')
49
+ end
20
50
 
21
- $: << File.expand_path('../../lib', __FILE__)
22
51
  require "tailstrom/command/#{options[:mode]}"
23
52
  cls = Module.const_get "Tailstrom::Command::#{options[:mode].capitalize}"
24
53
  cmd = cls.new options
data/example/map1.rb CHANGED
@@ -7,4 +7,4 @@ key = case col[3]
7
7
  when %r(^/products/)
8
8
  'products'
9
9
  end
10
- #filter = 'value > 0'
10
+ #in_filter = 'value > 0'
@@ -5,58 +5,91 @@ require 'tailstrom/tail_reader'
5
5
  module Tailstrom
6
6
  module Command
7
7
  class Stat
8
- SCHEMA = [
9
- { :name => 'time', :width => 8 },
10
- { :name => 'count', :width => 7 },
11
- { :name => 'min', :width => 10 },
12
- { :name => 'max', :width => 10 },
13
- { :name => 'avg', :width => 10 },
14
- { :name => 'key', :width => 10, :align => :left }
15
- ]
16
-
17
8
  def initialize(options)
18
- @infile = $stdin
9
+ @infile = options[:static_infile] || $stdin
19
10
  @counters = CounterCollection.new
20
- @table = Table.new SCHEMA
21
- @options = options
11
+ @options = { :async => !options[:static_infile] }.merge options
12
+ @table = Table.new schema
13
+ end
14
+
15
+ def schema
16
+ [
17
+ ({ :name => 'time', :width => 8 } if @options[:async]),
18
+ { :name => 'count', :width => 7 },
19
+ { :name => 'min', :width => 10 },
20
+ { :name => 'max', :width => 10 },
21
+ { :name => 'avg', :width => 10 },
22
+ { :name => 'key', :width => 10, :align => :left }
23
+ ].compact
22
24
  end
23
25
 
24
26
  def run
25
- Thread.start do
26
- reader = TailReader.new @infile, @options
27
- reader.each_line do |line|
28
- @counters[line[:key]] << line[:value]
29
- end
30
- puts 'EOF'
27
+ reader = TailReader.new @infile, @options
28
+ reader.each_line do |line|
29
+ @counters[line[:key]] << line[:value]
31
30
  end
32
31
 
33
32
  height = `put lines`.to_i - 4 rescue 10
34
- @i = 0
35
- loop do
33
+ i = 0
34
+ begin
36
35
  sleep @options[:interval]
37
36
 
38
- if @i % height == 0
37
+ if i % height == 0
39
38
  @table.print_header
40
39
  end
41
40
 
42
- @counters.to_a.sort_by {|key, c|
43
- c.sum
44
- }.reverse_each do |key, c|
45
- key = (key == :nil ? nil : key)
46
- time = Time.now.strftime("%H:%M:%S")
47
- @table.print_row time, c.count, c.min, c.max, c.avg, key
48
- end
41
+ print_counters
49
42
 
50
43
  if @counters.size > 1
51
44
  @table.puts
52
45
  end
53
46
 
54
47
  @counters.clear
55
- @i = @i + 1
56
- end
48
+ i = i + 1
49
+ end while !reader.eof?
57
50
  rescue Interrupt
58
51
  exit 0
59
52
  end
53
+
54
+ private
55
+ def print_counters
56
+ sorted_counters.each do |key, c|
57
+ key = (key == :nil ? nil : key)
58
+ next unless out_filter(key, c)
59
+ if @options[:async]
60
+ time = Time.now.strftime("%H:%M:%S")
61
+ @table.print_row time, c.count, c.min, c.max, c.avg, key
62
+ else
63
+ @table.print_row c.count, c.min, c.max, c.avg, key
64
+ end
65
+ end
66
+ end
67
+
68
+ def sorted_counters
69
+ counters = @counters.to_a
70
+ if sort = @options[:sort]
71
+ counters.sort_by! do |key, c|
72
+ sum, avg, min, max, count =
73
+ c.sum, c.avg, c.min, c.max, c.count
74
+ binding.eval sort
75
+ end
76
+ else
77
+ counters.sort_by! do |key, c|
78
+ c.sum
79
+ end
80
+ end
81
+ @options[:order] == :asc ? counters : counters.reverse
82
+ end
83
+
84
+ def out_filter(key, counter)
85
+ if filter = @options[:out_filter]
86
+ sum, avg, min, max, count =
87
+ counter.sum, counter.avg, counter.min, counter.max, counter.count
88
+ binding.eval filter
89
+ else
90
+ true
91
+ end
92
+ end
60
93
  end
61
94
  end
62
95
  end
@@ -5,11 +5,17 @@ module Tailstrom
5
5
  end
6
6
 
7
7
  def <<(value)
8
+ purge_cache
8
9
  @values << value
9
10
  end
10
11
 
11
12
  def clear
12
13
  @values = []
14
+ purge_cache
15
+ end
16
+
17
+ def purge_cache
18
+ @cache = {}
13
19
  end
14
20
 
15
21
  def avg
@@ -18,15 +24,15 @@ module Tailstrom
18
24
  end
19
25
 
20
26
  def sum
21
- @values.inject(0, :+)
27
+ @cache[:sum] ||= @values.inject(0, :+)
22
28
  end
23
29
 
24
30
  def min
25
- @values.min
31
+ @cache[:min] ||= @values.min
26
32
  end
27
33
 
28
34
  def max
29
- @values.max
35
+ @cache[:max] ||= @values.max
30
36
  end
31
37
 
32
38
  def med
@@ -34,7 +40,7 @@ module Tailstrom
34
40
  end
35
41
 
36
42
  def count
37
- @values.count
43
+ @cache[:count] ||= @values.count
38
44
  end
39
45
  end
40
46
  end
@@ -8,10 +8,10 @@ module Tailstrom
8
8
  def print_row(*cols)
9
9
  cols.each_with_index do |col, i|
10
10
  col_schema = @schema[i]
11
- num_str = col ? num_with_delim(col) : '-'
11
+ str = format_string col
12
12
  print ' ' if i > 0
13
13
  align = col_schema[:align].to_s == 'left' ? '-' : nil
14
- printf "%#{align}#{col_schema[:width]}s", num_str
14
+ printf "%#{align}#{col_schema[:width]}s", str
15
15
  end
16
16
  self.puts
17
17
  end
@@ -35,6 +35,17 @@ module Tailstrom
35
35
  end
36
36
 
37
37
  private
38
+ def format_string(value)
39
+ case value
40
+ when Numeric
41
+ num_with_delim value
42
+ when nil
43
+ '-'
44
+ else
45
+ value
46
+ end
47
+ end
48
+
38
49
  def num_with_delim(num)
39
50
  head, tail = num.to_s.split('.')
40
51
  head.gsub!(/(\d)(?=(\d\d\d)+(?!\d))/, "\\1,")
@@ -5,28 +5,41 @@ module Tailstrom
5
5
  @options = options
6
6
  end
7
7
 
8
- def each_line
8
+ def each_line(&block)
9
+ if @options[:async]
10
+ Thread.new { _each_line &block }
11
+ else
12
+ _each_line &block
13
+ end
14
+ end
15
+
16
+ def _each_line
9
17
  @infile.each_line do |line|
10
18
  line.chomp!
11
19
  result = parse_line(line)
12
20
  yield result if result
13
21
  end
14
22
  end
23
+ private :_each_line
24
+
25
+ def eof?
26
+ @infile.eof?
27
+ end
15
28
 
16
29
  def parse_line(line)
17
30
  col = line.split @options[:delimiter]
18
31
  value = @options[:field] ? col[@options[:field]] : line
19
32
  value = format_value value
20
33
  key = @options[:key] ? col[@options[:key]] : :nil
21
- filter = @options[:filter]
34
+ in_filter = @options[:in_filter]
22
35
 
23
36
  if @options[:map]
24
37
  binding.eval(@options[:map])
25
38
  value = format_value value
26
39
  end
27
40
 
28
- if filter
29
- return nil unless binding.eval(filter)
41
+ if in_filter
42
+ return nil unless binding.eval(in_filter)
30
43
  end
31
44
 
32
45
  { :line => line, :columns => col, :key => key, :value => value }
@@ -1,3 +1,3 @@
1
1
  module Tailstrom
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
data/tailstrom.gemspec CHANGED
@@ -8,7 +8,7 @@ Gem::Specification.new do |spec|
8
8
  spec.version = Tailstrom::VERSION
9
9
  spec.authors = ["Issei Naruta"]
10
10
  spec.email = ["naruta@cookpad.com"]
11
- spec.description = %q{tailstrom is an utility for "tail -f"}
11
+ spec.description = %q{tailstrom is an utility for "tail -f"}
12
12
  spec.summary = %q{A utility for "tail -f"}
13
13
  spec.homepage = ""
14
14
  spec.license = "MIT"
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: tailstrom
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Issei Naruta