chainsaw 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE +1 -1
- data/README.md +16 -1
- data/Rakefile +2 -0
- data/lib/chainsaw/core_extensions.rb +9 -0
- data/lib/chainsaw/detector.rb +63 -70
- data/lib/chainsaw/format.rb +5 -1
- data/lib/chainsaw/version.rb +1 -1
- data/lib/chainsaw.rb +1 -0
- data/test/detector_test.rb +12 -12
- metadata +8 -7
data/LICENSE
CHANGED
data/README.md
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
# Chainsaw
|
2
2
|
|
3
|
-
Parses a log file and returns lines matching the time period provided.
|
3
|
+
Parses a log file and returns lines matching the time period provided. Chainsaw tries to be smart about determining the log format and parsing it accordingly. See the list of currently supported formats below.
|
4
4
|
|
5
5
|
Chronic is used to parse the time strings, so any format chronic
|
6
6
|
supports, chainsaw supports. A list of supported formats can
|
@@ -47,6 +47,21 @@ If you want to print a line and wait for input (press return) before moving to t
|
|
47
47
|
Chainsaw will output the found log lines to a file on the system if you specify with `-o FILENAME`.
|
48
48
|
|
49
49
|
> chainsaw access.log yesterday -o yesterday.log
|
50
|
+
|
51
|
+
## Supported log formats (we think)
|
52
|
+
|
53
|
+
* syslog
|
54
|
+
* apache/nginx access (CLF)
|
55
|
+
* apache error
|
56
|
+
* nginx error
|
57
|
+
* rack
|
58
|
+
* rails
|
59
|
+
* django
|
60
|
+
* mongodb
|
61
|
+
* redis
|
62
|
+
* puppet
|
63
|
+
* python logger
|
64
|
+
* ruby logger
|
50
65
|
|
51
66
|
## Contributing
|
52
67
|
|
data/Rakefile
CHANGED
data/lib/chainsaw/detector.rb
CHANGED
@@ -1,90 +1,83 @@
|
|
1
1
|
module Chainsaw
|
2
2
|
class Detector
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
3
|
+
PATTERNS = {
|
4
|
+
:clf => {
|
5
|
+
:pattern => /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} (?:-|[^ ]+) (?:-|[^ ]+) \[(\d{2}\/[a-z]{3}\/\d{4}:\d{2}:\d{2}:\d{2} -\d{4})\]/i,
|
6
|
+
:time_format => '%d/%b/%Y:%H:%M:%S %z'
|
7
|
+
},
|
8
|
+
:apache_error => {
|
9
|
+
:pattern => /^\[([a-z]{3} [a-z]{3} \d{2} \d{2}:\d{2}:\d{2} \d{4})\]/i,
|
10
|
+
:time_format => '%a %b %d %H:%M:%S %Y'
|
11
|
+
},
|
12
|
+
:nginx_error => {
|
13
|
+
:pattern => /^(\d{4}\/\d{2}\/\d{2} \d{2}:\d{2}:\d{2})/i,
|
14
|
+
:time_format => '%Y/%m/%d %H:%M:%S'
|
15
|
+
},
|
16
|
+
:ruby_logger => {
|
17
|
+
:pattern => /^[a-z]{1}, \[(\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2})\.\d+ #\d+\]/i,
|
18
|
+
:time_format => '%Y-%m-%dT%H:%M:%S'
|
19
|
+
},
|
20
|
+
:rails => {
|
21
|
+
:pattern => /^started [a-z]+ "[^"]+" for \d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} at (\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} -\d{4})/i,
|
22
|
+
:time_format => '%Y-%m-%d %H:%M:%S %z'
|
23
|
+
},
|
24
|
+
:syslog => {
|
25
|
+
:pattern => /^([a-z]{3} ?\d{1,2} \d{2}:\d{2}:\d{2})/i,
|
26
|
+
:time_format => '%b %e %H:%M:%S'
|
27
|
+
},
|
28
|
+
:redis => {
|
29
|
+
:pattern => /^\[\d+\] ?(\d{1,2} [a-z]{3} \d{2}:\d{2}:\d{2})/i,
|
30
|
+
:time_format => '%e %b %H:%M:%S'
|
31
|
+
},
|
32
|
+
:puppet => {
|
33
|
+
:pattern => /^\[(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})\]/i,
|
34
|
+
:time_format => '%Y-%m-%d %H:%M:%S'
|
35
|
+
},
|
36
|
+
:mongodb => {
|
37
|
+
:pattern => /^(\w{3} \w{3} \d{2} \d{2}:\d{2}:\d{2})/i,
|
38
|
+
:time_format => '%a %b %d %H:%M:%S'
|
39
|
+
},
|
40
|
+
:rack => {
|
41
|
+
:pattern => /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3} (?:-|[^ ]+) (?:-|[^ ]+) \[(\d{2}\/[a-z]{3}\/\d{4} \d{2}:\d{2}:\d{2})\]/i,
|
42
|
+
:time_format => '%d/%b/%Y %H:%M:%S'
|
43
|
+
},
|
44
|
+
:python => {
|
45
|
+
:pattern => /^(\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2})/i,
|
46
|
+
:time_format => '%Y-%m-%d %H:%M:%S'
|
47
|
+
},
|
48
|
+
:django => {
|
49
|
+
:pattern => /^\[(\d{2}\/[a-z]{3}\/\d{4} \d{2}:\d{2}:\d{2})\]/i,
|
50
|
+
:time_format => '%d/%b/%Y %H:%M:%S'
|
51
|
+
}
|
52
|
+
}
|
16
53
|
|
17
54
|
def self.detect(log)
|
18
|
-
|
55
|
+
type = nil
|
19
56
|
|
20
57
|
log.each_line do |line|
|
21
|
-
|
22
|
-
break unless
|
58
|
+
type = _detect(line)
|
59
|
+
break unless type.nil?
|
23
60
|
end
|
24
61
|
|
25
|
-
if
|
62
|
+
if type.nil?
|
26
63
|
puts "\033[31mUnable to determine log format :(\033[0m"
|
27
64
|
exit
|
28
65
|
else
|
29
|
-
|
66
|
+
Format.new(type, PATTERNS[type])
|
30
67
|
end
|
31
68
|
end
|
32
69
|
|
33
70
|
def self._detect(line)
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
when APACHE_ERROR_PATTERN
|
42
|
-
format.type = 'apache_error'
|
43
|
-
format.time_format = '%a %b %d %H:%M:%S %Y'
|
44
|
-
format.pattern = APACHE_ERROR_PATTERN
|
45
|
-
when NGINX_ERROR_PATTERN
|
46
|
-
format.type = 'nginx_error'
|
47
|
-
format.time_format = '%Y/%m/%d %H:%M:%S'
|
48
|
-
format.pattern = NGINX_ERROR_PATTERN
|
49
|
-
when RUBY_LOGGER_PATTERN
|
50
|
-
format.type = 'ruby_logger'
|
51
|
-
format.time_format = '%Y-%m-%dT%H:%M:%S'
|
52
|
-
format.pattern = RUBY_LOGGER_PATTERN
|
53
|
-
when RAILS_PATTERN
|
54
|
-
format.type = 'rails'
|
55
|
-
format.time_format = '%Y-%m-%d %H:%M:%S %z'
|
56
|
-
format.pattern = RAILS_PATTERN
|
57
|
-
when SYSLOG_PATTERN
|
58
|
-
format.type = 'syslog'
|
59
|
-
format.time_format = '%b %e %H:%M:%S'
|
60
|
-
format.pattern = SYSLOG_PATTERN
|
61
|
-
when REDIS_PATTERN
|
62
|
-
format.type = 'redis'
|
63
|
-
format.time_format = '%e %b %H:%M:%S'
|
64
|
-
format.pattern = REDIS_PATTERN
|
65
|
-
when PUPPET_PATTERN
|
66
|
-
format.type = 'puppet'
|
67
|
-
format.time_format = '%Y-%m-%d %H:%M:%S'
|
68
|
-
format.pattern = PUPPET_PATTERN
|
69
|
-
when MONGODB_PATTERN
|
70
|
-
format.type = 'mongodb'
|
71
|
-
format.time_format = '%a %b %d %H:%M:%S'
|
72
|
-
format.pattern = MONGODB_PATTERN
|
73
|
-
when RACK_PATTERN
|
74
|
-
format.type = 'rack'
|
75
|
-
format.time_format = '%d/%b/%Y %H:%M:%S'
|
76
|
-
format.pattern = RACK_PATTERN
|
77
|
-
when PYTHON_PATTERN
|
78
|
-
format.type = 'python'
|
79
|
-
format.time_format = '%Y-%m-%d %H:%M:%S'
|
80
|
-
format.pattern = PYTHON_PATTERN
|
81
|
-
when DJANGO_PATTERN
|
82
|
-
format.type = 'django'
|
83
|
-
format.time_format = '%d/%b/%Y %H:%M:%S'
|
84
|
-
format.pattern = DJANGO_PATTERN
|
71
|
+
type = nil
|
72
|
+
|
73
|
+
PATTERNS.each do |key, value|
|
74
|
+
if line.match(value[:pattern])
|
75
|
+
type = key
|
76
|
+
break
|
77
|
+
end
|
85
78
|
end
|
86
79
|
|
87
|
-
|
80
|
+
type
|
88
81
|
end
|
89
82
|
|
90
83
|
end
|
data/lib/chainsaw/format.rb
CHANGED
data/lib/chainsaw/version.rb
CHANGED
data/lib/chainsaw.rb
CHANGED
data/test/detector_test.rb
CHANGED
@@ -8,7 +8,7 @@ describe Chainsaw::Detector do
|
|
8
8
|
format = Detector.detect(line)
|
9
9
|
time = get_time(line, format)
|
10
10
|
|
11
|
-
format.type.must_equal
|
11
|
+
format.type.must_equal :clf
|
12
12
|
time.must_equal Time.local(2012, 8, 26, 7, 42, 20)
|
13
13
|
end
|
14
14
|
|
@@ -17,7 +17,7 @@ describe Chainsaw::Detector do
|
|
17
17
|
format = Detector.detect(line)
|
18
18
|
time = get_time(line, format)
|
19
19
|
|
20
|
-
format.type.must_equal
|
20
|
+
format.type.must_equal :apache_error
|
21
21
|
|
22
22
|
time.must_equal Time.local(2012, 8, 26, 7, 42, 20)
|
23
23
|
end
|
@@ -27,7 +27,7 @@ describe Chainsaw::Detector do
|
|
27
27
|
format = Detector.detect(line)
|
28
28
|
time = get_time(line, format)
|
29
29
|
|
30
|
-
format.type.must_equal
|
30
|
+
format.type.must_equal :nginx_error
|
31
31
|
time.must_equal Time.local(2012, 8, 29, 7, 48, 59)
|
32
32
|
end
|
33
33
|
|
@@ -36,7 +36,7 @@ describe Chainsaw::Detector do
|
|
36
36
|
format = Detector.detect(line)
|
37
37
|
time = get_time(line, format)
|
38
38
|
|
39
|
-
format.type.must_equal
|
39
|
+
format.type.must_equal :ruby_logger
|
40
40
|
time.must_equal Time.local(2012, 9, 1, 11, 21, 26)
|
41
41
|
end
|
42
42
|
|
@@ -45,7 +45,7 @@ describe Chainsaw::Detector do
|
|
45
45
|
format = Detector.detect(line)
|
46
46
|
time = get_time(line, format)
|
47
47
|
|
48
|
-
format.type.must_equal
|
48
|
+
format.type.must_equal :rails
|
49
49
|
time.must_equal Time.local(2012, 9, 1, 9, 34, 35)
|
50
50
|
end
|
51
51
|
|
@@ -55,7 +55,7 @@ describe Chainsaw::Detector do
|
|
55
55
|
time = get_time(line, format)
|
56
56
|
year = Time.now.year
|
57
57
|
|
58
|
-
format.type.must_equal
|
58
|
+
format.type.must_equal :syslog
|
59
59
|
time.must_equal Time.local(2012, 8, 1, 17, 36, 55)
|
60
60
|
end
|
61
61
|
|
@@ -64,7 +64,7 @@ describe Chainsaw::Detector do
|
|
64
64
|
format = Detector.detect(line)
|
65
65
|
time = get_time(line, format)
|
66
66
|
|
67
|
-
format.type.must_equal
|
67
|
+
format.type.must_equal :redis
|
68
68
|
time.must_equal Time.local(2012, 4, 12, 18, 43, 33)
|
69
69
|
end
|
70
70
|
|
@@ -73,7 +73,7 @@ describe Chainsaw::Detector do
|
|
73
73
|
format = Detector.detect(line)
|
74
74
|
time = get_time(line, format)
|
75
75
|
|
76
|
-
format.type.must_equal
|
76
|
+
format.type.must_equal :puppet
|
77
77
|
time.must_equal Time.local(2012, 02, 04, 04, 8, 52)
|
78
78
|
end
|
79
79
|
|
@@ -82,7 +82,7 @@ describe Chainsaw::Detector do
|
|
82
82
|
format = Detector.detect(line)
|
83
83
|
time = get_time(line, format)
|
84
84
|
|
85
|
-
format.type.must_equal
|
85
|
+
format.type.must_equal :mongodb
|
86
86
|
time.must_equal Time.local(2012, 8, 26, 7, 43, 54)
|
87
87
|
end
|
88
88
|
|
@@ -91,7 +91,7 @@ describe Chainsaw::Detector do
|
|
91
91
|
format = Detector.detect(line)
|
92
92
|
time = get_time(line, format)
|
93
93
|
|
94
|
-
format.type.must_equal
|
94
|
+
format.type.must_equal :rack
|
95
95
|
time.must_equal Time.local(2012, 9, 03, 22, 51, 16)
|
96
96
|
end
|
97
97
|
|
@@ -100,7 +100,7 @@ describe Chainsaw::Detector do
|
|
100
100
|
format = Detector.detect(line)
|
101
101
|
time = get_time(line, format)
|
102
102
|
|
103
|
-
format.type.must_equal
|
103
|
+
format.type.must_equal :python
|
104
104
|
time.must_equal Time.local(2010, 12, 12, 11, 41, 42)
|
105
105
|
end
|
106
106
|
|
@@ -109,7 +109,7 @@ describe Chainsaw::Detector do
|
|
109
109
|
format = Detector.detect(line)
|
110
110
|
time = get_time(line, format)
|
111
111
|
|
112
|
-
format.type.must_equal
|
112
|
+
format.type.must_equal :django
|
113
113
|
time.must_equal Time.local(2012, 9, 03, 21, 49, 47)
|
114
114
|
end
|
115
115
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: chainsaw
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -14,7 +14,7 @@ date: 2012-09-04 00:00:00.000000000 Z
|
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: chronic
|
17
|
-
requirement: &
|
17
|
+
requirement: &70185022060360 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ~>
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: 0.7.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *70185022060360
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: minitest
|
28
|
-
requirement: &
|
28
|
+
requirement: &70185022059220 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ~>
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: 3.0.0
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *70185022059220
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: mocha
|
39
|
-
requirement: &
|
39
|
+
requirement: &70185022058220 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ~>
|
@@ -44,7 +44,7 @@ dependencies:
|
|
44
44
|
version: 0.11.4
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *70185022058220
|
48
48
|
description: Filter logfiles based on a time range
|
49
49
|
email:
|
50
50
|
- tdunn13@gmail.com
|
@@ -62,6 +62,7 @@ files:
|
|
62
62
|
- chainsaw.gemspec
|
63
63
|
- lib/chainsaw.rb
|
64
64
|
- lib/chainsaw/cli.rb
|
65
|
+
- lib/chainsaw/core_extensions.rb
|
65
66
|
- lib/chainsaw/detector.rb
|
66
67
|
- lib/chainsaw/filter.rb
|
67
68
|
- lib/chainsaw/format.rb
|