lugg 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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 [![Build Status](https://secure.travis-ci.org/avdgaag/lugg.png?branch=master)](http://travis-ci.org/avdgaag/lugg) [![Code Climate](https://codeclimate.com/github/avdgaag/lugg.png)](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
|