steno 0.0.20 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/steno/config.rb +7 -2
- data/lib/steno/sink/io.rb +34 -10
- data/lib/steno/version.rb +1 -1
- data/spec/unit/config_spec.rb +21 -5
- data/spec/unit/sink/io_spec.rb +64 -1
- metadata +2 -2
data/lib/steno/config.rb
CHANGED
@@ -42,7 +42,9 @@ class Steno::Config
|
|
42
42
|
}
|
43
43
|
|
44
44
|
if hash[:file]
|
45
|
-
|
45
|
+
max_retries = hash[:max_retries]
|
46
|
+
opts[:sinks] << Steno::Sink::IO.for_file(hash[:file],
|
47
|
+
:max_retries => max_retries)
|
46
48
|
end
|
47
49
|
|
48
50
|
if hash[:syslog]
|
@@ -50,7 +52,10 @@ class Steno::Config
|
|
50
52
|
opts[:sinks] << Steno::Sink::Syslog.instance
|
51
53
|
end
|
52
54
|
|
53
|
-
|
55
|
+
if opts[:sinks].empty?
|
56
|
+
opts[:sinks] << Steno::Sink::IO.new(STDOUT)
|
57
|
+
end
|
58
|
+
|
54
59
|
opts
|
55
60
|
end
|
56
61
|
|
data/lib/steno/sink/io.rb
CHANGED
@@ -10,24 +10,36 @@ class Steno::Sink::IO < Steno::Sink::Base
|
|
10
10
|
# Returns a new sink configured to append to the file at path.
|
11
11
|
#
|
12
12
|
# @param [String] path
|
13
|
-
# @param [
|
14
|
-
#
|
15
|
-
#
|
13
|
+
# @param [Hash] If the key :autoflush is set to true, encoded records
|
14
|
+
# will not be buffered by Ruby. The key :max_retries
|
15
|
+
# is forwarded to Steno::Sink::IO object during creation.
|
16
16
|
# @return [Steno::Sink::IO]
|
17
|
-
def for_file(path,
|
17
|
+
def for_file(path, opts = {})
|
18
|
+
autoflush = true
|
19
|
+
if opts.include?(:autoflush)
|
20
|
+
autoflush = opts[:autoflush]
|
21
|
+
end
|
22
|
+
|
18
23
|
io = File.open(path, "a+")
|
19
24
|
|
20
25
|
io.sync = autoflush
|
21
26
|
|
22
|
-
new(io)
|
27
|
+
new(io, :max_retries => opts[:max_retries])
|
23
28
|
end
|
24
29
|
end
|
25
30
|
|
26
|
-
|
27
|
-
# @param [Steno::Codec::Base] codec
|
28
|
-
def initialize(io, codec = nil)
|
29
|
-
super(codec)
|
31
|
+
attr_reader :max_retries
|
30
32
|
|
33
|
+
# @param [IO] io The IO object that will be written to
|
34
|
+
# @param [Hash] opts Key :codec is used to specify a codec inheriting from
|
35
|
+
# Steno::Codec::Base.
|
36
|
+
# Key :max_retries takes an integer value which specifies
|
37
|
+
# the number of times the write operation can be retried
|
38
|
+
# when IOError is raised while writing a record.
|
39
|
+
def initialize(io, opts = {})
|
40
|
+
super(opts[:codec])
|
41
|
+
|
42
|
+
@max_retries = opts[:max_retries] || -1
|
31
43
|
@io_lock = Mutex.new
|
32
44
|
@io = io
|
33
45
|
end
|
@@ -35,7 +47,19 @@ class Steno::Sink::IO < Steno::Sink::Base
|
|
35
47
|
def add_record(record)
|
36
48
|
bytes = @codec.encode_record(record)
|
37
49
|
|
38
|
-
@io_lock.synchronize
|
50
|
+
@io_lock.synchronize do
|
51
|
+
retries = 0
|
52
|
+
begin
|
53
|
+
@io.write(bytes)
|
54
|
+
rescue IOError => e
|
55
|
+
if retries < @max_retries
|
56
|
+
retries += 1
|
57
|
+
retry
|
58
|
+
else
|
59
|
+
raise e
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
39
63
|
|
40
64
|
nil
|
41
65
|
end
|
data/lib/steno/version.rb
CHANGED
data/spec/unit/config_spec.rb
CHANGED
@@ -10,7 +10,8 @@ describe Steno::Config do
|
|
10
10
|
|
11
11
|
@mock_sink_file = mock("sink")
|
12
12
|
@mock_sink_file.stub(:codec=)
|
13
|
-
Steno::Sink::IO.should_receive(:for_file).with(@log_path
|
13
|
+
Steno::Sink::IO.should_receive(:for_file).with(@log_path,
|
14
|
+
:max_retries => 5)
|
14
15
|
.and_return(@mock_sink_file)
|
15
16
|
|
16
17
|
@mock_sink_syslog = mock("sink")
|
@@ -36,7 +37,8 @@ describe Steno::Config do
|
|
36
37
|
:file => @log_path,
|
37
38
|
:level => "debug2",
|
38
39
|
:default_log_level => "warn",
|
39
|
-
:syslog => "test"
|
40
|
+
:syslog => "test",
|
41
|
+
:max_retries => 5,
|
40
42
|
}
|
41
43
|
end
|
42
44
|
|
@@ -45,7 +47,8 @@ describe Steno::Config do
|
|
45
47
|
"file" => @log_path,
|
46
48
|
"level" => "debug2",
|
47
49
|
"default_log_level" => "warn",
|
48
|
-
"syslog" => "test"
|
50
|
+
"syslog" => "test",
|
51
|
+
"max_retries" => 5,
|
49
52
|
}
|
50
53
|
end
|
51
54
|
end
|
@@ -90,11 +93,12 @@ describe Steno::Config do
|
|
90
93
|
end
|
91
94
|
|
92
95
|
it "should add a file sink if the 'file' key is specified" do
|
93
|
-
write_config(@config_path, { "file" => @log_path })
|
96
|
+
write_config(@config_path, { "file" => @log_path, "max_retries" => 2 })
|
94
97
|
mock_sink = mock("sink")
|
95
98
|
mock_sink.stub(:codec=)
|
96
99
|
|
97
|
-
Steno::Sink::IO.should_receive(:for_file).
|
100
|
+
Steno::Sink::IO.should_receive(:for_file).
|
101
|
+
with(@log_path, :max_retries => 2).and_return(mock_sink)
|
98
102
|
config = Steno::Config.from_file(@config_path)
|
99
103
|
config.sinks.size.should == 1
|
100
104
|
config.sinks[0].should == mock_sink
|
@@ -113,6 +117,18 @@ describe Steno::Config do
|
|
113
117
|
config.sinks[0].should == mock_sink
|
114
118
|
end
|
115
119
|
|
120
|
+
it "should add an io sink to stdout if no sinks are explicitly specified in the config file" do
|
121
|
+
write_config(@config_path, {})
|
122
|
+
mock_sink = mock("sink")
|
123
|
+
mock_sink.stub(:codec=)
|
124
|
+
|
125
|
+
Steno::Sink::IO.should_receive(:new).with(STDOUT).and_return(mock_sink)
|
126
|
+
|
127
|
+
config = Steno::Config.from_file(@config_path)
|
128
|
+
config.sinks.size.should == 1
|
129
|
+
config.sinks[0].should == mock_sink
|
130
|
+
end
|
131
|
+
|
116
132
|
it "should merge supplied overrides with the file based config" do
|
117
133
|
write_config(@config_path, { "default_log_level" => "debug" })
|
118
134
|
|
data/spec/unit/sink/io_spec.rb
CHANGED
@@ -9,6 +9,41 @@ describe Steno::Sink::IO do
|
|
9
9
|
Steno::Record.new("source", level, "message")
|
10
10
|
end
|
11
11
|
|
12
|
+
describe ".for_file" do
|
13
|
+
it "should return a new sink configured to append to the file at path with autosync set to true by default" do
|
14
|
+
mock_handle = mock("file handle")
|
15
|
+
|
16
|
+
File.should_receive(:open).with("path", "a+").and_return(mock_handle)
|
17
|
+
mock_handle.should_receive(:sync=).with(true)
|
18
|
+
|
19
|
+
mock_sink = mock("sink")
|
20
|
+
Steno::Sink::IO.should_receive(:new).with(mock_handle,
|
21
|
+
:max_retries => 10).
|
22
|
+
and_return(mock_sink)
|
23
|
+
|
24
|
+
returned = Steno::Sink::IO.for_file("path",
|
25
|
+
:max_retries => 10)
|
26
|
+
returned.should == mock_sink
|
27
|
+
end
|
28
|
+
|
29
|
+
it "should return a new sink configured to append to the file at path with specified options" do
|
30
|
+
mock_handle = mock("file handle")
|
31
|
+
|
32
|
+
File.should_receive(:open).with("path", "a+").and_return(mock_handle)
|
33
|
+
mock_handle.should_receive(:sync=).with(false)
|
34
|
+
|
35
|
+
mock_sink = mock("sink")
|
36
|
+
Steno::Sink::IO.should_receive(:new).with(mock_handle,
|
37
|
+
:max_retries => 10).
|
38
|
+
and_return(mock_sink)
|
39
|
+
|
40
|
+
returned = Steno::Sink::IO.for_file("path",
|
41
|
+
:autoflush => false,
|
42
|
+
:max_retries => 10)
|
43
|
+
returned.should == mock_sink
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
12
47
|
describe "#add_record" do
|
13
48
|
it "should encode the record and write it to the underlying io object" do
|
14
49
|
codec = mock("codec")
|
@@ -17,7 +52,35 @@ describe Steno::Sink::IO do
|
|
17
52
|
io = mock("io")
|
18
53
|
io.should_receive(:write).with(record.message)
|
19
54
|
|
20
|
-
Steno::Sink::IO.new(io, codec).add_record(record)
|
55
|
+
Steno::Sink::IO.new(io, :codec => codec).add_record(record)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "should by default not retry on IOError" do
|
59
|
+
codec = mock("codec")
|
60
|
+
codec.should_receive(:encode_record).with(record).and_return(record.message)
|
61
|
+
|
62
|
+
io = mock("io")
|
63
|
+
|
64
|
+
io.should_receive(:write).with(record.message).ordered.and_raise(IOError)
|
65
|
+
|
66
|
+
expect {
|
67
|
+
Steno::Sink::IO.new(io, :codec => codec).add_record(record)
|
68
|
+
}.to raise_error(IOError)
|
69
|
+
end
|
70
|
+
|
71
|
+
it "should retry not more than specified number of times on IOError" do
|
72
|
+
codec = mock("codec")
|
73
|
+
codec.should_receive(:encode_record).with(record).and_return(record.message)
|
74
|
+
|
75
|
+
io = mock("io")
|
76
|
+
|
77
|
+
io.should_receive(:write).exactly(3).times.with(record.message).ordered.
|
78
|
+
and_raise(IOError)
|
79
|
+
|
80
|
+
expect {
|
81
|
+
Steno::Sink::IO.new(io, :codec => codec, :max_retries => 2).
|
82
|
+
add_record(record)
|
83
|
+
}.to raise_error(IOError)
|
21
84
|
end
|
22
85
|
end
|
23
86
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: steno
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: grape
|