steno 0.0.20 → 1.0.0
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/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
|