ntail 0.0.11 → 0.0.12
Sign up to get free protection for your applications and to get access to all the features.
- data/Gemfile +5 -0
- data/Gemfile.lock +37 -4
- data/README.md +158 -0
- data/Rakefile +24 -11
- data/VERSION +1 -1
- data/bin/ntail +1 -1
- data/lib/ntail/application.rb +74 -97
- data/lib/ntail/body_bytes_sent.rb +2 -2
- data/lib/ntail/formatting.rb +157 -44
- data/lib/ntail/formatting.treetop +44 -15
- data/lib/ntail/http_method.rb +2 -2
- data/lib/ntail/http_referer.rb +2 -2
- data/lib/ntail/http_user_agent.rb +3 -1
- data/lib/ntail/http_version.rb +20 -5
- data/lib/ntail/known_ip_addresses.rb +2 -2
- data/lib/ntail/local_ip_addresses.rb +2 -2
- data/lib/ntail/log_line.rb +90 -42
- data/lib/ntail/node.rb +3 -0
- data/lib/ntail/options.rb +82 -0
- data/lib/ntail/proxy_addresses.rb +2 -2
- data/lib/ntail/remote_addr.rb +2 -2
- data/lib/ntail/remote_user.rb +2 -2
- data/lib/ntail/request.rb +2 -2
- data/lib/ntail/status.rb +1 -1
- data/lib/ntail/time_local.rb +2 -2
- data/lib/ntail/uri.rb +8 -1
- data/lib/ntail.rb +18 -3
- data/ntail.gemspec +29 -6
- data/spec/application_spec.rb +23 -0
- data/spec/spec_helper.rb +9 -0
- data/test/helper.rb +4 -1
- data/test/ntail/test_formatting.rb +72 -0
- data/test/ntail/test_http_version.rb +36 -0
- data/test/ntail/test_log_line.rb +5 -4
- data/test/ntail/test_remote_addr.rb +25 -3
- data/test/test_ntail.rb +7 -0
- metadata +125 -43
- data/README.rdoc +0 -99
@@ -0,0 +1,72 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestFormatting < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "NginxTail::Formatting" do
|
6
|
+
|
7
|
+
should "correctly format remote_addr using the %a taken" do
|
8
|
+
remote_addr = random_ip_address
|
9
|
+
log_line = random_log_line(:remote_addr => remote_addr)
|
10
|
+
NginxTail::LogLine.format = "%a"
|
11
|
+
assert_equal "%15s" % remote_addr, log_line.to_s(:color => false)
|
12
|
+
end
|
13
|
+
|
14
|
+
should "correctly format remote_user using the %u taken" do
|
15
|
+
remote_user = 'me_myself_and_i'
|
16
|
+
log_line = random_log_line(:remote_user => remote_user)
|
17
|
+
NginxTail::LogLine.format = "%u"
|
18
|
+
assert_equal remote_user, log_line.to_s(:color => false)
|
19
|
+
end
|
20
|
+
|
21
|
+
should "correctly format time_local using the %t taken" do
|
22
|
+
time_local = '25/Feb/2011:07:53:29 +0000'
|
23
|
+
log_line = random_log_line(:time_local => time_local)
|
24
|
+
NginxTail::LogLine.format = "%t"
|
25
|
+
assert_equal '2011-02-25 07:53:29', log_line.to_s(:color => false)
|
26
|
+
end
|
27
|
+
|
28
|
+
should "correctly format request using the %r taken" do
|
29
|
+
request = 'GET / HTTP/1.1'
|
30
|
+
log_line = random_log_line(:request => request)
|
31
|
+
NginxTail::LogLine.format = "%r"
|
32
|
+
assert_equal 'GET /', log_line.to_s(:color => false)
|
33
|
+
end
|
34
|
+
|
35
|
+
should "correctly format status using the %s taken" do
|
36
|
+
status = '200'
|
37
|
+
log_line = random_log_line(:status => status)
|
38
|
+
NginxTail::LogLine.format = "%s"
|
39
|
+
assert_equal status, log_line.to_s(:color => false)
|
40
|
+
end
|
41
|
+
|
42
|
+
should "correctly format body_bytes_sent using the %b taken" do
|
43
|
+
body_bytes_sent = '31415'
|
44
|
+
log_line = random_log_line(:body_bytes_sent => body_bytes_sent)
|
45
|
+
NginxTail::LogLine.format = "%b"
|
46
|
+
assert_equal body_bytes_sent, log_line.to_s(:color => false)
|
47
|
+
end
|
48
|
+
|
49
|
+
should "correctly format http_referer using the %R taken" do
|
50
|
+
http_referer = 'http://www.google.com/search?q=ntail'
|
51
|
+
log_line = random_log_line(:http_referer => http_referer)
|
52
|
+
NginxTail::LogLine.format = "%R"
|
53
|
+
assert_equal 'www.google.com', log_line.to_s(:color => false)
|
54
|
+
end
|
55
|
+
|
56
|
+
should "correctly format http_user_agent using the %U taken" do
|
57
|
+
http_user_agent = 'Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_4; en-US) AppleWebKit/534.13 (KHTML, like Gecko) Chrome/9.0.597.102 Safari/534.13'
|
58
|
+
log_line = random_log_line(:http_user_agent => http_user_agent)
|
59
|
+
NginxTail::LogLine.format = "%U"
|
60
|
+
assert_equal '(Chrome, OS X 10.6)', log_line.to_s(:color => false)
|
61
|
+
end
|
62
|
+
|
63
|
+
# should "correctly format proxy_addresses using the %p taken" do
|
64
|
+
# proxy_addresses = '"127.0.0.1"'
|
65
|
+
# log_line = random_log_line(:proxy_addresses => proxy_addresses)
|
66
|
+
# NginxTail::LogLine.format = "%p"
|
67
|
+
# assert_equal proxy_addresses, log_line.to_s(:color => false)
|
68
|
+
# end
|
69
|
+
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class TestHttpVersion < Test::Unit::TestCase
|
4
|
+
|
5
|
+
context "ntail" do
|
6
|
+
|
7
|
+
should "correctly identify the HTTP version of the request" do
|
8
|
+
http_version = "HTTP/1.0"
|
9
|
+
# directly via the helper function
|
10
|
+
assert_equal http_version, NginxTail::LogLine.to_http_version_s(http_version)
|
11
|
+
# parsed from a raw log line
|
12
|
+
log_line = random_log_line(:http_version => http_version)
|
13
|
+
assert_equal http_version, log_line.to_http_version_s
|
14
|
+
end
|
15
|
+
|
16
|
+
should "correctly identify the major HTTP version" do
|
17
|
+
http_version = "HTTP/1.0"
|
18
|
+
# directly via the helper function
|
19
|
+
assert_equal "1", NginxTail::LogLine.to_http_version_s(http_version, :major)
|
20
|
+
# parsed from a raw log line
|
21
|
+
log_line = random_log_line(:http_version => http_version)
|
22
|
+
assert_equal "1", log_line.to_http_version_s(:major)
|
23
|
+
end
|
24
|
+
|
25
|
+
should "correctly identify the minor HTTP version" do
|
26
|
+
http_version = "HTTP/1.0"
|
27
|
+
# directly via the helper function
|
28
|
+
assert_equal "1", NginxTail::LogLine.to_http_version_s(http_version, :minor)
|
29
|
+
# parsed from a raw log line
|
30
|
+
log_line = random_log_line(:http_version => http_version)
|
31
|
+
assert_equal "1", log_line.to_http_version_s(:minor)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/test/ntail/test_log_line.rb
CHANGED
@@ -28,24 +28,25 @@ class TestLogLine < Test::Unit::TestCase
|
|
28
28
|
should "implement a getter method for each (sub-)component" do
|
29
29
|
(NginxTail::LogLine::COMPONENTS + NginxTail::LogLine::SUBCOMPONENTS).each do |component|
|
30
30
|
getter_method = component.to_s
|
31
|
-
assert NginxTail::LogLine.instance_methods.include?(getter_method), "getter '#{getter_method}' should exist"
|
31
|
+
assert NginxTail::LogLine.instance_methods.map(&:to_s).include?(getter_method), "getter '#{getter_method}' should exist"
|
32
32
|
end
|
33
33
|
end
|
34
34
|
|
35
35
|
should "NOT implement a setter method for any (sub-)component" do
|
36
36
|
(NginxTail::LogLine::COMPONENTS + NginxTail::LogLine::SUBCOMPONENTS).each do |component|
|
37
37
|
setter_method = component.to_s + "="
|
38
|
-
assert !NginxTail::LogLine.instance_methods.include?(setter_method), "setter '#{setter_method}' should NOT exist"
|
38
|
+
assert !NginxTail::LogLine.instance_methods.map(&:to_s).include?(setter_method), "setter '#{setter_method}' should NOT exist"
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
42
|
should "include an extension module for each (sub-)component" do
|
43
43
|
(NginxTail::LogLine::COMPONENTS + NginxTail::LogLine::SUBCOMPONENTS).each do |component|
|
44
|
-
ntail_module = NginxTail::
|
44
|
+
ntail_module = NginxTail::Inflections.component_to_ntail_module(component)
|
45
|
+
next unless ntail_module # e.g. some Apache components...
|
45
46
|
assert NginxTail::LogLine.included_modules.include?(ntail_module), "module '#{ntail_module.name}' should be included"
|
46
47
|
end
|
47
48
|
end
|
48
49
|
|
49
50
|
end
|
50
51
|
|
51
|
-
end
|
52
|
+
end
|
@@ -9,15 +9,36 @@ class TestRemoteAddr < Test::Unit::TestCase
|
|
9
9
|
@log_line = random_log_line(:remote_addr => @remote_addr)
|
10
10
|
end
|
11
11
|
|
12
|
+
#
|
13
|
+
# Note on the assertions in this unit test, which should read:
|
14
|
+
#
|
15
|
+
# assert_equal "www.example.com", to_host_s
|
16
|
+
# assert_equal "www.example.com", @log_line.to_host_s
|
17
|
+
#
|
18
|
+
# However, when the tests are run
|
19
|
+
# when not connected to a network
|
20
|
+
# the DNS lookup will fail, and:
|
21
|
+
#
|
22
|
+
# "192.0.32.10" => "192.0.32.10"
|
23
|
+
#
|
24
|
+
# instead of:
|
25
|
+
#
|
26
|
+
# "192.0.32.10" => "example.com"
|
27
|
+
#
|
28
|
+
# We could fix this by adding the corresponding entry to the
|
29
|
+
# local /etc/hosts file, or (arguably :-) with some mocking
|
30
|
+
#
|
31
|
+
|
12
32
|
should "convert the request's remote address into a host string" do
|
13
33
|
# directly via the helper function
|
14
34
|
to_host_s = NginxTail::LogLine.to_host_s(@remote_addr)
|
15
|
-
|
35
|
+
assert ["www.example.com", "192.0.32.10"].include? to_host_s
|
16
36
|
# parsed from a raw log line
|
17
|
-
|
37
|
+
assert ["www.example.com", "192.0.32.10"].include? @log_line.to_host_s
|
18
38
|
end
|
19
39
|
|
20
40
|
should "convert the request's remote address into a country string" do
|
41
|
+
return unless File.exists?('/usr/share/GeoIP/GeoIP.dat')
|
21
42
|
# directly via the helper function
|
22
43
|
to_country_s = NginxTail::LogLine.to_country_s(@remote_addr)
|
23
44
|
assert_equal "United States", to_country_s
|
@@ -26,6 +47,7 @@ class TestRemoteAddr < Test::Unit::TestCase
|
|
26
47
|
end
|
27
48
|
|
28
49
|
should "convert the request's remote address into a city string" do
|
50
|
+
return unless File.exists?('/usr/share/GeoIP/GeoIPCity.dat')
|
29
51
|
# directly via the helper function
|
30
52
|
to_city_s = NginxTail::LogLine.to_city_s(@remote_addr)
|
31
53
|
assert_equal "Marina Del Rey", to_city_s
|
@@ -35,4 +57,4 @@ class TestRemoteAddr < Test::Unit::TestCase
|
|
35
57
|
|
36
58
|
end
|
37
59
|
|
38
|
-
end
|
60
|
+
end
|
data/test/test_ntail.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require 'helper'
|
2
2
|
|
3
3
|
class TestNtail < Test::Unit::TestCase
|
4
|
+
|
4
5
|
should "have namespaced classes" do
|
5
6
|
assert_equal "constant", defined? NginxTail
|
6
7
|
assert NginxTail.is_a? Module
|
@@ -11,4 +12,10 @@ class TestNtail < Test::Unit::TestCase
|
|
11
12
|
assert_equal "constant", defined? NginxTail::Application
|
12
13
|
assert NginxTail::Application.is_a? Class
|
13
14
|
end
|
15
|
+
|
16
|
+
should "have namespaced modules" do
|
17
|
+
assert_equal "constant", defined? NginxTail::Inflections
|
18
|
+
assert NginxTail::Inflections.is_a? Module
|
19
|
+
end
|
20
|
+
|
14
21
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ntail
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
5
|
-
prerelease:
|
4
|
+
hash: 7
|
5
|
+
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 12
|
10
|
+
version: 0.0.12
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Peter Vandenberk
|
@@ -15,13 +15,12 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-
|
18
|
+
date: 2011-08-08 00:00:00 +01:00
|
19
19
|
default_executable: ntail
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
22
|
-
|
23
|
-
|
24
|
-
version_requirements: &id001 !ruby/object:Gem::Requirement
|
22
|
+
type: :runtime
|
23
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
24
|
none: false
|
26
25
|
requirements:
|
27
26
|
- - ">="
|
@@ -30,12 +29,12 @@ dependencies:
|
|
30
29
|
segments:
|
31
30
|
- 0
|
32
31
|
version: "0"
|
33
|
-
|
34
|
-
|
35
|
-
- !ruby/object:Gem::Dependency
|
32
|
+
name: rainbow
|
33
|
+
version_requirements: *id001
|
36
34
|
prerelease: false
|
37
|
-
|
38
|
-
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
type: :runtime
|
37
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
38
|
none: false
|
40
39
|
requirements:
|
41
40
|
- - ">="
|
@@ -44,12 +43,12 @@ dependencies:
|
|
44
43
|
segments:
|
45
44
|
- 0
|
46
45
|
version: "0"
|
47
|
-
|
48
|
-
|
49
|
-
- !ruby/object:Gem::Dependency
|
46
|
+
name: user-agent
|
47
|
+
version_requirements: *id002
|
50
48
|
prerelease: false
|
51
|
-
|
52
|
-
|
49
|
+
- !ruby/object:Gem::Dependency
|
50
|
+
type: :runtime
|
51
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
53
52
|
none: false
|
54
53
|
requirements:
|
55
54
|
- - ~>
|
@@ -60,12 +59,40 @@ dependencies:
|
|
60
59
|
- 4
|
61
60
|
- 9
|
62
61
|
version: 1.4.9
|
63
|
-
|
62
|
+
name: treetop
|
63
|
+
version_requirements: *id003
|
64
|
+
prerelease: false
|
65
|
+
- !ruby/object:Gem::Dependency
|
64
66
|
type: :runtime
|
67
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
68
|
+
none: false
|
69
|
+
requirements:
|
70
|
+
- - ">="
|
71
|
+
- !ruby/object:Gem::Version
|
72
|
+
hash: 3
|
73
|
+
segments:
|
74
|
+
- 0
|
75
|
+
version: "0"
|
76
|
+
name: sequel
|
77
|
+
version_requirements: *id004
|
78
|
+
prerelease: false
|
65
79
|
- !ruby/object:Gem::Dependency
|
80
|
+
type: :runtime
|
81
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
82
|
+
none: false
|
83
|
+
requirements:
|
84
|
+
- - ">="
|
85
|
+
- !ruby/object:Gem::Version
|
86
|
+
hash: 3
|
87
|
+
segments:
|
88
|
+
- 0
|
89
|
+
version: "0"
|
90
|
+
name: mongoid
|
91
|
+
version_requirements: *id005
|
66
92
|
prerelease: false
|
67
|
-
|
68
|
-
|
93
|
+
- !ruby/object:Gem::Dependency
|
94
|
+
type: :runtime
|
95
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
69
96
|
none: false
|
70
97
|
requirements:
|
71
98
|
- - ">="
|
@@ -74,12 +101,42 @@ dependencies:
|
|
74
101
|
segments:
|
75
102
|
- 0
|
76
103
|
version: "0"
|
77
|
-
|
104
|
+
name: sqlite3-ruby
|
105
|
+
version_requirements: *id006
|
106
|
+
prerelease: false
|
107
|
+
- !ruby/object:Gem::Dependency
|
78
108
|
type: :development
|
109
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
110
|
+
none: false
|
111
|
+
requirements:
|
112
|
+
- - ">="
|
113
|
+
- !ruby/object:Gem::Version
|
114
|
+
hash: 63
|
115
|
+
segments:
|
116
|
+
- 0
|
117
|
+
- 9
|
118
|
+
- 2
|
119
|
+
version: 0.9.2
|
120
|
+
name: rake
|
121
|
+
version_requirements: *id007
|
122
|
+
prerelease: false
|
79
123
|
- !ruby/object:Gem::Dependency
|
124
|
+
type: :development
|
125
|
+
requirement: &id008 !ruby/object:Gem::Requirement
|
126
|
+
none: false
|
127
|
+
requirements:
|
128
|
+
- - ">="
|
129
|
+
- !ruby/object:Gem::Version
|
130
|
+
hash: 3
|
131
|
+
segments:
|
132
|
+
- 0
|
133
|
+
version: "0"
|
134
|
+
name: shoulda
|
135
|
+
version_requirements: *id008
|
80
136
|
prerelease: false
|
81
|
-
|
82
|
-
|
137
|
+
- !ruby/object:Gem::Dependency
|
138
|
+
type: :development
|
139
|
+
requirement: &id009 !ruby/object:Gem::Requirement
|
83
140
|
none: false
|
84
141
|
requirements:
|
85
142
|
- - ~>
|
@@ -90,12 +147,12 @@ dependencies:
|
|
90
147
|
- 0
|
91
148
|
- 0
|
92
149
|
version: 1.0.0
|
93
|
-
|
94
|
-
|
95
|
-
- !ruby/object:Gem::Dependency
|
150
|
+
name: bundler
|
151
|
+
version_requirements: *id009
|
96
152
|
prerelease: false
|
97
|
-
|
98
|
-
|
153
|
+
- !ruby/object:Gem::Dependency
|
154
|
+
type: :development
|
155
|
+
requirement: &id010 !ruby/object:Gem::Requirement
|
99
156
|
none: false
|
100
157
|
requirements:
|
101
158
|
- - ~>
|
@@ -106,12 +163,12 @@ dependencies:
|
|
106
163
|
- 5
|
107
164
|
- 1
|
108
165
|
version: 1.5.1
|
109
|
-
|
110
|
-
|
111
|
-
- !ruby/object:Gem::Dependency
|
166
|
+
name: jeweler
|
167
|
+
version_requirements: *id010
|
112
168
|
prerelease: false
|
113
|
-
|
114
|
-
|
169
|
+
- !ruby/object:Gem::Dependency
|
170
|
+
type: :development
|
171
|
+
requirement: &id011 !ruby/object:Gem::Requirement
|
115
172
|
none: false
|
116
173
|
requirements:
|
117
174
|
- - ">="
|
@@ -120,12 +177,12 @@ dependencies:
|
|
120
177
|
segments:
|
121
178
|
- 0
|
122
179
|
version: "0"
|
123
|
-
|
124
|
-
|
125
|
-
- !ruby/object:Gem::Dependency
|
180
|
+
name: rcov
|
181
|
+
version_requirements: *id011
|
126
182
|
prerelease: false
|
127
|
-
|
128
|
-
|
183
|
+
- !ruby/object:Gem::Dependency
|
184
|
+
type: :development
|
185
|
+
requirement: &id012 !ruby/object:Gem::Requirement
|
129
186
|
none: false
|
130
187
|
requirements:
|
131
188
|
- - ">="
|
@@ -134,8 +191,24 @@ dependencies:
|
|
134
191
|
segments:
|
135
192
|
- 0
|
136
193
|
version: "0"
|
137
|
-
|
194
|
+
name: geoip
|
195
|
+
version_requirements: *id012
|
196
|
+
prerelease: false
|
197
|
+
- !ruby/object:Gem::Dependency
|
138
198
|
type: :development
|
199
|
+
requirement: &id013 !ruby/object:Gem::Requirement
|
200
|
+
none: false
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
hash: 9
|
205
|
+
segments:
|
206
|
+
- 2
|
207
|
+
- 5
|
208
|
+
version: "2.5"
|
209
|
+
name: rspec
|
210
|
+
version_requirements: *id013
|
211
|
+
prerelease: false
|
139
212
|
description: A tail(1)-like utility for nginx log files. It supports parsing, filtering and formatting individual log lines.
|
140
213
|
email: pvandenberk@mac.com
|
141
214
|
executables:
|
@@ -144,13 +217,13 @@ extensions: []
|
|
144
217
|
|
145
218
|
extra_rdoc_files:
|
146
219
|
- LICENSE.txt
|
147
|
-
- README.
|
220
|
+
- README.md
|
148
221
|
files:
|
149
222
|
- .document
|
150
223
|
- Gemfile
|
151
224
|
- Gemfile.lock
|
152
225
|
- LICENSE.txt
|
153
|
-
- README.
|
226
|
+
- README.md
|
154
227
|
- Rakefile
|
155
228
|
- VERSION
|
156
229
|
- bin/ntail
|
@@ -167,6 +240,7 @@ files:
|
|
167
240
|
- lib/ntail/local_ip_addresses.rb
|
168
241
|
- lib/ntail/log_line.rb
|
169
242
|
- lib/ntail/node.rb
|
243
|
+
- lib/ntail/options.rb
|
170
244
|
- lib/ntail/proxy_addresses.rb
|
171
245
|
- lib/ntail/remote_addr.rb
|
172
246
|
- lib/ntail/remote_user.rb
|
@@ -175,10 +249,14 @@ files:
|
|
175
249
|
- lib/ntail/time_local.rb
|
176
250
|
- lib/ntail/uri.rb
|
177
251
|
- ntail.gemspec
|
252
|
+
- spec/application_spec.rb
|
253
|
+
- spec/spec_helper.rb
|
178
254
|
- test/helper.rb
|
255
|
+
- test/ntail/test_formatting.rb
|
179
256
|
- test/ntail/test_http_method.rb
|
180
257
|
- test/ntail/test_http_referer.rb
|
181
258
|
- test/ntail/test_http_user_agent.rb
|
259
|
+
- test/ntail/test_http_version.rb
|
182
260
|
- test/ntail/test_known_ip_addresses.rb
|
183
261
|
- test/ntail/test_local_ip_addresses.rb
|
184
262
|
- test/ntail/test_log_line.rb
|
@@ -219,15 +297,19 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
219
297
|
requirements: []
|
220
298
|
|
221
299
|
rubyforge_project:
|
222
|
-
rubygems_version: 1.
|
300
|
+
rubygems_version: 1.5.2
|
223
301
|
signing_key:
|
224
302
|
specification_version: 3
|
225
303
|
summary: A tail(1)-like utility for nginx log files
|
226
304
|
test_files:
|
305
|
+
- spec/application_spec.rb
|
306
|
+
- spec/spec_helper.rb
|
227
307
|
- test/helper.rb
|
308
|
+
- test/ntail/test_formatting.rb
|
228
309
|
- test/ntail/test_http_method.rb
|
229
310
|
- test/ntail/test_http_referer.rb
|
230
311
|
- test/ntail/test_http_user_agent.rb
|
312
|
+
- test/ntail/test_http_version.rb
|
231
313
|
- test/ntail/test_known_ip_addresses.rb
|
232
314
|
- test/ntail/test_local_ip_addresses.rb
|
233
315
|
- test/ntail/test_log_line.rb
|
data/README.rdoc
DELETED
@@ -1,99 +0,0 @@
|
|
1
|
-
= ntail
|
2
|
-
|
3
|
-
A <tt>tail(1)</tt>-like utility for nginx log files that supports parsing, filtering and formatting of individual
|
4
|
-
log lines (in nginx's so-called {"combined" log format}[http://wiki.nginx.org/NginxHttpLogModule#log_format]).
|
5
|
-
|
6
|
-
== Installation
|
7
|
-
|
8
|
-
Installing the gem also installs the <tt>ntail</tt> executable, typically as <tt>/usr/bin/ntail</tt> or <tt>/usr/local/bin/ntail</tt>:
|
9
|
-
|
10
|
-
> gem install ntail
|
11
|
-
|
12
|
-
To ensure easy execution of the <tt>ntail</tt> script, add the actual installation directory to your shell's <tt>$PATH</tt> variable.
|
13
|
-
|
14
|
-
== Basic Usage
|
15
|
-
|
16
|
-
* process an entire nginx log file and print each parsed and formatted line to STDOUT
|
17
|
-
|
18
|
-
> ntail /var/log/nginx/access.log
|
19
|
-
|
20
|
-
* tail an "active" nginx log file and print each new line to STDOUT <em>(stop with ^C)</em>
|
21
|
-
|
22
|
-
> tail -f /var/log/nginx/access.log | ntail
|
23
|
-
|
24
|
-
== Advanced Examples
|
25
|
-
|
26
|
-
* read from STDIN and print each line to STDOUT <em>(stop with ^D)</em>
|
27
|
-
|
28
|
-
> ntail
|
29
|
-
|
30
|
-
* read from STDIN and print out the length of each line <em>(to illustrate -e option)</em>
|
31
|
-
|
32
|
-
> ntail -e '{ |line| puts line.size }'
|
33
|
-
|
34
|
-
* read from STDIN but only print out non-empty lines <em>(to illustrate -f option)</em>
|
35
|
-
|
36
|
-
> ntail -f '{ |line| line.size > 0 }'
|
37
|
-
|
38
|
-
* the following invocations behave exactly the same <em>(to illustrate -e and -f options)</em>
|
39
|
-
|
40
|
-
> ntail
|
41
|
-
> ntail -f '{ |line| true }' -e '{ |line| puts line }'
|
42
|
-
|
43
|
-
* print out all HTTP requests that are coming from a given IP address
|
44
|
-
|
45
|
-
> ntail -f '{ |line| line.remote_address == "208.67.222.222" }' /var/log/nginx/access.log
|
46
|
-
|
47
|
-
* find all HTTP requests that resulted in a '5xx' HTTP error/status code <em>(e.g. Rails 500 errors)</em>
|
48
|
-
|
49
|
-
> gunzip -S .gz -c access.log-20101216.gz | ntail -f '{ |line| line.server_error_status? }'
|
50
|
-
|
51
|
-
* generate a summary report of HTTP status codes, for all non-200 HTTP requests
|
52
|
-
|
53
|
-
> ntail -f '{ |line| line.status != "200" }' -e '{ |line| puts line.status }' access.log | sort | uniq -c
|
54
|
-
76 301
|
55
|
-
16 302
|
56
|
-
2 304
|
57
|
-
1 406
|
58
|
-
|
59
|
-
* print out GeoIP country and city information for each HTTP request <em>(depends on the optional <tt>geoip</tt> gem)</em>
|
60
|
-
|
61
|
-
> ntail -e '{ |line| puts [line.to_country_s, line.to_city_s].join("\t") }' /var/log/nginx/access.log
|
62
|
-
United States Los Angeles
|
63
|
-
United States Houston
|
64
|
-
Germany Berlin
|
65
|
-
United Kingdom London
|
66
|
-
|
67
|
-
* print out the IP address and the corresponding host name for each HTTP request <em>(slows things down considerably, due to <tt>nslookup</tt> call)</em>
|
68
|
-
|
69
|
-
> ntail -e '{ |line| puts [line.remote_address, line.to_host_name].join("\t") }' /var/log/nginx/access.log
|
70
|
-
66.249.72.196 crawl-66-249-72-196.googlebot.com
|
71
|
-
67.192.120.134 s402.pingdom.com
|
72
|
-
75.31.109.144 adsl-75-31-109-144.dsl.irvnca.sbcglobal.net
|
73
|
-
|
74
|
-
== TODO
|
75
|
-
|
76
|
-
* implement a native <tt>"-f"</tt> option for ntail, similar to that of <tt>tail(1)</tt>, using e.g. flori's {file-tail gem}[https://github.com/flori/file-tail]
|
77
|
-
* implement a <tt>"-i"</tt> option ("ignore exceptions"/"continue processing"), if handling a single line raises an exception
|
78
|
-
* or indeed a reverse <tt>"-r"</tt> option ("re-raise exception"), to immediately stop processing and raising the exception for investigation
|
79
|
-
* implement (better) support for custom nginx log formats, in addition to {nginx's default "combined" log format}[http://wiki.nginx.org/NginxHttpLogModule#log_format].
|
80
|
-
|
81
|
-
== Acknowledgements
|
82
|
-
|
83
|
-
* ntail's parsing feature is inspired by an nginx log parser written by {Richard Taylor (moomerman)}[https://github.com/moomerman]
|
84
|
-
* parsing and expanding ntail's formatting string is done using nathansobo's quite brilliant {treetop gem}[https://github.com/nathansobo/treetop]
|
85
|
-
|
86
|
-
== Contributing to ntail
|
87
|
-
|
88
|
-
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
89
|
-
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
90
|
-
* Fork the project
|
91
|
-
* Start a feature/bugfix branch
|
92
|
-
* Commit and push until you are happy with your contribution
|
93
|
-
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
94
|
-
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
95
|
-
|
96
|
-
== Copyright
|
97
|
-
|
98
|
-
Copyright (c) 2011 Peter Vandenberk. See LICENSE.txt for further details.
|
99
|
-
|