clarity 0.9.2 → 0.9.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.
- data/Manifest.txt +1 -3
- data/README.rdoc +1 -1
- data/Rakefile +8 -14
- data/lib/clarity.rb +1 -1
- data/lib/clarity/cli.rb +15 -6
- data/lib/clarity/grep_renderer.rb +17 -17
- data/lib/clarity/process_tree.rb +23 -0
- data/lib/clarity/renderers/log_renderer.rb +22 -33
- data/lib/clarity/server.rb +11 -27
- data/lib/clarity/server/chunk_http.rb +2 -0
- data/test/commands/command_builder_test.rb +10 -11
- data/test/commands/tail_command_builder_test.rb +1 -2
- data/test/parsers/hostname_parser_test.rb +1 -2
- data/test/parsers/shop_parser_test.rb +1 -2
- data/test/parsers/time_parser_test.rb +1 -2
- data/test/test_helper.rb +3 -2
- data/test/test_string_scanner.rb +1 -2
- data/views/_toolbar.html.erb +3 -3
- metadata +8 -7
- data/lib/clarity/parsers/hostname_parser.rb +0 -43
- data/lib/clarity/parsers/shop_parser.rb +0 -48
- data/lib/clarity/parsers/time_parser.rb +0 -93
data/Manifest.txt
CHANGED
|
@@ -10,9 +10,7 @@ lib/clarity/cli.rb
|
|
|
10
10
|
lib/clarity/commands/command_builder.rb
|
|
11
11
|
lib/clarity/commands/tail_command_builder.rb
|
|
12
12
|
lib/clarity/grep_renderer.rb
|
|
13
|
-
lib/clarity/
|
|
14
|
-
lib/clarity/parsers/shop_parser.rb
|
|
15
|
-
lib/clarity/parsers/time_parser.rb
|
|
13
|
+
lib/clarity/process_tree.rb
|
|
16
14
|
lib/clarity/renderers/log_renderer.rb
|
|
17
15
|
lib/clarity/server.rb
|
|
18
16
|
lib/clarity/server/basic_auth.rb
|
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
|
@@ -1,27 +1,21 @@
|
|
|
1
|
+
$LOAD_PATH.unshift File.join(File.dirname(__FILE__), "lib")
|
|
2
|
+
|
|
1
3
|
require 'rubygems'
|
|
2
4
|
gem 'hoe', '>= 2.1.0'
|
|
5
|
+
gem 'newgem'
|
|
6
|
+
|
|
3
7
|
require 'hoe'
|
|
4
|
-
require '
|
|
5
|
-
require './lib/clarity'
|
|
8
|
+
require 'clarity'
|
|
6
9
|
|
|
7
10
|
Hoe.plugin :newgem
|
|
8
|
-
# Hoe.plugin :website
|
|
9
|
-
# Hoe.plugin :cucumberfeatures
|
|
10
11
|
|
|
11
|
-
# Generate all the Rake tasks
|
|
12
|
-
# Run 'rake -T' to see list of generated tasks (from gem root directory)
|
|
13
12
|
$hoe = Hoe.spec 'clarity' do
|
|
14
13
|
self.developer 'Tobias Lütke', 'tobi@shopify.com'
|
|
15
14
|
self.developer 'John Tajima', 'john@shopify.com'
|
|
16
|
-
self.post_install_message = 'PostInstall.txt'
|
|
17
|
-
# self.rubyforge_name = self.name # TODO this is default value
|
|
18
|
-
|
|
15
|
+
self.post_install_message = 'PostInstall.txt'
|
|
19
16
|
self.extra_deps = [['eventmachine','>= 0.12.10'], ['eventmachine_httpserver','>= 0.2.0']]
|
|
17
|
+
self.test_globs = ['test/**/*_test.rb']
|
|
20
18
|
end
|
|
21
19
|
|
|
22
20
|
require 'newgem/tasks'
|
|
23
|
-
Dir['tasks/**/*.rake'].each { |t| load t }
|
|
24
|
-
|
|
25
|
-
# TODO - want other tests/tasks run by default? Add them to the list
|
|
26
|
-
# remove_task :default
|
|
27
|
-
# task :default => [:spec, :features]
|
|
21
|
+
Dir['tasks/**/*.rake'].each { |t| load t }
|
data/lib/clarity.rb
CHANGED
data/lib/clarity/cli.rb
CHANGED
|
@@ -1,6 +1,4 @@
|
|
|
1
1
|
require 'optparse'
|
|
2
|
-
#require File.dirname(__FILE__) + '/../clarity'
|
|
3
|
-
|
|
4
2
|
|
|
5
3
|
module Clarity
|
|
6
4
|
class CLI
|
|
@@ -9,9 +7,11 @@ module Clarity
|
|
|
9
7
|
options = {
|
|
10
8
|
:username => nil,
|
|
11
9
|
:password => nil,
|
|
12
|
-
:log_files =>
|
|
10
|
+
:log_files => nil,
|
|
13
11
|
:port => 8080,
|
|
14
|
-
:address => "0.0.0.0"
|
|
12
|
+
:address => "0.0.0.0",
|
|
13
|
+
:user => nil,
|
|
14
|
+
:group => nil
|
|
15
15
|
}
|
|
16
16
|
|
|
17
17
|
mandatory_options = %w( )
|
|
@@ -23,7 +23,10 @@ module Clarity
|
|
|
23
23
|
opts.separator "Specific options:"
|
|
24
24
|
|
|
25
25
|
opts.on( "-f", "--config=FILE", String, "Config file (yml)" ) do |opt|
|
|
26
|
-
|
|
26
|
+
config = YAML.load_file( opt )
|
|
27
|
+
config.keys.each do |key|
|
|
28
|
+
options[key.to_sym] = config[key]
|
|
29
|
+
end
|
|
27
30
|
end
|
|
28
31
|
|
|
29
32
|
opts.on( "-p", "--port=PORT", Integer, "Port to listen on" ) do |opt|
|
|
@@ -38,7 +41,11 @@ module Clarity
|
|
|
38
41
|
options[:log_files] ||= []
|
|
39
42
|
options[:log_files] += opt
|
|
40
43
|
end
|
|
41
|
-
|
|
44
|
+
|
|
45
|
+
opts.on( "--user=USER", String, "User to run as" ) do |opt|
|
|
46
|
+
options[:user] = opt
|
|
47
|
+
end
|
|
48
|
+
|
|
42
49
|
opts.separator " "
|
|
43
50
|
opts.separator "Password protection:"
|
|
44
51
|
|
|
@@ -67,6 +74,8 @@ module Clarity
|
|
|
67
74
|
Dir.chdir(arguments.first)
|
|
68
75
|
end
|
|
69
76
|
|
|
77
|
+
options[:log_files] ||= ['**/*.log*']
|
|
78
|
+
|
|
70
79
|
::Clarity::Server.run(options)
|
|
71
80
|
|
|
72
81
|
#rescue
|
|
@@ -1,10 +1,7 @@
|
|
|
1
1
|
module Clarity
|
|
2
|
-
module GrepRenderer
|
|
3
|
-
attr_accessor :response
|
|
4
|
-
|
|
5
|
-
def parser
|
|
6
|
-
@parser ||= TimeParser.new( HostnameParser.new(ShopParser.new), params)
|
|
7
|
-
end
|
|
2
|
+
module GrepRenderer
|
|
3
|
+
attr_accessor :response
|
|
4
|
+
attr_writer :renderer
|
|
8
5
|
|
|
9
6
|
def renderer
|
|
10
7
|
@renderer ||= LogRenderer.new
|
|
@@ -15,22 +12,25 @@ module Clarity
|
|
|
15
12
|
@buffer ||= StringScanner.new("")
|
|
16
13
|
@buffer << data
|
|
17
14
|
|
|
18
|
-
html = ""
|
|
19
15
|
while line = @buffer.scan_until(/\n/)
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
end
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
response.chunk html
|
|
16
|
+
response.chunk renderer.render(line)
|
|
17
|
+
flush
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def flush
|
|
27
22
|
response.send_chunks
|
|
28
23
|
end
|
|
24
|
+
|
|
25
|
+
def close
|
|
26
|
+
ProcessTree.kill(get_status.pid)
|
|
27
|
+
end
|
|
29
28
|
|
|
30
|
-
def unbind
|
|
31
|
-
response.chunk
|
|
29
|
+
def unbind
|
|
30
|
+
response.chunk renderer.finalize
|
|
32
31
|
response.chunk ''
|
|
33
|
-
|
|
32
|
+
close
|
|
33
|
+
flush
|
|
34
34
|
puts 'Done'
|
|
35
35
|
end
|
|
36
36
|
end
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
module ProcessTree
|
|
2
|
+
|
|
3
|
+
def self.kill(ppid)
|
|
4
|
+
return if ppid.nil?
|
|
5
|
+
all_pids = [ppid] + child_pids_of(ppid).flatten.uniq.compact
|
|
6
|
+
all_pids.each do |pid|
|
|
7
|
+
Process.kill('TERM',pid.to_i) rescue nil
|
|
8
|
+
end
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def self.child_pids_of(ppid)
|
|
12
|
+
out = `ps -opid,ppid | grep #{ppid.to_s}`
|
|
13
|
+
ids = out.split("\n").map {|line| $1 if line =~ /^\s*([0-9]+)\s.*/ }.compact
|
|
14
|
+
ids.delete(ppid.to_s)
|
|
15
|
+
if ids.empty?
|
|
16
|
+
ids
|
|
17
|
+
else
|
|
18
|
+
ids << ids.map {|id| child_pids_of(id) }
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
end
|
|
@@ -1,47 +1,36 @@
|
|
|
1
|
-
require 'action_view'
|
|
2
1
|
require 'uri'
|
|
2
|
+
require 'erb'
|
|
3
3
|
|
|
4
|
-
class LogRenderer
|
|
5
|
-
include ActionView::Helpers::TagHelper
|
|
6
|
-
include ActionView::Helpers::UrlHelper
|
|
4
|
+
class LogRenderer
|
|
7
5
|
|
|
6
|
+
# Thank you to http://daringfireball.net/2009/11/liberal_regex_for_matching_urls
|
|
7
|
+
#
|
|
8
|
+
UrlParser = %r{\b(([\w-]+://?|www[.])[^\s()<>]+(?:\([\w\d]+\)|([^[:punct:]\s]|/)))}
|
|
8
9
|
Prefix = ""
|
|
9
10
|
Suffix = "<br/>\n"
|
|
10
|
-
TagOrder = [ :timestamp, :shop, :labels, :line ]
|
|
11
|
-
MarkTime = 60 * 5 # 5 minutes
|
|
12
|
-
|
|
13
|
-
def initialize()
|
|
14
|
-
@last_timestamp = nil
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
def render(elements = {})
|
|
18
|
-
@elements = elements
|
|
19
|
-
@tags = []
|
|
20
|
-
TagOrder.each do |tag|
|
|
21
|
-
if content = @elements.fetch(tag, nil)
|
|
22
|
-
method = ("tag_"+tag.to_s).to_sym
|
|
23
|
-
@tags << self.send(method, content)
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
@tags.empty? ? "" : Prefix + @tags.join(" ").to_s + Suffix
|
|
28
|
-
end
|
|
29
11
|
|
|
12
|
+
def render(line = {})
|
|
13
|
+
# Escape
|
|
14
|
+
output = ERB::Util.h(line)
|
|
30
15
|
|
|
31
|
-
|
|
32
|
-
|
|
16
|
+
# Transform urls into html links
|
|
17
|
+
output.gsub!(UrlParser) do |match|
|
|
18
|
+
html_link(match)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# Return with formatting
|
|
22
|
+
"#{Prefix}#{output}#{Suffix}"
|
|
33
23
|
end
|
|
34
24
|
|
|
35
|
-
def
|
|
36
|
-
|
|
25
|
+
def finalize
|
|
26
|
+
'</div><hr><p id="done">Done</p></body></html>'
|
|
37
27
|
end
|
|
38
28
|
|
|
39
|
-
|
|
40
|
-
|
|
29
|
+
private
|
|
30
|
+
|
|
31
|
+
def html_link(url)
|
|
32
|
+
uri = URI.parse(url)
|
|
33
|
+
"<a href='#{uri}'>#{url}</a>"
|
|
41
34
|
end
|
|
42
35
|
|
|
43
|
-
def tag_labels(content, options = {})
|
|
44
|
-
"[#{content}]"
|
|
45
|
-
end
|
|
46
|
-
|
|
47
36
|
end
|
data/lib/clarity/server.rb
CHANGED
|
@@ -3,6 +3,7 @@ require File.dirname(__FILE__) + '/server/basic_auth'
|
|
|
3
3
|
require File.dirname(__FILE__) + '/server/mime_types'
|
|
4
4
|
require File.dirname(__FILE__) + '/server/chunk_http'
|
|
5
5
|
require File.dirname(__FILE__) + '/grep_renderer'
|
|
6
|
+
require File.dirname(__FILE__) + '/process_tree'
|
|
6
7
|
|
|
7
8
|
module Clarity
|
|
8
9
|
class NotFoundError < StandardError; end
|
|
@@ -18,6 +19,7 @@ module Clarity
|
|
|
18
19
|
attr_accessor :log_files
|
|
19
20
|
|
|
20
21
|
def self.run(options)
|
|
22
|
+
|
|
21
23
|
EventMachine::run do
|
|
22
24
|
EventMachine.epoll
|
|
23
25
|
EventMachine::start_server(options[:address], options[:port], self) do |a|
|
|
@@ -25,7 +27,14 @@ module Clarity
|
|
|
25
27
|
a.required_username = options[:username]
|
|
26
28
|
a.required_password = options[:password]
|
|
27
29
|
end
|
|
30
|
+
|
|
28
31
|
STDERR.puts "Listening #{options[:address]}:#{options[:port]}..."
|
|
32
|
+
|
|
33
|
+
if options[:user]
|
|
34
|
+
STDERR.puts "Running as user #{options[:user]}"
|
|
35
|
+
EventMachine.set_effective_user(options[:user])
|
|
36
|
+
end
|
|
37
|
+
|
|
29
38
|
STDERR.puts "Adding log files: #{options[:log_files].inspect}"
|
|
30
39
|
end
|
|
31
40
|
end
|
|
@@ -54,10 +63,9 @@ module Clarity
|
|
|
54
63
|
response.chunk results_page # display page header
|
|
55
64
|
|
|
56
65
|
puts "Running: #{command}"
|
|
66
|
+
|
|
57
67
|
EventMachine::popen(command, GrepRenderer) do |grepper|
|
|
58
68
|
@grepper = grepper
|
|
59
|
-
@grepper.marker = 0
|
|
60
|
-
@grepper.params = params
|
|
61
69
|
@grepper.response = response
|
|
62
70
|
end
|
|
63
71
|
end
|
|
@@ -97,34 +105,10 @@ module Clarity
|
|
|
97
105
|
end
|
|
98
106
|
|
|
99
107
|
def unbind
|
|
100
|
-
|
|
101
|
-
kill_processes(@grepper.get_status.pid)
|
|
108
|
+
@grepper.close_connection if @grepper
|
|
102
109
|
close_connection
|
|
103
110
|
end
|
|
104
111
|
|
|
105
|
-
def kill_processes(ppid)
|
|
106
|
-
return if ppid.nil?
|
|
107
|
-
all_pids = [ppid] + get_child_pids(ppid).flatten.uniq.compact
|
|
108
|
-
puts "=== pids are #{all_pids.inspect}"
|
|
109
|
-
all_pids.each do |pid|
|
|
110
|
-
Process.kill('TERM',pid.to_i)
|
|
111
|
-
puts "=== killing #{pid}"
|
|
112
|
-
end
|
|
113
|
-
rescue Exception => e
|
|
114
|
-
puts "!Error killing processes: #{e}"
|
|
115
|
-
end
|
|
116
|
-
|
|
117
|
-
def get_child_pids(ppid)
|
|
118
|
-
out = `ps -opid,ppid | grep #{ppid.to_s}`
|
|
119
|
-
ids = out.split("\n").map {|line| $1 if line =~ /^\s*([0-9]+)\s.*/ }.compact
|
|
120
|
-
ids.delete(ppid.to_s)
|
|
121
|
-
if ids.empty?
|
|
122
|
-
ids
|
|
123
|
-
else
|
|
124
|
-
ids << ids.map {|id| get_child_pids(id) }
|
|
125
|
-
end
|
|
126
|
-
end
|
|
127
|
-
|
|
128
112
|
private
|
|
129
113
|
|
|
130
114
|
def authenticate!
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
require
|
|
2
|
-
require File.dirname(__FILE__) + "/../../lib/commands/command_builder.rb"
|
|
1
|
+
require 'test_helper'
|
|
3
2
|
|
|
4
3
|
class CommandBuilderTest < Test::Unit::TestCase
|
|
5
4
|
|
|
@@ -29,35 +28,35 @@ class CommandBuilderTest < Test::Unit::TestCase
|
|
|
29
28
|
def test_exec_functions_for_log
|
|
30
29
|
command = CommandBuilder.new(@params)
|
|
31
30
|
assert_equal 1, command.exec_functions.size
|
|
32
|
-
assert_match
|
|
31
|
+
assert_match(/^grep/, command.exec_functions.first)
|
|
33
32
|
end
|
|
34
33
|
|
|
35
34
|
def test_exec_functions_with_multiple_terms_for_log
|
|
36
35
|
command = CommandBuilder.new(@params.merge("term2" => "bar", "term3" => "baz"))
|
|
37
36
|
assert_equal 3, command.exec_functions.size
|
|
38
|
-
assert_match
|
|
39
|
-
assert_match
|
|
40
|
-
assert_match
|
|
37
|
+
assert_match(/^grep/, command.exec_functions[0])
|
|
38
|
+
assert_match(/^grep/, command.exec_functions[1])
|
|
39
|
+
assert_match(/^grep/, command.exec_functions[2])
|
|
41
40
|
end
|
|
42
41
|
|
|
43
42
|
def test_exec_function_with_no_terms_for_log
|
|
44
43
|
command = CommandBuilder.new(@params.merge("term1" => nil))
|
|
45
44
|
assert_equal 1, command.exec_functions.size
|
|
46
|
-
assert_match
|
|
45
|
+
assert_match(/^cat/, command.exec_functions[0])
|
|
47
46
|
end
|
|
48
47
|
|
|
49
48
|
def test_exec_funcations_for_gzip
|
|
50
49
|
command = CommandBuilder.new(@params.merge("file" => "testfile.gz"))
|
|
51
50
|
assert_equal 1, command.exec_functions.size
|
|
52
|
-
assert_match
|
|
51
|
+
assert_match(/^zgrep/, command.exec_functions.first)
|
|
53
52
|
end
|
|
54
53
|
|
|
55
54
|
def test_exec_functions_with_multiple_terms_for_gzip
|
|
56
55
|
command = CommandBuilder.new(@params.merge("file" => "testfile.gz", "term2" => "bar", "term3" => "baz"))
|
|
57
56
|
assert_equal 3, command.exec_functions.size
|
|
58
|
-
assert_match
|
|
59
|
-
assert_match
|
|
60
|
-
assert_match
|
|
57
|
+
assert_match(/^zgrep/, command.exec_functions[0])
|
|
58
|
+
assert_match(/^grep/, command.exec_functions[1])
|
|
59
|
+
assert_match(/^grep/, command.exec_functions[2])
|
|
61
60
|
end
|
|
62
61
|
|
|
63
62
|
def test_exec_function_with_no_terms_for_gzip
|
data/test/test_helper.rb
CHANGED
data/test/test_string_scanner.rb
CHANGED
data/views/_toolbar.html.erb
CHANGED
|
@@ -81,9 +81,9 @@
|
|
|
81
81
|
</div>
|
|
82
82
|
|
|
83
83
|
<script>
|
|
84
|
-
Search.init({ 'grep': <%= logfiles.map {|f| f }.
|
|
85
|
-
'tail': <%= logfiles.map {|f| f if f =~ /log$/ }.compact.
|
|
86
|
-
<%= params.empty? ?
|
|
84
|
+
Search.init({ 'grep': <%= logfiles.map {|f| f }.inspect %>,
|
|
85
|
+
'tail': <%= logfiles.map {|f| f if f =~ /log$/ }.compact.inspect %> },
|
|
86
|
+
<%= params.empty? ? 'null' : params.inspect %> );
|
|
87
87
|
|
|
88
88
|
|
|
89
89
|
</script>
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: clarity
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.9.
|
|
4
|
+
version: 0.9.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- "Tobias L\xC3\xBCtke"
|
|
@@ -10,7 +10,7 @@ autorequire:
|
|
|
10
10
|
bindir: bin
|
|
11
11
|
cert_chain: []
|
|
12
12
|
|
|
13
|
-
date: 2009-
|
|
13
|
+
date: 2009-12-04 00:00:00 -05:00
|
|
14
14
|
default_executable:
|
|
15
15
|
dependencies:
|
|
16
16
|
- !ruby/object:Gem::Dependency
|
|
@@ -77,9 +77,7 @@ files:
|
|
|
77
77
|
- lib/clarity/commands/command_builder.rb
|
|
78
78
|
- lib/clarity/commands/tail_command_builder.rb
|
|
79
79
|
- lib/clarity/grep_renderer.rb
|
|
80
|
-
- lib/clarity/
|
|
81
|
-
- lib/clarity/parsers/shop_parser.rb
|
|
82
|
-
- lib/clarity/parsers/time_parser.rb
|
|
80
|
+
- lib/clarity/process_tree.rb
|
|
83
81
|
- lib/clarity/renderers/log_renderer.rb
|
|
84
82
|
- lib/clarity/server.rb
|
|
85
83
|
- lib/clarity/server/basic_auth.rb
|
|
@@ -133,5 +131,8 @@ signing_key:
|
|
|
133
131
|
specification_version: 3
|
|
134
132
|
summary: "Clarity - a log search tool By John Tajima & Tobi L\xC3\xBCtke Clarity is a Splunk like web interface for your server log files"
|
|
135
133
|
test_files:
|
|
136
|
-
- test/
|
|
137
|
-
- test/
|
|
134
|
+
- test/commands/command_builder_test.rb
|
|
135
|
+
- test/commands/tail_command_builder_test.rb
|
|
136
|
+
- test/parsers/hostname_parser_test.rb
|
|
137
|
+
- test/parsers/shop_parser_test.rb
|
|
138
|
+
- test/parsers/time_parser_test.rb
|
|
@@ -1,43 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
class HostnameParser
|
|
3
|
-
|
|
4
|
-
# given a string in format:
|
|
5
|
-
#
|
|
6
|
-
# app3 rails.shopify[9855]: [wadedemt.myshopify.com] Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
7
|
-
# 129.123.2.1 rails.shopify[9855]: [wadedemt.myshopify.com] Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
8
|
-
#
|
|
9
|
-
# strips out the hostname/IP and appname
|
|
10
|
-
#
|
|
11
|
-
# result => [wadedemt.myshopify.com] Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
LineRegexp = /^([\w-]+|\d+\.\d+\.\d+\.\d+)\s([^:]*):\s*(.*)/
|
|
15
|
-
|
|
16
|
-
attr_accessor :elements, :next_parser
|
|
17
|
-
|
|
18
|
-
def initialize(next_renderer = nil)
|
|
19
|
-
@next_renderer = next_renderer
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def parse(line, elements = {})
|
|
23
|
-
@elements = elements
|
|
24
|
-
# parse line into elements and put into element
|
|
25
|
-
next_line = parse_line(line)
|
|
26
|
-
if @next_renderer && next_line
|
|
27
|
-
@elements = @next_renderer.parse(next_line, @elements)
|
|
28
|
-
end
|
|
29
|
-
@elements
|
|
30
|
-
end
|
|
31
|
-
|
|
32
|
-
# parse line and break into pieces
|
|
33
|
-
def parse_line(line)
|
|
34
|
-
results = LineRegexp.match(line)
|
|
35
|
-
if results
|
|
36
|
-
@elements[:line] = results[-1]
|
|
37
|
-
results[-1] # remaining line
|
|
38
|
-
else
|
|
39
|
-
@elements[:line] = line
|
|
40
|
-
line
|
|
41
|
-
end
|
|
42
|
-
end
|
|
43
|
-
end
|
|
@@ -1,48 +0,0 @@
|
|
|
1
|
-
class ShopParser
|
|
2
|
-
|
|
3
|
-
# given a string in format:
|
|
4
|
-
#
|
|
5
|
-
# [wadedemt.myshopify.com] Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
6
|
-
#
|
|
7
|
-
# strips out the shop name
|
|
8
|
-
#
|
|
9
|
-
# result => :shop => wadedemt.myshopify.com
|
|
10
|
-
# :line => Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
LineRegexp = /^\s*\[([a-zA-Z0-9\-.]+)\]\s*(.*)/
|
|
14
|
-
|
|
15
|
-
attr_accessor :elements
|
|
16
|
-
|
|
17
|
-
def initialize(next_renderer = nil)
|
|
18
|
-
@next_renderer = next_renderer
|
|
19
|
-
end
|
|
20
|
-
|
|
21
|
-
def parse(line, elements = {})
|
|
22
|
-
@elements = elements
|
|
23
|
-
# parse line into elements and put into element
|
|
24
|
-
next_line = parse_line(line)
|
|
25
|
-
if @next_renderer && next_line
|
|
26
|
-
@elements = @next_renderer.parse(next_line, @elements)
|
|
27
|
-
end
|
|
28
|
-
@elements
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
# parse line and break into pieces
|
|
32
|
-
def parse_line(line)
|
|
33
|
-
results = LineRegexp.match(line)
|
|
34
|
-
if results
|
|
35
|
-
if results[1] =~ /\./
|
|
36
|
-
@elements[:shop] = results[1]
|
|
37
|
-
@elements[:line] = results[-1]
|
|
38
|
-
results[-1]
|
|
39
|
-
else
|
|
40
|
-
@elements[:line] = line
|
|
41
|
-
line
|
|
42
|
-
end
|
|
43
|
-
else
|
|
44
|
-
@elements[:line] = line
|
|
45
|
-
line
|
|
46
|
-
end
|
|
47
|
-
end
|
|
48
|
-
end
|
|
@@ -1,93 +0,0 @@
|
|
|
1
|
-
|
|
2
|
-
class TimeParser
|
|
3
|
-
|
|
4
|
-
# strips out timestamp and if start/end times are defined, will reject lines that don't fall within proper time periods
|
|
5
|
-
#
|
|
6
|
-
# entry format:
|
|
7
|
-
# Jul 24 14:58:21 app3 rails.shopify[9855]: [wadedemt.myshopify.com] Processing ShopController#products (for 192.168.1.230 at 2009-07-24 14:58:21) [GET]
|
|
8
|
-
#
|
|
9
|
-
# params = {
|
|
10
|
-
# 'sh' => start hour
|
|
11
|
-
# 'sm' => start minute
|
|
12
|
-
# 'ss' => start second
|
|
13
|
-
# 'eh' => end hour
|
|
14
|
-
# 'em' => end minute
|
|
15
|
-
# 'es' => end second
|
|
16
|
-
# }
|
|
17
|
-
#
|
|
18
|
-
# if 'sh' is defined, reject any lines where timestamp is earlier than start time
|
|
19
|
-
# if 'eh' is defined, reject any lines where timestamp is later than end time
|
|
20
|
-
# if 'sh' && 'eh' is defined, reject any lines where timestamp is not between start time and end time
|
|
21
|
-
|
|
22
|
-
LineRegexp = /^(\w+\s+\d+\s\d\d:\d\d:\d\d)\s(.*)/
|
|
23
|
-
|
|
24
|
-
attr_accessor :elements, :params
|
|
25
|
-
|
|
26
|
-
def initialize(next_renderer = nil, params = {})
|
|
27
|
-
@next_renderer = next_renderer
|
|
28
|
-
@params = params
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def parse(line, elements = {})
|
|
32
|
-
@elements = elements
|
|
33
|
-
next_line = parse_line(line)
|
|
34
|
-
|
|
35
|
-
# reject line if we filter by time
|
|
36
|
-
if check_time?
|
|
37
|
-
if !start_time_valid? || !end_time_valid?
|
|
38
|
-
# reject this entry
|
|
39
|
-
@elements = {}
|
|
40
|
-
return @elements
|
|
41
|
-
end
|
|
42
|
-
else
|
|
43
|
-
if @next_renderer && next_line
|
|
44
|
-
@elements = @next_renderer.parse(next_line, @elements)
|
|
45
|
-
end
|
|
46
|
-
end
|
|
47
|
-
@elements
|
|
48
|
-
end
|
|
49
|
-
|
|
50
|
-
def check_time?
|
|
51
|
-
(params['sh'] && !params['sh'].empty?) || (params['eh'] && !params['eh'].empty?)
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
# check if current line's time is >= start time, if it was set
|
|
55
|
-
def start_time_valid?
|
|
56
|
-
line_time = parse_time_from_string(@elements[:timestamp])
|
|
57
|
-
start_time = Time.utc(line_time.year, line_time.month, line_time.day, params.fetch('sh',0).to_i, params.fetch('sm', 0).to_i, params.fetch('ss', 0).to_i )
|
|
58
|
-
line_time >= start_time ? true : false
|
|
59
|
-
rescue Exception => e
|
|
60
|
-
puts "Error! #{e}"
|
|
61
|
-
end
|
|
62
|
-
|
|
63
|
-
def end_time_valid?
|
|
64
|
-
line_time = parse_time_from_string(@elements[:timestamp])
|
|
65
|
-
end_time = Time.utc(line_time.year, line_time.month, line_time.day, params.fetch('eh',23).to_i, params.fetch('em', 59).to_i, params.fetch('es', 59).to_i )
|
|
66
|
-
line_time <= end_time ? true : false
|
|
67
|
-
rescue Exception => e
|
|
68
|
-
puts "Error! #{e}"
|
|
69
|
-
end
|
|
70
|
-
|
|
71
|
-
def parse_time_from_string(text)
|
|
72
|
-
# Jul 24 14:58:21
|
|
73
|
-
time = nil
|
|
74
|
-
if text =~ /(\w+)\s+(\d+)\s+(\d+):(\d+):(\d+)/
|
|
75
|
-
time = Time.utc(Time.now.year, $1, $2, $3, $4, $5)
|
|
76
|
-
end
|
|
77
|
-
time
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# parse line and break into pieces
|
|
81
|
-
def parse_line(line)
|
|
82
|
-
results = LineRegexp.match(line)
|
|
83
|
-
if results
|
|
84
|
-
@elements[:timestamp] = results[1]
|
|
85
|
-
@elements[:line] = results[-1]
|
|
86
|
-
results[-1] # remaining line
|
|
87
|
-
else
|
|
88
|
-
@elements[:line] = line
|
|
89
|
-
line
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
end
|