rails-log-sorter 0.1

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.
@@ -0,0 +1,17 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rails-log-sorter"
4
+
5
+ file = ARGV[0]
6
+ action = ARGV[1]
7
+ limit = (ARGV[2] || 0).to_f
8
+
9
+ log = RailsLogSorter::Log.new_with_file(file)
10
+
11
+ reqs = log.find_slowest(action, limit)
12
+ reqs.each {|req|
13
+ req.lines.each {|line| puts line.original_line}
14
+ puts ""
15
+ puts "*" * 50
16
+ puts ""
17
+ }
@@ -0,0 +1,93 @@
1
+ module RailsLogSorter
2
+ class Log
3
+ def self.new_with_file(file)
4
+ new(File.read(file))
5
+ end
6
+
7
+ attr_reader :requests
8
+
9
+ def initialize(log)
10
+ @requests = []
11
+
12
+ current_requests = {}
13
+
14
+ log.split("\n").each {|line|
15
+ begin
16
+ line = Line.new(line)
17
+
18
+ request = current_requests[line.pid]
19
+
20
+ case line.type
21
+ when :started
22
+ current_requests[line.pid] = request = Request.new
23
+ request.lines << line
24
+ @requests << request
25
+ when :processing
26
+ if request
27
+ request.action = line.action
28
+ request.lines << line
29
+ end
30
+ when :completed
31
+ if request
32
+ request.runtime = line.runtime
33
+ request.lines << line
34
+ end
35
+ current_requests[line.pid] = nil
36
+ else
37
+ request.lines << line if request
38
+ end
39
+
40
+ rescue
41
+ p line
42
+ raise
43
+ end
44
+ }
45
+ end
46
+
47
+ def find(action)
48
+ @requests.select {|r| r.action == action}
49
+ end
50
+
51
+ def find_slowest(action, limit=5)
52
+ find(action).sort_by {|r| r.runtime}.reverse[0..(limit - 1)]
53
+ end
54
+ end
55
+
56
+ class Request
57
+ attr_accessor :lines, :action, :runtime
58
+
59
+ def initialize
60
+ @lines = []
61
+ end
62
+ end
63
+
64
+ class Line
65
+ FORMAT = /\A(?<timestamp>\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}) \[(?<loglevel>.*)\] (?<message>.*) \(pid:(?<pid>\d+)\)/
66
+
67
+ attr_reader :message, :pid, :type, :action, :runtime, :original_line
68
+
69
+ def initialize(line)
70
+ @original_line = line
71
+ match = line.match(FORMAT)
72
+ if !match
73
+ @type = :unknown
74
+ else
75
+ @message = match[:message]
76
+ @pid = match[:pid]
77
+
78
+ @type = case @message
79
+ when /\AStarted (GET|POST|PUT|DELETE)/
80
+ :started
81
+ when /\AProcessing by (\S+) as/
82
+ @action = $1
83
+ :processing
84
+ when /Completed \d{3} .* in (\d+\.\d+)ms/
85
+ @runtime = $1.to_f
86
+ :completed
87
+ else
88
+ :log
89
+ end
90
+ end
91
+ end
92
+ end
93
+ end
@@ -0,0 +1,12 @@
1
+ 2014-03-04 10:00:00.100 [INFO ] Started GET "/" for 127.0.0.1 at 2014-03-04 10:26:45 +0100 (pid:1)
2
+ 2014-03-04 10:00:00.100 [INFO ] Started GET "/123" for 127.0.0.1 at 2014-03-04 10:26:45 +0100 (pid:2)
3
+ 2014-03-04 10:00:00.200 [INFO ] Processing by BlogController#index as HTML (pid:1)
4
+ 2014-03-04 10:00:00.200 [INFO ] Processing by BlogController#show as HTML (pid:2)
5
+ 2014-03-04 10:00:00.300 [DEBUG ] We are probably serving up some blogs now. (pid:1)
6
+ 2014-03-04 10:00:00.300 [DEBUG ] Serving the single blog alright (pid:2)
7
+ 2014-03-04 10:00:00.400 [INFO ] Completed 200 OK in 100.2ms (pid:1)
8
+ 2014-03-04 10:00:00.400 [INFO ] Completed 200 OK in 200.18ms (pid:2)
9
+ 2014-03-04 10:00:00.100 [INFO ] Started GET "/" for 127.0.0.1 at 2014-03-04 10:26:45 +0100 (pid:1)
10
+ 2014-03-04 10:00:00.200 [INFO ] Processing by BlogController#index as HTML (pid:1)
11
+ 2014-03-04 10:00:00.300 [DEBUG ] We are probably serving up some blogs now. (pid:1)
12
+ 2014-03-04 10:00:00.400 [INFO ] Completed 200 OK in 300.3ms (pid:1)
@@ -0,0 +1,3 @@
1
+ require "rails-log-sorter"
2
+ require "minitest/unit"
3
+ require "minitest/autorun"
@@ -0,0 +1,50 @@
1
+ require "test_helper"
2
+
3
+ class TestLine < MiniTest::Unit::TestCase
4
+ include RailsLogSorter
5
+
6
+ def test_started_line
7
+ line = Line.new('2014-03-04 10:00:00.100 [INFO ] Started GET "/" (pid:1)')
8
+
9
+ assert_equal 'Started GET "/"', line.message
10
+ assert_equal '1', line.pid
11
+ assert_equal :started, line.type
12
+ end
13
+
14
+ def test_processing_line
15
+ line = Line.new('2014-03-04 10:00:00.100 [INFO ] Processing by FooController#index as HTML (pid:1)')
16
+
17
+ assert_equal '1', line.pid
18
+ assert_equal :processing, line.type
19
+ assert_equal "FooController#index", line.action
20
+ end
21
+
22
+ def test_completed_line
23
+ line = Line.new('2014-03-04 10:00:00.100 [INFO ] Completed 200 OK in 50.1ms (pid:1)')
24
+
25
+ assert_equal '1', line.pid
26
+ assert_equal :completed, line.type
27
+ assert_equal 50.1, line.runtime
28
+ end
29
+
30
+ def test_completed_line_with_breakdown
31
+ line = Line.new('2014-03-04 10:26:47.736 [INFO ] Completed 200 OK in 1837.5ms (Views: 1808.8ms | ActiveRecord: 5.1ms) (pid:18269)')
32
+
33
+ assert_equal '18269', line.pid
34
+ assert_equal :completed, line.type
35
+ assert_equal 1837.5, line.runtime
36
+ end
37
+
38
+ def test_log_line
39
+ line = Line.new('2014-03-04 10:00:00.100 [INFO ] This is a log (pid:1)')
40
+
41
+ assert_equal '1', line.pid
42
+ assert_equal :log, line.type
43
+ end
44
+
45
+ def test_unknown_line
46
+ line = Line.new('Connecting to database')
47
+
48
+ assert_equal :unknown, line.type
49
+ end
50
+ end
@@ -0,0 +1,32 @@
1
+ require "test_helper"
2
+
3
+ class TestLog < MiniTest::Unit::TestCase
4
+ include RailsLogSorter
5
+
6
+ def test_parsing_log_file
7
+ log = Log.new_with_file("test/example.log")
8
+
9
+ r1 = log.requests[0]
10
+ assert_equal "BlogController#index", r1.action
11
+ assert_equal 100.2, r1.runtime
12
+
13
+ r2 = log.requests[1]
14
+ assert_equal "BlogController#show", r2.action
15
+ assert_equal 200.18, r2.runtime
16
+
17
+ r3 = log.requests[2]
18
+ assert_equal "BlogController#index", r3.action
19
+ assert_equal 300.3, r3.runtime
20
+ end
21
+
22
+ def test_find_slowest
23
+ log = Log.new_with_file("test/example.log")
24
+
25
+ slow = log.find_slowest("BlogController#index")
26
+
27
+ assert_equal 2, slow.size
28
+
29
+ assert_equal 300.3, slow[0].runtime
30
+ assert_equal 100.2, slow[1].runtime
31
+ end
32
+ end
metadata ADDED
@@ -0,0 +1,57 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: rails-log-sorter
3
+ version: !ruby/object:Gem::Version
4
+ version: '0.1'
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Harry Vangberg
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2014-04-15 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Sort log files
15
+ email:
16
+ - hv@firmafon.dk
17
+ executables:
18
+ - rails-log-sorter
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/rails-log-sorter.rb
23
+ - test/test_helper.rb
24
+ - test/test_log.rb
25
+ - test/example.log
26
+ - test/test_line.rb
27
+ - bin/rails-log-sorter
28
+ homepage: https://github.com/firmafon/rails-log-sorter
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.23
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: Sort log files
52
+ test_files:
53
+ - test/test_helper.rb
54
+ - test/test_log.rb
55
+ - test/example.log
56
+ - test/test_line.rb
57
+ has_rdoc: