nginx_utils 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- 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
|