nginx_utils 0.0.5 → 0.0.6
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.
- data/bin/nginx_utils +6 -0
- data/lib/nginx_utils/cli.rb +36 -0
- data/lib/nginx_utils/logreader.rb +2 -2
- data/lib/nginx_utils/logrotate.rb +67 -115
- data/lib/nginx_utils/version.rb +1 -1
- data/lib/nginx_utils.rb +2 -0
- data/nginx_utils.gemspec +1 -1
- data/spec/nginx_utils/cli_spec.rb +114 -0
- data/spec/nginx_utils/logreader_spec.rb +112 -107
- data/spec/nginx_utils/logrotate_spec.rb +272 -306
- data/spec/nginx_utils/status_spec.rb +13 -15
- data/spec/spec_helper.rb +0 -1
- metadata +23 -22
- data/bin/nginx_logrotate +0 -29
- data/bin/nginx_status +0 -35
data/bin/nginx_utils
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
module NginxUtils
|
4
|
+
class CLI < Thor
|
5
|
+
desc "status example.com", "Print status of Nginx"
|
6
|
+
long_desc <<-LONGDESC
|
7
|
+
`status` to view the status of Nginx.
|
8
|
+
LONGDESC
|
9
|
+
option :only_value, type: :boolean, desc: "print status value only."
|
10
|
+
def status(host="localhost")
|
11
|
+
result = NginxUtils::Status.get host: host
|
12
|
+
if options[:only_value]
|
13
|
+
puts result.values.join("\t")
|
14
|
+
else
|
15
|
+
puts "Active Connections: #{result[:active_connection]}"
|
16
|
+
puts "Accepts: #{result[:accepts]} Handled: #{result[:handled]} Requests: #{result[:requests]}"
|
17
|
+
puts "Reading: #{result[:reading]} Writing: #{result[:writing]} Waiting: #{result[:waiting]}"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
desc "logrotate -d", "Nginx logrotate"
|
22
|
+
long_desc <<-LONGDESC
|
23
|
+
`logrotate` will log rotation of Nginx.
|
24
|
+
LONGDESC
|
25
|
+
option :debug, type: :boolean, aliases: "-d", desc: "Debug mode. Run only log output to STDOUT."
|
26
|
+
option :script_log, desc: "Log file for script."
|
27
|
+
option :log_level, desc: "Log level of script log."
|
28
|
+
option :root_dir, desc: "Root directory of Nginx."
|
29
|
+
option :target_logs, desc: "Specify logs of target."
|
30
|
+
option :retention, desc: "Specify in days the retention period of log."
|
31
|
+
option :pid_file, desc: "PID file of Nginx"
|
32
|
+
def logrotate
|
33
|
+
NginxUtils::Logrotate.new(options).execute
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -5,7 +5,7 @@ module NginxUtils
|
|
5
5
|
include Enumerable
|
6
6
|
|
7
7
|
def initialize(log, options={})
|
8
|
-
@log = File.open(log
|
8
|
+
@log = File.open(log)
|
9
9
|
|
10
10
|
if options[:parser]
|
11
11
|
if options[:parser].is_a? Regexp
|
@@ -27,7 +27,7 @@ module NginxUtils
|
|
27
27
|
|
28
28
|
private
|
29
29
|
def parse(line)
|
30
|
-
case @format
|
30
|
+
case @format.to_sym
|
31
31
|
when :ltsv then
|
32
32
|
row = line.split("\t").map do |f|
|
33
33
|
c = f.split(":")
|
@@ -7,111 +7,16 @@ module NginxUtils
|
|
7
7
|
attr_accessor :delete_logs
|
8
8
|
|
9
9
|
def initialize(options={})
|
10
|
-
|
11
|
-
# debug: false => Not execute. Only output of logs to STDOUT.
|
12
|
-
# debug: true => Execute rotate logs Nginx. (default)
|
13
|
-
if options[:debug]
|
14
|
-
debug
|
15
|
-
else
|
16
|
-
@execute = true
|
17
|
-
|
18
|
-
# Script log file
|
19
|
-
# not specified => /tmp/nginx_rotate.log (default)
|
20
|
-
# script_log: false => Not output of logs.
|
21
|
-
# script_log: "/path/to/nginx_rotate.log" => /path/to/nginx_rotate.log
|
22
|
-
# script_log: STDOUT => STDOUT
|
23
|
-
set_logger options[:script_log]
|
24
|
-
|
25
|
-
# Script log level
|
26
|
-
# not specified => Logger::DEBUG (default)
|
27
|
-
# log_level: [:fatal|:error|:info|:warn]
|
28
|
-
set_log_level options[:log_level]
|
29
|
-
end
|
30
|
-
|
31
|
-
# Target logs
|
32
|
-
# Log of rename target is "#{root_dir}/**/#{target_logs}"
|
33
|
-
# Log of delete target is "#{root_dir}/**/#{target_logs}.*"
|
34
|
-
# Default parameters are as follows:
|
35
|
-
# - root_dir => /usr/local/nginx
|
36
|
-
# - target_logs => *.log
|
37
|
-
@root_dir = options[:root_dir] || "/usr/local/nginx"
|
38
|
-
@target_logs = options[:target_logs] || "*.log"
|
39
|
-
@rename_logs = Dir.glob(File.join(@root_dir, "**", @target_logs))
|
40
|
-
@delete_logs = Dir.glob(File.join(@root_dir, "**", "#{@target_logs}.*"))
|
41
|
-
|
42
|
-
# Rename prefix
|
43
|
-
# Log of rename target to add the prefix.
|
44
|
-
# File name of the renamed after: "#{filename}.#{prefix}"
|
45
|
-
# Current time default. (YYYYmmddHHMMSS)
|
46
|
-
@prefix = options[:prefix] || Time.now.strftime("%Y%m%d%H%M%S")
|
47
|
-
|
48
|
-
# Retention period
|
49
|
-
# Delete log last modification time has passed the retention period.
|
50
|
-
# Specified unit of day.
|
51
|
-
dates = options[:retention] || 90
|
52
|
-
@retention = Time.now - (dates.to_i * 3600 * 24)
|
53
|
-
|
54
|
-
# PID file of Nginx
|
55
|
-
# The default is "#{root_dir}/logs/nginx.pid".
|
56
|
-
@pid_file = options[:pid_file] || File.join(@root_dir, "logs", "nginx.pid")
|
10
|
+
configure(options)
|
57
11
|
end
|
58
12
|
|
59
13
|
def config(options={})
|
60
|
-
|
61
|
-
unless options[:debug].nil?
|
62
|
-
if options[:debug]
|
63
|
-
debug
|
64
|
-
else
|
65
|
-
debug false
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Script log file
|
70
|
-
unless options[:script_log].nil?
|
71
|
-
set_logger options[:script_log]
|
72
|
-
end
|
73
|
-
|
74
|
-
# Script log level
|
75
|
-
unless options[:log_level].nil?
|
76
|
-
set_log_level options[:log_level]
|
77
|
-
end
|
78
|
-
|
79
|
-
# Target logs
|
80
|
-
reglog = false
|
81
|
-
unless options[:root_dir].nil?
|
82
|
-
@root_dir = options[:root_dir]
|
83
|
-
reglob = true
|
84
|
-
end
|
85
|
-
|
86
|
-
unless options[:target_logs].nil?
|
87
|
-
@target_logs = options[:target_logs]
|
88
|
-
reglob = true
|
89
|
-
end
|
90
|
-
|
91
|
-
if reglob
|
92
|
-
@rename_logs = Dir.glob(File.join(@root_dir, "**", @target_logs))
|
93
|
-
@delete_logs = Dir.glob(File.join(@root_dir, "**", "#{@target_logs}.*"))
|
94
|
-
end
|
95
|
-
|
96
|
-
# Rename prefix
|
97
|
-
unless options[:prefix].nil?
|
98
|
-
@prefix = options[:prefix]
|
99
|
-
end
|
100
|
-
|
101
|
-
# Retention period
|
102
|
-
unless options[:retention].nil?
|
103
|
-
@retention = Time.now - (options[:retention].to_i * 3600 * 24)
|
104
|
-
end
|
105
|
-
|
106
|
-
# PID file of Nginx
|
107
|
-
unless options[:pid_file].nil?
|
108
|
-
@pid_file = options[:pid_file]
|
109
|
-
end
|
14
|
+
configure(options)
|
110
15
|
end
|
111
16
|
|
112
17
|
def rename
|
113
18
|
@rename_logs.each do |log|
|
114
|
-
after = "#{log}.#{@prefix}"
|
19
|
+
after = "#{log}.#{@params[:prefix]}"
|
115
20
|
if File.exists? after
|
116
21
|
@logger.warn "File already exists: #{after}" if @logger
|
117
22
|
else
|
@@ -122,8 +27,10 @@ module NginxUtils
|
|
122
27
|
end
|
123
28
|
|
124
29
|
def delete
|
30
|
+
retention_time = Time.now - (@params[:retention].to_i * 3600 * 24)
|
31
|
+
|
125
32
|
@delete_logs.each do |log|
|
126
|
-
if File.stat(log).mtime <
|
33
|
+
if File.stat(log).mtime < retention_time
|
127
34
|
File.unlink(log) if @execute
|
128
35
|
@logger.debug "Delete log file: #{log}" if @logger
|
129
36
|
end
|
@@ -131,19 +38,19 @@ module NginxUtils
|
|
131
38
|
end
|
132
39
|
|
133
40
|
def restart
|
134
|
-
if File.exists? @pid_file
|
135
|
-
cmd = "kill -USR1 `cat #{@pid_file}`"
|
136
|
-
@logger.debug "Nginx restart command: #{cmd}" if @logger
|
41
|
+
if File.exists? @params[:pid_file]
|
137
42
|
if @execute
|
138
|
-
|
43
|
+
begin
|
44
|
+
Process.kill(:USR1, File.read(@params[:pid_file]).to_i)
|
139
45
|
@logger.info "Nginx restart is successfully" if @logger
|
140
|
-
|
46
|
+
rescue => e
|
141
47
|
@logger.error "Nginx restart failed" if @logger
|
142
|
-
|
48
|
+
@logger.error e if @logger
|
49
|
+
raise "Nginx restart failed"
|
143
50
|
end
|
144
51
|
end
|
145
52
|
else
|
146
|
-
@logger.warn "Pid file is not found. Do not restart nginx.
|
53
|
+
@logger.warn "Pid file is not found. Do not restart nginx." if @logger
|
147
54
|
end
|
148
55
|
end
|
149
56
|
|
@@ -156,8 +63,48 @@ module NginxUtils
|
|
156
63
|
end
|
157
64
|
|
158
65
|
private
|
159
|
-
def
|
160
|
-
|
66
|
+
def configure(options)
|
67
|
+
options = options.inject({}){|r,(k,v)| r.store(k.to_sym, v); r}
|
68
|
+
if @params.nil?
|
69
|
+
first = true
|
70
|
+
@params = default_params.merge(options)
|
71
|
+
flags = @params.keys
|
72
|
+
else
|
73
|
+
first = false
|
74
|
+
flags = options.select{|k,v| @params[k] != v}.keys
|
75
|
+
@params.merge!(options)
|
76
|
+
end
|
77
|
+
|
78
|
+
reglob = false
|
79
|
+
|
80
|
+
flags.each do |key|
|
81
|
+
case key
|
82
|
+
when :debug then config_debug
|
83
|
+
when :script_log then config_logger
|
84
|
+
when :log_level then config_loglevel
|
85
|
+
when :root_dir then reglob = true
|
86
|
+
when :target_logs then reglob = true
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
reglob_logs if reglob
|
91
|
+
end
|
92
|
+
|
93
|
+
def default_params
|
94
|
+
{
|
95
|
+
debug: false,
|
96
|
+
script_log: "/tmp/nginx_rotate.log",
|
97
|
+
log_level: :debug,
|
98
|
+
root_dir: "/usr/local/nginx",
|
99
|
+
target_logs: "*.log",
|
100
|
+
prefix: Time.now.strftime("%Y%m%d%H%M%S"),
|
101
|
+
retention: 90,
|
102
|
+
pid_file: "/usr/local/nginx/logs/nginx.pid"
|
103
|
+
}
|
104
|
+
end
|
105
|
+
|
106
|
+
def config_debug
|
107
|
+
if @params[:debug]
|
161
108
|
@execute = false
|
162
109
|
@logger = Logger.new(STDOUT)
|
163
110
|
else
|
@@ -165,17 +112,17 @@ module NginxUtils
|
|
165
112
|
end
|
166
113
|
end
|
167
114
|
|
168
|
-
def
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
115
|
+
def config_logger
|
116
|
+
if @params[:script_log] == false
|
117
|
+
@logger = false
|
118
|
+
else
|
119
|
+
@logger = Logger.new(@params[:script_log])
|
173
120
|
end
|
174
121
|
end
|
175
122
|
|
176
|
-
def
|
123
|
+
def config_loglevel
|
177
124
|
if @logger
|
178
|
-
case
|
125
|
+
case @params[:log_level]
|
179
126
|
when :fatal then @logger.level = Logger::FATAL
|
180
127
|
when :error then @logger.level = Logger::ERROR
|
181
128
|
when :warn then @logger.level = Logger::WARN
|
@@ -185,5 +132,10 @@ module NginxUtils
|
|
185
132
|
end
|
186
133
|
end
|
187
134
|
end
|
135
|
+
|
136
|
+
def reglob_logs
|
137
|
+
@rename_logs = Dir.glob(File.join(@params[:root_dir], "**", @params[:target_logs]))
|
138
|
+
@delete_logs = Dir.glob(File.join(@params[:root_dir], "**", "#{@params[:target_logs]}.*"))
|
139
|
+
end
|
188
140
|
end
|
189
141
|
end
|
data/lib/nginx_utils/version.rb
CHANGED
data/lib/nginx_utils.rb
CHANGED
data/nginx_utils.gemspec
CHANGED
@@ -18,8 +18,8 @@ Gem::Specification.new do |spec|
|
|
18
18
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
19
|
spec.require_paths = ["lib"]
|
20
20
|
|
21
|
+
spec.add_dependency "thor"
|
21
22
|
spec.add_development_dependency "bundler", "~> 1.3"
|
22
23
|
spec.add_development_dependency "rake"
|
23
24
|
spec.add_development_dependency "rspec"
|
24
|
-
spec.add_development_dependency "fakefs"
|
25
25
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
|
3
|
+
require "spec_helper"
|
4
|
+
require "stringio"
|
5
|
+
|
6
|
+
describe "NginxUtils::CLI" do
|
7
|
+
def capture(stream)
|
8
|
+
begin
|
9
|
+
stream = stream.to_s
|
10
|
+
eval "$#{stream} = StringIO.new"
|
11
|
+
yield
|
12
|
+
result = eval("$#{stream}").string
|
13
|
+
ensure
|
14
|
+
eval("$#{stream} = #{stream.upcase}")
|
15
|
+
end
|
16
|
+
result
|
17
|
+
end
|
18
|
+
|
19
|
+
describe "#status" do
|
20
|
+
let(:result) {
|
21
|
+
{
|
22
|
+
active_connections: 1,
|
23
|
+
accepts: 4,
|
24
|
+
handled: 5,
|
25
|
+
requests: 51,
|
26
|
+
reading: 1,
|
27
|
+
writing: 3,
|
28
|
+
waiting: 2
|
29
|
+
}
|
30
|
+
}
|
31
|
+
|
32
|
+
before(:each) {NginxUtils::Status.should_receive(:get).and_return(result)}
|
33
|
+
|
34
|
+
it "default output" do
|
35
|
+
args = ["status"]
|
36
|
+
expect(
|
37
|
+
capture(:stdout) {
|
38
|
+
NginxUtils::CLI.start(args)
|
39
|
+
}
|
40
|
+
).to eq("Active Connections: \nAccepts: 4 Handled: 5 Requests: 51\nReading: 1 Writing: 3 Waiting: 2\n")
|
41
|
+
end
|
42
|
+
|
43
|
+
it "only value output" do
|
44
|
+
args = ["status", "--only_value"]
|
45
|
+
expect(
|
46
|
+
capture(:stdout) {
|
47
|
+
NginxUtils::CLI.start(args)
|
48
|
+
}
|
49
|
+
).to eq("1\t4\t5\t51\t1\t3\t2\n")
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
describe "#logrotate" do
|
54
|
+
before(:each) do
|
55
|
+
@rotate = double("lotate mock")
|
56
|
+
@rotate.should_receive(:execute).and_return(true)
|
57
|
+
end
|
58
|
+
|
59
|
+
it "logrotate should be execute" do
|
60
|
+
NginxUtils::Logrotate.should_receive(:new).and_return(@rotate)
|
61
|
+
args = ["logrotate"]
|
62
|
+
NginxUtils::CLI.start(args)
|
63
|
+
end
|
64
|
+
|
65
|
+
it "debug option" do
|
66
|
+
options = {"debug" => true}
|
67
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
68
|
+
args = ["logrotate", "-d"]
|
69
|
+
NginxUtils::CLI.start(args)
|
70
|
+
end
|
71
|
+
|
72
|
+
it "script_log option" do
|
73
|
+
options = {"script_log" => "/var/log/nginx_rotate.log"}
|
74
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
75
|
+
args = ["logrotate", "--script_log", "/var/log/nginx_rotate.log"]
|
76
|
+
NginxUtils::CLI.start(args)
|
77
|
+
end
|
78
|
+
|
79
|
+
it "log_level option" do
|
80
|
+
options = {"log_level" => "warn"}
|
81
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
82
|
+
args = ["logrotate", "--log_level", "warn"]
|
83
|
+
NginxUtils::CLI.start(args)
|
84
|
+
end
|
85
|
+
|
86
|
+
it "root_dir option" do
|
87
|
+
options = {"root_dir" => "/usr/local/nginx_other"}
|
88
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
89
|
+
args = ["logrotate", "--root_dir", "/usr/local/nginx_other"]
|
90
|
+
NginxUtils::CLI.start(args)
|
91
|
+
end
|
92
|
+
|
93
|
+
it "target_logs option" do
|
94
|
+
options = {"target_logs" => "*_log"}
|
95
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
96
|
+
args = ["logrotate", "--target_logs", "*_log"]
|
97
|
+
NginxUtils::CLI.start(args)
|
98
|
+
end
|
99
|
+
|
100
|
+
it "retention option" do
|
101
|
+
options = {"retention" => "30"}
|
102
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
103
|
+
args = ["logrotate", "--retention", "30"]
|
104
|
+
NginxUtils::CLI.start(args)
|
105
|
+
end
|
106
|
+
|
107
|
+
it "pid_file option" do
|
108
|
+
options = {"pid_file" => "/var/run/nginx.pid"}
|
109
|
+
NginxUtils::Logrotate.should_receive(:new).with(options).and_return(@rotate)
|
110
|
+
args = ["logrotate", "--pid_file", "/var/run/nginx.pid"]
|
111
|
+
NginxUtils::CLI.start(args)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
@@ -2,125 +2,130 @@
|
|
2
2
|
|
3
3
|
require "spec_helper"
|
4
4
|
|
5
|
-
describe NginxUtils do
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
FileUtils.mkdir_p log_dir
|
11
|
-
|
12
|
-
case format
|
13
|
-
when :ltsv then
|
14
|
-
line = "time:2013-05-19T08:13:14+00:00\thost:192.168.1.10\txff:-\tmethod:GET\tpath:/\tstatus:200\tua:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31\treq_size:124\treq_time:0.007\tres_size:239\tbody_size:11\tapp_time:-\n"
|
15
|
-
when :combined then
|
16
|
-
line = "192.168.1.10 - - [19/May/2013:23:14:04 +0900] \"GET / HTTP/1.1\" 200 239 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31\"\n"
|
17
|
-
else raise "format error"
|
18
|
-
end
|
19
|
-
|
20
|
-
File.open(File.join(log_dir, "access.log"), "w") do |f|
|
21
|
-
3.times {f.write line}
|
22
|
-
end
|
5
|
+
describe "NginxUtils::Logreader" do
|
6
|
+
let!(:io_mock) do
|
7
|
+
io = double("io mock").as_null_object
|
8
|
+
File.stub(:open).and_return(io)
|
9
|
+
io
|
23
10
|
end
|
24
11
|
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
end
|
12
|
+
let(:access_log) {"/usr/local/nginx/logs/access.log"}
|
13
|
+
let(:parser) {/([0-9.]+)\s-\s([^\s]+)\s\[(.*?)\]\s"(.*?)"\s([0-9]+)\s([0-9]+)\s"(.*?)"\s"(.*?)".*/}
|
14
|
+
let(:reader) {NginxUtils::Logreader.new(access_log)}
|
29
15
|
|
30
|
-
describe "
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
@reader = NginxUtils::Logreader.new(@log_file)
|
36
|
-
end
|
37
|
-
|
38
|
-
it "specified file should be opened" do
|
39
|
-
expect(@reader.instance_eval{@log}.path).to eq(@log_file)
|
40
|
-
end
|
41
|
-
|
42
|
-
it "default format should be ltsv" do
|
43
|
-
expect(@reader.instance_eval{@format}).to eq(:ltsv)
|
44
|
-
end
|
45
|
-
|
46
|
-
it "default parser should be nil" do
|
47
|
-
expect(@reader.instance_eval{@parser}).to eq(nil)
|
48
|
-
end
|
16
|
+
describe "#initialize" do
|
17
|
+
context "with default parameters" do
|
18
|
+
it "specified file should be opened" do
|
19
|
+
File.should_receive(:open).with(access_log)
|
20
|
+
reader
|
49
21
|
end
|
50
22
|
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
reader = NginxUtils::Logreader.new(@log_file, format: :combined)
|
58
|
-
expect(reader.instance_eval{@format}).to eq(:combined)
|
59
|
-
end
|
60
|
-
|
61
|
-
it "parser should be specified parameter" do
|
62
|
-
reader = NginxUtils::Logreader.new(@log_file, parser: @parser)
|
63
|
-
expect(reader.instance_eval{@parser}).to eq(@parser)
|
64
|
-
end
|
65
|
-
|
66
|
-
it "format should be :custom if specified parser" do
|
67
|
-
reader = NginxUtils::Logreader.new(@log_file, parser: @parser)
|
68
|
-
expect(reader.instance_eval{@format}).to eq(:custom)
|
69
|
-
end
|
70
|
-
|
71
|
-
it "should create exception if parser is not Regexp instance" do
|
72
|
-
expect(proc{NginxUtils::Logreader.new(@log_file, parser: "invalid parser")}).to raise_error("invalid argument")
|
73
|
-
end
|
23
|
+
it "default format should be ltsv" do
|
24
|
+
expect(reader.instance_eval{@format}).to eq(:ltsv)
|
25
|
+
end
|
26
|
+
|
27
|
+
it "default parser should be nil" do
|
28
|
+
expect(reader.instance_eval{@parser}).to eq(nil)
|
74
29
|
end
|
75
30
|
end
|
76
31
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
reader = NginxUtils::Logreader.new(@log_file)
|
82
|
-
ltsv_hash = {
|
83
|
-
time: "2013-05-19T08:13:14+00:00",
|
84
|
-
host: "192.168.1.10",
|
85
|
-
xff:"-",
|
86
|
-
method: "GET",
|
87
|
-
path: "/",
|
88
|
-
status: "200",
|
89
|
-
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31",
|
90
|
-
req_size: "124",
|
91
|
-
req_time: "0.007",
|
92
|
-
res_size: "239",
|
93
|
-
body_size: "11",
|
94
|
-
app_time: "-"
|
95
|
-
}
|
96
|
-
reader.each {|line| expect(line).to eq(ltsv_hash)}
|
97
|
-
end
|
32
|
+
context "with custom parameters" do
|
33
|
+
it "format should be specified parameter" do
|
34
|
+
reader = NginxUtils::Logreader.new(access_log, format: :combined)
|
35
|
+
expect(reader.instance_eval{@format}).to eq(:combined)
|
98
36
|
end
|
99
37
|
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
38
|
+
it "parser should be specified parameter" do
|
39
|
+
reader = NginxUtils::Logreader.new(access_log, parser: parser)
|
40
|
+
expect(reader.instance_eval{@parser}).to eq(parser)
|
41
|
+
end
|
42
|
+
|
43
|
+
it "format should be :custom if specified parser" do
|
44
|
+
reader = NginxUtils::Logreader.new(access_log, parser: parser)
|
45
|
+
expect(reader.instance_eval{@format}).to eq(:custom)
|
46
|
+
end
|
47
|
+
|
48
|
+
it "should create exception if parser is not Regexp instance" do
|
49
|
+
expect(
|
50
|
+
proc {
|
51
|
+
NginxUtils::Logreader.new(access_log, parser: "invalid parser")
|
113
52
|
}
|
114
|
-
|
115
|
-
end
|
116
|
-
|
117
|
-
it "return unknown log if parse error" do
|
118
|
-
create_log(:combined)
|
119
|
-
File.open(@log_file, "w") {|f| f.write "unknown log"}
|
120
|
-
reader = NginxUtils::Logreader.new(@log_file, format: :combined)
|
121
|
-
reader.each {|line| expect(line).to eq({unknown: "unknown log"})}
|
122
|
-
end
|
53
|
+
).to raise_error("invalid argument")
|
123
54
|
end
|
124
55
|
end
|
125
56
|
end
|
57
|
+
|
58
|
+
describe "#each" do
|
59
|
+
it "call parse method" do
|
60
|
+
io_mock.stub(:each).and_yield("log line\n")
|
61
|
+
NginxUtils::Logreader.any_instance.should_receive(:parse)
|
62
|
+
reader.each {|line| line}
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
describe "#parse" do
|
67
|
+
let(:ltsv_line) {"time:2013-05-19T08:13:14+00:00\thost:192.168.1.10\txff:-\tmethod:GET\tpath:/\tstatus:200\tua:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31\treq_size:124\treq_time:0.007\tres_size:239\tbody_size:11\tapp_time:-\n"}
|
68
|
+
let(:combined_line) {"192.168.1.10 - - [19/May/2013:23:14:04 +0900] \"GET / HTTP/1.1\" 200 239 \"-\" \"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31\"\n"}
|
69
|
+
|
70
|
+
it "ltsv format log" do
|
71
|
+
ltsv_hash = {
|
72
|
+
time: "2013-05-19T08:13:14+00:00",
|
73
|
+
host: "192.168.1.10",
|
74
|
+
xff:"-",
|
75
|
+
method: "GET",
|
76
|
+
path: "/",
|
77
|
+
status: "200",
|
78
|
+
ua: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31",
|
79
|
+
req_size: "124",
|
80
|
+
req_time: "0.007",
|
81
|
+
res_size: "239",
|
82
|
+
body_size: "11",
|
83
|
+
app_time: "-"
|
84
|
+
}
|
85
|
+
expect(reader.send(:parse, ltsv_line.chomp)).to eq(ltsv_hash)
|
86
|
+
end
|
87
|
+
|
88
|
+
it "combined format log" do
|
89
|
+
combined_hash = {
|
90
|
+
remote_addr: "192.168.1.10",
|
91
|
+
remote_user: "-",
|
92
|
+
time_local: "19/May/2013:23:14:04 +0900",
|
93
|
+
request: "GET / HTTP/1.1",
|
94
|
+
status: "200",
|
95
|
+
body_bytes_sent: "239",
|
96
|
+
http_referer: "-",
|
97
|
+
http_user_agent: "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31"
|
98
|
+
}
|
99
|
+
reader = NginxUtils::Logreader.new(access_log, format: :combined)
|
100
|
+
expect(reader.send(:parse, combined_line.chomp)).to eq(combined_hash)
|
101
|
+
end
|
102
|
+
|
103
|
+
it "return unknown log if parse error" do
|
104
|
+
unknown_line = "unknown log"
|
105
|
+
reader = NginxUtils::Logreader.new(access_log, format: :combined)
|
106
|
+
expect(reader.send(:parse, unknown_line)).to eq({unknown: unknown_line})
|
107
|
+
end
|
108
|
+
|
109
|
+
it "custom format parser" do
|
110
|
+
custom_hash = [
|
111
|
+
[
|
112
|
+
"192.168.1.10",
|
113
|
+
"-",
|
114
|
+
"19/May/2013:23:14:04 +0900",
|
115
|
+
"GET / HTTP/1.1",
|
116
|
+
"200",
|
117
|
+
"239",
|
118
|
+
"-",
|
119
|
+
"Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/537.31 (KHTML, like Gecko) Chrome/26.0.1410.65 Safari/537.31"
|
120
|
+
]
|
121
|
+
]
|
122
|
+
reader = NginxUtils::Logreader.new(access_log, parser: parser)
|
123
|
+
expect(reader.send(:parse, combined_line.chomp)).to eq(custom_hash)
|
124
|
+
end
|
125
|
+
|
126
|
+
it "create exception if unknown format" do
|
127
|
+
reader = NginxUtils::Logreader.new(access_log, format: :unknown)
|
128
|
+
expect(proc{reader.send(:parse, combined_line.chomp)}).to raise_error("format error")
|
129
|
+
end
|
130
|
+
end
|
126
131
|
end
|