log_query 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +5 -5
- data/bin/lq +24 -4
- data/lib/log_query/messages.rb +16 -0
- data/lib/log_query/messages/heroku_router.rb +5 -0
- data/lib/log_query/messages/heroku_web/rails.rb +44 -0
- data/lib/log_query/messages/message_type_matcher.rb +1 -1
- data/lib/log_query/screen.rb +40 -7
- data/lib/log_query/version.rb +1 -1
- data/log_query.gif +0 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6a5eace67508a8f9b304887399b8850934c394e
|
4
|
+
data.tar.gz: 40b0398eed248d957935748636fb9cbdb1b6b1a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1fea3044667c84a0d59691382da0216465d3738480cbd87bb5ab4929e238528e499d8fe378baaea9b4391f29edaa1790e0399a0bac08703249a465ef0c9cc276
|
7
|
+
data.tar.gz: 66ca2acebdd27e20842e861848dc2da2eb08fe5eb27d795d6a6513d29b9de801e9d57693f2c79cb5a706850fb14d21d8e791fa2a5d74211190e31cdfe250a816
|
data/README.md
CHANGED
@@ -1,8 +1,6 @@
|
|
1
1
|
# LogQuery
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
TODO: Delete this and the text above, and describe your gem
|
3
|
+
TODO: Add description
|
6
4
|
|
7
5
|
## Installation
|
8
6
|
|
@@ -16,13 +14,15 @@ And then execute:
|
|
16
14
|
|
17
15
|
$ bundle
|
18
16
|
|
19
|
-
Or install
|
17
|
+
Or install the binary as:
|
20
18
|
|
21
19
|
$ gem install log_query
|
22
20
|
|
23
21
|
## Usage
|
24
22
|
|
25
|
-
|
23
|
+
`heroku logs --tail -n 1500 | lq --group_by path --measure service --average --varience --percentile 99`
|
24
|
+
|
25
|
+
![log_query usage](/log_query.gif?raw=true)
|
26
26
|
|
27
27
|
## Development
|
28
28
|
|
data/bin/lq
CHANGED
@@ -16,6 +16,7 @@ global_option('-g', '--group_by ATTRIBUTE', 'Attribute to group by')
|
|
16
16
|
global_option('-m', '--measure ATTRIBUTE', 'Attribute to measure')
|
17
17
|
global_option('-a', '--average', 'Perform average')
|
18
18
|
global_option('-p', '--percentile NUMBER', Integer,'Find nth percentile')
|
19
|
+
global_option('-c', '--count', 'Count instances of attribute')
|
19
20
|
global_option('--variance', 'Perform variance')
|
20
21
|
|
21
22
|
default_command :run
|
@@ -26,16 +27,35 @@ command :run do |c|
|
|
26
27
|
screen = Screen.new
|
27
28
|
ARGF.each_line do |line|
|
28
29
|
entry = LogEntry.from_heroku_log_line(line)
|
29
|
-
|
30
|
+
message = entry.message
|
30
31
|
|
31
|
-
|
32
|
-
|
33
|
-
|
32
|
+
# check which type group_by is in
|
33
|
+
if options.group_by
|
34
|
+
unless Messages.class_from_attribute(options.group_by).detect { |klass| message.is_a?(klass) }
|
35
|
+
#screen.line("#{options.group_by} is not in #{message.class} with attributes #{message.class&.attributes}")
|
36
|
+
next
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# check which type measure is in
|
41
|
+
unless Messages.class_from_attribute(options.measure).detect { |klass| message.is_a?(klass) }
|
42
|
+
#screen.line("#{options.measure} is not in #{message.class} with attributes #{message.class&.attributes}")
|
43
|
+
next
|
44
|
+
end
|
45
|
+
|
46
|
+
entries << entry
|
47
|
+
|
48
|
+
data = entries.group_by { |e| e.message.send(options.group_by) } if options.group_by
|
49
|
+
data ||= { all: entries }
|
50
|
+
|
51
|
+
data.
|
52
|
+
map { |k, es| [k, DescriptiveStatistics::Stats.new(es.map { |e| e.message.send(options.measure) } )] }.
|
34
53
|
map do |k, stats|
|
35
54
|
line = "#{k}: "
|
36
55
|
line += "mean: #{stats.mean.round(2)} " if options.average
|
37
56
|
line += "variance: #{stats.variance.round(2)} " if options.variance
|
38
57
|
line += "#{options.percentile}th: #{stats.percentile(options.percentile).round(2)} " if options.percentile
|
58
|
+
line += "count: #{stats.number} " if options.count
|
39
59
|
screen.line(line)
|
40
60
|
end
|
41
61
|
|
data/lib/log_query/messages.rb
CHANGED
@@ -1,12 +1,28 @@
|
|
1
1
|
require_relative './messages/heroku_router'
|
2
|
+
require_relative './messages/heroku_web/rails'
|
2
3
|
|
3
4
|
module Messages
|
5
|
+
def self.class_from_attribute(attr)
|
6
|
+
[HerokuRouter, HerokuWeb::Rails].select do |klass|
|
7
|
+
klass.attributes.include?(attr.to_sym)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
4
11
|
def self.resolve_message(source, dyno)
|
5
12
|
case [source, dyno]
|
13
|
+
when HerokuWeb::Rails
|
14
|
+
HerokuWeb::Rails
|
6
15
|
when HerokuRouter
|
7
16
|
HerokuRouter
|
8
17
|
else
|
9
18
|
String
|
10
19
|
end
|
11
20
|
end
|
21
|
+
|
22
|
+
# A wrapper for native string class
|
23
|
+
class String < String
|
24
|
+
def self.attributes
|
25
|
+
[]
|
26
|
+
end
|
27
|
+
end
|
12
28
|
end
|
@@ -9,6 +9,10 @@ module Messages
|
|
9
9
|
ATTRIBUTES = [:sock, :at, :code, :desc, :method, :path, :host, :request_id, :fwd, :dyno, :connect, :service, :status, :bytes]
|
10
10
|
attr_accessor *ATTRIBUTES
|
11
11
|
|
12
|
+
def self.attributes
|
13
|
+
ATTRIBUTES
|
14
|
+
end
|
15
|
+
|
12
16
|
def initialize(message)
|
13
17
|
ATTRIBUTES.
|
14
18
|
select { |attr| message.include?(" #{attr}=") }.
|
@@ -22,6 +26,7 @@ module Messages
|
|
22
26
|
end
|
23
27
|
end
|
24
28
|
|
29
|
+
|
25
30
|
def parse_value(value, attribute)
|
26
31
|
case attribute
|
27
32
|
when :sock, :at, :code, :desc, :method, :host, :request_id, :fwd, :dyno, :status
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Messages
|
2
|
+
module HerokuWeb
|
3
|
+
# 2016-10-20T17:19:51.396574+00:00 app[web.1]: Started HEAD "/" for 127.0.0.1 at 2016-10-20 17:19:51 +0000
|
4
|
+
# 2016-10-20T17:19:51.508781+00:00 app[web.1]: Processing by HomeController#index as HTML
|
5
|
+
# 2016-10-20T17:19:51.575265+00:00 app[web.1]: Rendered home/index.html.erb (53.0ms)
|
6
|
+
# 2016-10-20T17:19:51.575470+00:00 app[web.1]: Completed 500 Internal Server Error in 67ms (ActiveRecord: 0.0ms)
|
7
|
+
class Rails < MessageTypeMatcher
|
8
|
+
source 'app'
|
9
|
+
dyno 'web.*'
|
10
|
+
|
11
|
+
ATTRIBUTES = {
|
12
|
+
method: /Started ([^\s]+)/,
|
13
|
+
route: /"([^"]+)"/,
|
14
|
+
ip_address: /for (([0-9]{1,3}\.){4})/,
|
15
|
+
timestamp: /at (.*)$/,
|
16
|
+
controller: /Processing by ([^\s]+)/,
|
17
|
+
format: /as (.*)$/,
|
18
|
+
template: /Rendered ([^\s]+)/,
|
19
|
+
render_time: /\(([0-9\.]+?)ms\)/,
|
20
|
+
status: /Completed ([^\s]+)/,
|
21
|
+
total_time: /in ([0-9\.]+)ms/,
|
22
|
+
active_record_time: /ActiveRecord: ([0-9\.])ms/
|
23
|
+
}
|
24
|
+
|
25
|
+
attr_accessor *(ATTRIBUTES.keys)
|
26
|
+
|
27
|
+
def self.attributes
|
28
|
+
ATTRIBUTES.keys
|
29
|
+
end
|
30
|
+
|
31
|
+
def initialize(message)
|
32
|
+
ATTRIBUTES.
|
33
|
+
select { |attr, regexp| message.match(regexp) }.
|
34
|
+
map do |attr, regexp|
|
35
|
+
value = message.match(regexp)[0]
|
36
|
+
value = Integer(value) rescue value
|
37
|
+
[attr, value]
|
38
|
+
end.each do |(key, value)|
|
39
|
+
instance_variable_set("@#{key}", value)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
data/lib/log_query/screen.rb
CHANGED
@@ -1,20 +1,53 @@
|
|
1
1
|
class Screen
|
2
2
|
def initialize
|
3
|
-
@
|
4
|
-
@
|
3
|
+
@old_lines = []
|
4
|
+
@new_lines = []
|
5
|
+
@current_line = 0
|
5
6
|
end
|
6
7
|
|
7
8
|
def line(value)
|
8
|
-
@
|
9
|
-
|
9
|
+
@new_lines << value
|
10
|
+
end
|
11
|
+
|
12
|
+
def move_to(row)
|
13
|
+
#puts "moving to #{row}"
|
14
|
+
#puts "current line #{@current_line}"
|
15
|
+
diff = row - @current_line
|
16
|
+
if diff > 0
|
17
|
+
#puts "moving down #{diff.abs}"
|
18
|
+
@buffer += "\e[#{diff.abs}B"
|
19
|
+
elsif diff < 0
|
20
|
+
#puts "moving up #{diff.abs}"
|
21
|
+
@buffer += "\e[#{diff.abs}A"
|
22
|
+
end
|
23
|
+
@current_line += diff
|
10
24
|
end
|
11
25
|
|
12
|
-
def
|
13
|
-
@buffer
|
14
|
-
|
26
|
+
def delete_current_line
|
27
|
+
@buffer += "\e[2K"
|
28
|
+
end
|
29
|
+
|
30
|
+
def print_line(line)
|
31
|
+
@buffer += "#{line}\n"
|
32
|
+
@current_line += 1
|
15
33
|
end
|
16
34
|
|
17
35
|
def draw
|
36
|
+
@buffer = ""
|
37
|
+
# pad line buffers
|
38
|
+
line_count = [@old_lines.size, @new_lines.size].max
|
39
|
+
@old_lines.fill(nil, @old_lines.size, line_count) if @old_lines.size < line_count
|
40
|
+
@new_lines.fill(nil, @new_lines.size, line_count) if @new_lines.size < line_count
|
41
|
+
|
42
|
+
@old_lines.zip(@new_lines).each_with_index do |(old, new), index|
|
43
|
+
if old != new
|
44
|
+
move_to(index)
|
45
|
+
delete_current_line
|
46
|
+
print_line(new)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
@old_lines = @new_lines
|
50
|
+
@new_lines = []
|
18
51
|
print @buffer
|
19
52
|
end
|
20
53
|
end
|
data/lib/log_query/version.rb
CHANGED
data/log_query.gif
ADDED
Binary file
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: log_query
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jasper Lyons
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2016-10-
|
11
|
+
date: 2016-10-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: descriptive_statistics
|
@@ -74,10 +74,12 @@ files:
|
|
74
74
|
- lib/log_query/log_entry.rb
|
75
75
|
- lib/log_query/messages.rb
|
76
76
|
- lib/log_query/messages/heroku_router.rb
|
77
|
+
- lib/log_query/messages/heroku_web/rails.rb
|
77
78
|
- lib/log_query/messages/message_type_matcher.rb
|
78
79
|
- lib/log_query/screen.rb
|
79
80
|
- lib/log_query/version.rb
|
80
81
|
- log_query.gemspec
|
82
|
+
- log_query.gif
|
81
83
|
homepage: https://github.com/releaseplatform/log_query
|
82
84
|
licenses:
|
83
85
|
- MIT
|