lugg 0.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +4 -0
- data/.rubocop.yml +36 -0
- data/.travis.yml +5 -0
- data/.yardopts +9 -0
- data/Gemfile +4 -0
- data/HISTORY.md +0 -0
- data/LICENSE +22 -0
- data/README.md +89 -0
- data/Rakefile +25 -0
- data/bin/lugg +4 -0
- data/lib/lugg/filter.rb +60 -0
- data/lib/lugg/request.rb +81 -0
- data/lib/lugg/request_matcher.rb +32 -0
- data/lib/lugg/runner.rb +150 -0
- data/lib/lugg/streamer.rb +31 -0
- data/lib/lugg/version.rb +3 -0
- data/lib/lugg.rb +44 -0
- data/lugg.gemspec +29 -0
- data/spec/fixtures/example.log +10006 -0
- data/spec/lugg/filter_spec.rb +36 -0
- data/spec/lugg/request_matcher_spec.rb +37 -0
- data/spec/lugg/request_spec.rb +36 -0
- data/spec/lugg/runner_spec.rb +71 -0
- data/spec/lugg/streamer_spec.rb +27 -0
- metadata +149 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 269ec3ed7cc8b001cb923289fcc45a991f1d6fbb
|
4
|
+
data.tar.gz: 9f34b5919963cfc7f972887ab416d6d1e21abf92
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 4c2a1b31b30905a76ce343f57510fa5373dfbe06c499b9819d57e7e40e90cf11eb3ea6f858eeb3390f3fabe8a92d466984b39e7bf5f6b9fbe3584d35678efbef
|
7
|
+
data.tar.gz: c673f9f5112bb7233ec78c882d913bbecbb7a5f425043ae5053eae42183d0930397469b0d411ef621ea6d47082b76143ed20f7f99a6ddba40c89526889b3ed0b
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
AllCops:
|
2
|
+
Includes:
|
3
|
+
- '**/*.gemspec'
|
4
|
+
- '**/Rakefile'
|
5
|
+
Excludes:
|
6
|
+
- 'bin/*'
|
7
|
+
|
8
|
+
SignalException:
|
9
|
+
EnforcedStyle: only_raise
|
10
|
+
|
11
|
+
SymbolArray:
|
12
|
+
Enabled: true
|
13
|
+
|
14
|
+
Documentation:
|
15
|
+
Exclude:
|
16
|
+
- spec/**/*.rb
|
17
|
+
- lib/lugg/version.rb
|
18
|
+
|
19
|
+
LineLength:
|
20
|
+
Exclude:
|
21
|
+
- spec/**/*.rb
|
22
|
+
- lib/lugg.rb
|
23
|
+
|
24
|
+
AndOr:
|
25
|
+
Enabled: false
|
26
|
+
|
27
|
+
ClassLength:
|
28
|
+
Exclude:
|
29
|
+
- lib/lugg/runner.rb
|
30
|
+
|
31
|
+
MethodLength:
|
32
|
+
Exclude:
|
33
|
+
- lib/lugg/runner.rb
|
34
|
+
|
35
|
+
DoubleNegation:
|
36
|
+
Enabled: false
|
data/.travis.yml
ADDED
data/.yardopts
ADDED
data/Gemfile
ADDED
data/HISTORY.md
ADDED
File without changes
|
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2014 Arjan van der Gaag
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,89 @@
|
|
1
|
+
# Lugg — query Rails log files [](http://travis-ci.org/avdgaag/lugg) [](https://codeclimate.com/github/avdgaag/lugg)
|
2
|
+
|
3
|
+
A tiny command line utility to search through Rails server log files and display
|
4
|
+
requests that meet certain criteria.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Lugg is distributed as a Ruby gem, which should be installed on most Macs and
|
9
|
+
Linux systems. Once you have ensured you have a working installation of Ruby
|
10
|
+
and Ruby gems, install the gem as follows from the command line:
|
11
|
+
|
12
|
+
$ gem install lugg
|
13
|
+
|
14
|
+
You can verify the gem has installed correctly by checking its version number:
|
15
|
+
|
16
|
+
$ lugg -v
|
17
|
+
|
18
|
+
If this generates an error, something has gone wrong. You should see something
|
19
|
+
along the lines of `lugg 1.0.0`.
|
20
|
+
|
21
|
+
## Usage
|
22
|
+
|
23
|
+
Lugg takes one or more files as arguments or input on STDIN and redirects that
|
24
|
+
content to STDOUT -- but not before applying some filters. Content will be
|
25
|
+
parsed as Rails server log files and only the entire log entries matching your
|
26
|
+
criteria are displayed.
|
27
|
+
|
28
|
+
You supply criteria by passing in command line options. You can see a full list
|
29
|
+
of accepted options by running `lugg -h`:
|
30
|
+
|
31
|
+
```
|
32
|
+
--and Combine previous and next clause with AND instead of OR
|
33
|
+
--get Limit to GET requests
|
34
|
+
--post Limit to POST requests
|
35
|
+
--put Limit to PUT requests
|
36
|
+
--delete Limit to DELETE requests
|
37
|
+
--head Limit to HEAD requests
|
38
|
+
--patch Limit to PATCH requests
|
39
|
+
-c, --controller CONTROLLER Limit to requests handled by CONTROLLER
|
40
|
+
-a, --action CONTROLLER_ACTION Limit to requests handled by CONTROLLER_ACTION
|
41
|
+
--json Limit to json requests
|
42
|
+
--html Limit to html requests
|
43
|
+
--xml Limit to xml requests
|
44
|
+
--csv Limit to csv requests
|
45
|
+
--pdf Limit to pdf requests
|
46
|
+
--js Limit to js requests
|
47
|
+
-f, --format FORMAT Limit to FORMAT requests
|
48
|
+
-s, --status CODE Limit requests with status code CODE
|
49
|
+
--since TIME Limit to requests made after TIME
|
50
|
+
--until TIME Limit to requests made before TIME
|
51
|
+
-d, --duration N Limit to requests longer than N ms
|
52
|
+
-u, --uri URI Limit to requests matching URI
|
53
|
+
-p, --param KEY=VAL Limit to requests with param KEY => VAL
|
54
|
+
|
55
|
+
-v, --version Display version number
|
56
|
+
-h, --help Display this message
|
57
|
+
```
|
58
|
+
|
59
|
+
Note that all conditions are combined with OR, but you can combine two
|
60
|
+
conditions with the `--and` flag.
|
61
|
+
|
62
|
+
### Documentation
|
63
|
+
|
64
|
+
See the inline [API docs](http://rubydoc.info/github/avdgaag/lugg/master/frames) for more information.
|
65
|
+
|
66
|
+
## Contributing
|
67
|
+
|
68
|
+
1. Fork it ( https://github.com/avdgaag/lugg/fork )
|
69
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
70
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
71
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
72
|
+
5. Create new Pull Request
|
73
|
+
|
74
|
+
### Issues
|
75
|
+
|
76
|
+
Please report any issues, defects or suggestions in the [Github issue
|
77
|
+
tracker](https://github.com/avdgaag/lugg/issues).
|
78
|
+
|
79
|
+
### What has changed?
|
80
|
+
|
81
|
+
See the [HISTORY](https://github.com/avdgaag/lugg/blob/master/HISTORY.md) file for a detailed changelog.
|
82
|
+
|
83
|
+
### Credits
|
84
|
+
|
85
|
+
Created by: Arjan van der Gaag
|
86
|
+
URL: [http://arjanvandergaag.nl](http://arjanvandergaag.nl)
|
87
|
+
Project homepage: [http://avdgaag.github.io/lugg](http://avdgaag.github.io/lugg)
|
88
|
+
Date: march 2014
|
89
|
+
License: [MIT-license](https://github.com/avdgaag/lugg/LICENSE) (same as Ruby)
|
data/Rakefile
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
desc 'Default: run specs.'
|
4
|
+
task default: %i[spec rubocop doc]
|
5
|
+
|
6
|
+
require 'rspec/core/rake_task'
|
7
|
+
desc 'Run specs'
|
8
|
+
RSpec::Core::RakeTask.new
|
9
|
+
|
10
|
+
require 'yard'
|
11
|
+
desc 'Generate API docs'
|
12
|
+
YARD::Rake::YardocTask.new :doc
|
13
|
+
|
14
|
+
require 'rubocop/rake_task'
|
15
|
+
desc 'Check source code against Ruby style guide'
|
16
|
+
Rubocop::RakeTask.new
|
17
|
+
|
18
|
+
desc 'Start Irb with Lugg pre-loaded'
|
19
|
+
task :console do
|
20
|
+
require 'irb'
|
21
|
+
require 'irb/completion'
|
22
|
+
require 'lugg'
|
23
|
+
ARGV.clear
|
24
|
+
IRB.start
|
25
|
+
end
|
data/bin/lugg
ADDED
data/lib/lugg/filter.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
module Lugg
|
2
|
+
# Apply a list of filters to an Enumerable object or an enumerator.
|
3
|
+
#
|
4
|
+
# This class is used to combine all the search queries into a single filter
|
5
|
+
# to process a collection with. Its input is expected to be a
|
6
|
+
# `Lugg::Streamer` enumerator, but it could be anything.
|
7
|
+
#
|
8
|
+
# By default, the collection will be passed through as-is, but you can add
|
9
|
+
# more conditions to limit the results with either callable objects (such as
|
10
|
+
# Procs) or with blocks.
|
11
|
+
#
|
12
|
+
# @example Using a proc
|
13
|
+
# filter = Filter.new
|
14
|
+
# filter.use ->(record) { record.method == 'GET' }
|
15
|
+
#
|
16
|
+
# @example Using a block
|
17
|
+
# filter = Filter.new
|
18
|
+
# filter.use { |record| record.code == 404 }
|
19
|
+
class Filter
|
20
|
+
def initialize
|
21
|
+
@conditions = []
|
22
|
+
end
|
23
|
+
|
24
|
+
# Apply all known conditions to `records`.
|
25
|
+
#
|
26
|
+
# @param [Enumerable] records
|
27
|
+
# @return [Enumerable] filtered records
|
28
|
+
def call(records)
|
29
|
+
return records unless @conditions.any?
|
30
|
+
records.select do |record|
|
31
|
+
matches?(record)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# Store a new condition to be used on the next invocation of {#call}.
|
36
|
+
#
|
37
|
+
# @param [#call] callable
|
38
|
+
# @raise ArgumentError when both a callable or block are given
|
39
|
+
# @raise ArgumentError when the given callable does not respond to #call
|
40
|
+
def use(callable = nil, &block)
|
41
|
+
unless block_given? ^ callable
|
42
|
+
raise ArgumentError, 'Supply either an argument or a block'
|
43
|
+
end
|
44
|
+
|
45
|
+
unless block_given? || callable.respond_to?(:call)
|
46
|
+
raise ArgumentError, 'Supply either a callable argument or a block'
|
47
|
+
end
|
48
|
+
|
49
|
+
@conditions << (block_given? ? block : callable)
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
def matches?(record)
|
55
|
+
@conditions.any? do |condition|
|
56
|
+
condition.call(record)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/lugg/request.rb
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'time'
|
2
|
+
|
3
|
+
module Lugg
|
4
|
+
# Request is a value object representing a single log entry from start to
|
5
|
+
# finish. Its value is the original source text from the log file, but it
|
6
|
+
# defines various reader methods to extract useful information from it.
|
7
|
+
#
|
8
|
+
# Note that a request is frozen once created. Two {Request} objects with
|
9
|
+
# the same source are considered equal.
|
10
|
+
#
|
11
|
+
# @todo optimise performance
|
12
|
+
class Request
|
13
|
+
attr_reader :source, :hash
|
14
|
+
|
15
|
+
def initialize(source)
|
16
|
+
@source = source
|
17
|
+
@hash = self.class.hash ^ source.hash
|
18
|
+
freeze
|
19
|
+
end
|
20
|
+
|
21
|
+
def eql?(other)
|
22
|
+
self.class == other.class && source == other.source
|
23
|
+
end
|
24
|
+
alias_method :==, :eql?
|
25
|
+
|
26
|
+
def method
|
27
|
+
source[/^Started ([A-Z]+)/, 1]
|
28
|
+
end
|
29
|
+
|
30
|
+
def controller
|
31
|
+
source[/^Processing by (\w+)#(\w+) as (\w+)$/, 1]
|
32
|
+
end
|
33
|
+
|
34
|
+
def action
|
35
|
+
source[/^Processing by (\w+)#(\w+) as (\w+)$/, 1] + '#' +
|
36
|
+
source[/^Processing by (\w+)#(\w+) as (\w+)$/, 2]
|
37
|
+
end
|
38
|
+
|
39
|
+
def format
|
40
|
+
source[/^Processing by (\w+)#(\w+) as (\w+)$/, 3]
|
41
|
+
end
|
42
|
+
|
43
|
+
def status
|
44
|
+
source[/^Completed (\d+) (\w+)/, 2]
|
45
|
+
end
|
46
|
+
|
47
|
+
def code
|
48
|
+
source[/^Completed (\d+) (\w+)/, 1].to_i
|
49
|
+
end
|
50
|
+
|
51
|
+
def ip
|
52
|
+
source[/^Started .* for ([0-9\.]+)/, 1]
|
53
|
+
end
|
54
|
+
|
55
|
+
def timestamp
|
56
|
+
Time.parse(source[/^Started .* at (.+)$/, 1])
|
57
|
+
end
|
58
|
+
|
59
|
+
def uri
|
60
|
+
source[/^Started \w+ "([^"]+)"/, 1]
|
61
|
+
end
|
62
|
+
|
63
|
+
def path
|
64
|
+
uri.split('?').first
|
65
|
+
end
|
66
|
+
|
67
|
+
def query
|
68
|
+
uri.split('?', 2).last
|
69
|
+
end
|
70
|
+
|
71
|
+
def duration
|
72
|
+
source[/^Completed .* in (\d+)ms/, 1].to_i
|
73
|
+
end
|
74
|
+
|
75
|
+
def params
|
76
|
+
params_string = source[/^ Parameters: (.+)$/, 1]
|
77
|
+
return {} unless params_string
|
78
|
+
eval(params_string) rescue {} # rubocop:disable Eval, RescueModifier
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Lugg
|
2
|
+
# RequestMatcher is a flip-flop conditional, that becomes true when compared
|
3
|
+
# to one condition, and then stays true until a new condition. It is used to
|
4
|
+
# match log entries in a log file, starting to match when encountering a line
|
5
|
+
# with `Starting...` and stopping to match when encountering a line with
|
6
|
+
# `Completed...`.
|
7
|
+
class RequestMatcher
|
8
|
+
def initialize
|
9
|
+
@active = false
|
10
|
+
@finished = false
|
11
|
+
end
|
12
|
+
|
13
|
+
def active?
|
14
|
+
!!@active
|
15
|
+
end
|
16
|
+
|
17
|
+
def finished?
|
18
|
+
!!@finished
|
19
|
+
end
|
20
|
+
|
21
|
+
def =~(line) # rubocop:disable OpMethod
|
22
|
+
if line =~ /^Started/
|
23
|
+
@active = true
|
24
|
+
elsif line =~ /^Completed/
|
25
|
+
@active = false
|
26
|
+
@finished = true
|
27
|
+
else
|
28
|
+
@active
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
data/lib/lugg/runner.rb
ADDED
@@ -0,0 +1,150 @@
|
|
1
|
+
require 'lugg/version'
|
2
|
+
require 'lugg/filter'
|
3
|
+
require 'lugg/streamer'
|
4
|
+
require 'optparse'
|
5
|
+
require 'optparse/time'
|
6
|
+
|
7
|
+
module Lugg
|
8
|
+
# The runner defines the command line interface for Lugg, using the other
|
9
|
+
# components and defining command line options and their implementations.
|
10
|
+
#
|
11
|
+
# When creating a Runner object, you pass it your option flags (typically
|
12
|
+
# `ARGV`). You can then apply its conditions to an IO object (typically
|
13
|
+
# `ARGF`).
|
14
|
+
#
|
15
|
+
# @todo extract conditions into individual objects.
|
16
|
+
class Runner
|
17
|
+
attr_reader :filter
|
18
|
+
private :filter
|
19
|
+
|
20
|
+
def initialize(flags = [], filter = Filter.new)
|
21
|
+
@filter = filter
|
22
|
+
reset
|
23
|
+
options.parse!(flags)
|
24
|
+
end
|
25
|
+
|
26
|
+
def run(io)
|
27
|
+
filter.call(Streamer.new(io).records).each do |request|
|
28
|
+
puts request.source
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
private
|
33
|
+
|
34
|
+
def reset
|
35
|
+
@combine = false
|
36
|
+
@last_block = nil
|
37
|
+
end
|
38
|
+
|
39
|
+
def combine_clauses?
|
40
|
+
@combine && @last_block
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_clause(&block)
|
44
|
+
if combine_clauses?
|
45
|
+
prev_block = @last_block
|
46
|
+
filter.use { |r| prev_block.call(r) && block.call(r) }
|
47
|
+
reset
|
48
|
+
else
|
49
|
+
filter.use(&block)
|
50
|
+
@last_block = block
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def options
|
55
|
+
@options ||= OptionParser.new do |o|
|
56
|
+
o.banner = <<-EOS
|
57
|
+
Usage: lugg [options] FILE
|
58
|
+
|
59
|
+
Parses log entries from FILE or STDIN and uses [options] to control what is
|
60
|
+
sent STDOUT.
|
61
|
+
EOS
|
62
|
+
o.separator ''
|
63
|
+
|
64
|
+
o.on '--and',
|
65
|
+
'Combine previous and next clause with AND instead of OR' do
|
66
|
+
@combine = true
|
67
|
+
end
|
68
|
+
|
69
|
+
%w(get post put delete head patch).each do |verb|
|
70
|
+
o.on "--#{verb}", "Limit to #{verb.upcase} requests" do
|
71
|
+
add_clause { |r| r.method == verb.upcase }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
o.on '-c',
|
76
|
+
'--controller CONTROLLER',
|
77
|
+
'Limit to requests handled by CONTROLLER' do |controller|
|
78
|
+
add_clause { |r| r.controller == controller }
|
79
|
+
end
|
80
|
+
|
81
|
+
o.on '-a',
|
82
|
+
'--action CONTROLLER_ACTION',
|
83
|
+
'Limit to requests handled by CONTROLLER_ACTION' do |ca|
|
84
|
+
add_clause { |r| r.action == ca }
|
85
|
+
end
|
86
|
+
|
87
|
+
%w(json html xml csv pdf js).each do |format|
|
88
|
+
o.on "--#{format}", "Limit to #{format} requests" do
|
89
|
+
add_clause { |r| r.format.downcase == format }
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
o.on '-f', '--format FORMAT', 'Limit to FORMAT requests' do |format|
|
94
|
+
add_clause { |r| r.format.downcase == format.downcase }
|
95
|
+
end
|
96
|
+
|
97
|
+
o.on '-s',
|
98
|
+
'--status CODE',
|
99
|
+
'Limit requests with status code CODE' do |code|
|
100
|
+
add_clause { |r| r.code == code }
|
101
|
+
end
|
102
|
+
|
103
|
+
o.on '--since TIME',
|
104
|
+
Time,
|
105
|
+
'Limit to requests made after TIME' do |time|
|
106
|
+
add_clause { |r| r.timestamp > time }
|
107
|
+
end
|
108
|
+
|
109
|
+
o.on '--until TIME',
|
110
|
+
Time,
|
111
|
+
'Limit to requests made before TIME' do |time|
|
112
|
+
add_clause { |r| r.timestamp < time }
|
113
|
+
end
|
114
|
+
|
115
|
+
o.on '-d',
|
116
|
+
'--duration N',
|
117
|
+
Integer,
|
118
|
+
'Limit to requests longer than N ms' do |n|
|
119
|
+
add_clause { |r| r.duration > n }
|
120
|
+
end
|
121
|
+
|
122
|
+
o.on '-u',
|
123
|
+
'--uri URI',
|
124
|
+
Regexp,
|
125
|
+
'Limit to requests matching URI' do |uri|
|
126
|
+
add_clause { |r| r.uri =~ uri }
|
127
|
+
end
|
128
|
+
|
129
|
+
o.on '-p',
|
130
|
+
'--param KEY=VAL',
|
131
|
+
'Limit to requests with param KEY => VAL' do |param|
|
132
|
+
key, value = param.split('=', 2)
|
133
|
+
add_clause { |r| r.params[key] == value }
|
134
|
+
end
|
135
|
+
|
136
|
+
o.separator ''
|
137
|
+
|
138
|
+
o.on_tail '-v', '--version', 'Display version number' do
|
139
|
+
puts Lugg::VERSION
|
140
|
+
exit
|
141
|
+
end
|
142
|
+
|
143
|
+
o.on_tail '-h', '--help', 'Display this message' do
|
144
|
+
puts o
|
145
|
+
exit
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
require 'lugg/request'
|
2
|
+
require 'lugg/request_matcher'
|
3
|
+
|
4
|
+
module Lugg
|
5
|
+
# The Streamer reads in content from an IO object and returns an Enumerator
|
6
|
+
# yielding {Request} objects.
|
7
|
+
class Streamer
|
8
|
+
attr_reader :io
|
9
|
+
private :io
|
10
|
+
|
11
|
+
def initialize(io)
|
12
|
+
@io = io
|
13
|
+
end
|
14
|
+
|
15
|
+
# @return [Enumerator]
|
16
|
+
def records # rubocop:disable MethodLength
|
17
|
+
Enumerator.new do |yielder|
|
18
|
+
buffer = ''
|
19
|
+
matcher = RequestMatcher.new
|
20
|
+
io.each do |line|
|
21
|
+
buffer << line if matcher =~ line
|
22
|
+
if matcher.finished?
|
23
|
+
yielder << Request.new(buffer)
|
24
|
+
matcher = RequestMatcher.new
|
25
|
+
buffer = ''
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
data/lib/lugg/version.rb
ADDED
data/lib/lugg.rb
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
require 'lugg/version'
|
2
|
+
require 'lugg/runner'
|
3
|
+
|
4
|
+
# A tiny command line utility to search through Rails server log files and
|
5
|
+
# display requests that meet certain criteria.
|
6
|
+
#
|
7
|
+
# Lugg takes one or more files as arguments or input on STDIN and redirects
|
8
|
+
# that content to STDOUT -- but not before applying some filters. Content will
|
9
|
+
# be parsed as Rails server log files and only the entire log entries matching
|
10
|
+
# your criteria are displayed.
|
11
|
+
#
|
12
|
+
# You supply criteria by passing in command line options. You can see a full
|
13
|
+
# list of accepted options by running `lugg -h`:
|
14
|
+
#
|
15
|
+
# --and Combine previous and next clause with AND instead of OR
|
16
|
+
# --get Limit to GET requests
|
17
|
+
# --post Limit to POST requests
|
18
|
+
# --put Limit to PUT requests
|
19
|
+
# --delete Limit to DELETE requests
|
20
|
+
# --head Limit to HEAD requests
|
21
|
+
# --patch Limit to PATCH requests
|
22
|
+
# -c, --controller CONTROLLER Limit to requests handled by CONTROLLER
|
23
|
+
# -a, --action CONTROLLER_ACTION Limit to requests handled by CONTROLLER_ACTION
|
24
|
+
# --json Limit to json requests
|
25
|
+
# --html Limit to html requests
|
26
|
+
# --xml Limit to xml requests
|
27
|
+
# --csv Limit to csv requests
|
28
|
+
# --pdf Limit to pdf requests
|
29
|
+
# --js Limit to js requests
|
30
|
+
# -f, --format FORMAT Limit to FORMAT requests
|
31
|
+
# -s, --status CODE Limit requests with status code CODE
|
32
|
+
# --since TIME Limit to requests made after TIME
|
33
|
+
# --until TIME Limit to requests made before TIME
|
34
|
+
# -d, --duration N Limit to requests longer than N ms
|
35
|
+
# -u, --uri URI Limit to requests matching URI
|
36
|
+
# -p, --param KEY=VAL Limit to requests with param KEY => VAL
|
37
|
+
#
|
38
|
+
# -v, --version Display version number
|
39
|
+
# -h, --help Display this message
|
40
|
+
#
|
41
|
+
# Note that all conditions are combined with OR, but you can combine two
|
42
|
+
# conditions with the `--and` flag.
|
43
|
+
module Lugg
|
44
|
+
end
|
data/lugg.gemspec
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'lugg/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = 'lugg'
|
8
|
+
spec.version = Lugg::VERSION
|
9
|
+
spec.authors = ['Arjan van der Gaag']
|
10
|
+
spec.email = ['arjan@kabisa.nl']
|
11
|
+
spec.summary = %q{Query Rails log files from the command line.}
|
12
|
+
spec.description = <<-EOS
|
13
|
+
A tiny command line utility to search through Rails server log files and
|
14
|
+
display requests that meet certain criteria.
|
15
|
+
EOS
|
16
|
+
spec.homepage = 'http://avdgaa.github.io/lugg'
|
17
|
+
spec.license = 'MIT'
|
18
|
+
|
19
|
+
spec.files = `git ls-files -z`.split("\x0")
|
20
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
21
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
22
|
+
spec.require_paths = ['lib']
|
23
|
+
|
24
|
+
spec.add_development_dependency 'bundler', '~> 1.5'
|
25
|
+
spec.add_development_dependency 'rake'
|
26
|
+
spec.add_development_dependency 'rspec'
|
27
|
+
spec.add_development_dependency 'yard'
|
28
|
+
spec.add_development_dependency 'rubocop'
|
29
|
+
end
|