yell 1.3.0 → 1.4.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.
- checksums.yaml +7 -0
- data/.gitignore +3 -1
- data/.travis.yml +1 -2
- data/Gemfile +5 -1
- data/README.md +67 -14
- data/examples/004.1-colorizing-the-log-output.rb +4 -4
- data/lib/yell.rb +19 -10
- data/lib/yell/adapters.rb +23 -26
- data/lib/yell/adapters/base.rb +8 -2
- data/lib/yell/adapters/datefile.rb +45 -42
- data/lib/yell/adapters/file.rb +10 -5
- data/lib/yell/adapters/io.rb +52 -48
- data/lib/yell/adapters/streams.rb +10 -2
- data/lib/yell/configuration.rb +1 -1
- data/lib/yell/event.rb +4 -4
- data/lib/yell/formatter.rb +11 -25
- data/lib/yell/helpers/adapters.rb +51 -0
- data/lib/yell/helpers/base.rb +19 -0
- data/lib/yell/helpers/formatter.rb +31 -0
- data/lib/yell/helpers/level.rb +36 -0
- data/lib/yell/helpers/silencer.rb +32 -0
- data/lib/yell/helpers/tracer.rb +48 -0
- data/lib/yell/level.rb +38 -47
- data/lib/yell/logger.rb +53 -73
- data/lib/yell/repository.rb +31 -29
- data/lib/yell/silencer.rb +69 -0
- data/lib/yell/version.rb +1 -1
- data/spec/spec_helper.rb +21 -9
- data/spec/yell/adapters/base_spec.rb +17 -34
- data/spec/yell/adapters/datefile_spec.rb +109 -66
- data/spec/yell/adapters/file_spec.rb +18 -18
- data/spec/yell/adapters/io_spec.rb +17 -13
- data/spec/yell/adapters/streams_spec.rb +7 -7
- data/spec/yell/adapters_spec.rb +18 -23
- data/spec/yell/configuration_spec.rb +7 -7
- data/spec/yell/event_spec.rb +25 -27
- data/spec/yell/formatter_spec.rb +89 -82
- data/spec/yell/level_spec.rb +119 -94
- data/spec/yell/loggable_spec.rb +6 -5
- data/spec/yell/logger_spec.rb +106 -66
- data/spec/yell/repository_spec.rb +23 -38
- data/spec/yell/silencer_spec.rb +49 -0
- data/spec/yell_spec.rb +24 -27
- metadata +16 -9
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
module Yell #:nodoc:
|
3
|
+
|
4
|
+
# The +Yell::Silencer+ is your handly helper for stiping out unwanted log messages.
|
5
|
+
class Silencer
|
6
|
+
|
7
|
+
def initialize( *patterns )
|
8
|
+
@patterns = patterns.dup
|
9
|
+
end
|
10
|
+
|
11
|
+
# Add one or more patterns to the silencer
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# add( 'password' )
|
15
|
+
# add( 'username', 'password' )
|
16
|
+
#
|
17
|
+
# @example Add regular expressions
|
18
|
+
# add( /password/ )
|
19
|
+
#
|
20
|
+
# @return [Array] All set patterns
|
21
|
+
def add( *patterns )
|
22
|
+
@patterns = @patterns | patterns.compact
|
23
|
+
end
|
24
|
+
|
25
|
+
# Clears out all the messages that would match any defined pattern
|
26
|
+
#
|
27
|
+
# @example
|
28
|
+
# silence('username', 'password')
|
29
|
+
# #=> ['username]
|
30
|
+
#
|
31
|
+
# @return [Array<String>] The remaining messages
|
32
|
+
def silence( *messages )
|
33
|
+
messages.reject { |m| matches?(m) }
|
34
|
+
end
|
35
|
+
|
36
|
+
# Anything to silence at all?
|
37
|
+
#
|
38
|
+
# @return [Boolean] true or false
|
39
|
+
def silence?
|
40
|
+
@patterns.any?
|
41
|
+
end
|
42
|
+
|
43
|
+
# Get a pretty string
|
44
|
+
def inspect
|
45
|
+
"#<#{self.class.name} patterns: #{@patterns.inspect}>"
|
46
|
+
end
|
47
|
+
|
48
|
+
# @private
|
49
|
+
def patterns
|
50
|
+
@patterns
|
51
|
+
end
|
52
|
+
|
53
|
+
|
54
|
+
private
|
55
|
+
|
56
|
+
# Check if the provided message matches any of the defined patterns.
|
57
|
+
#
|
58
|
+
# @example
|
59
|
+
# matches?('password')
|
60
|
+
# #=> true
|
61
|
+
#
|
62
|
+
# @return [Boolean] true or false
|
63
|
+
def matches?( message )
|
64
|
+
@patterns.any? { |pattern| message.match(pattern) }
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
data/lib/yell/version.rb
CHANGED
data/spec/spec_helper.rb
CHANGED
@@ -3,12 +3,29 @@ $:.unshift File.expand_path('../../lib', __FILE__)
|
|
3
3
|
|
4
4
|
ENV['YELL_ENV'] = 'test'
|
5
5
|
|
6
|
-
require '
|
7
|
-
|
8
|
-
require 'rspec'
|
6
|
+
require 'rspec/core'
|
7
|
+
require 'rspec/expectations'
|
9
8
|
require 'rr'
|
10
9
|
require 'timecop'
|
11
10
|
|
11
|
+
begin
|
12
|
+
require 'coveralls'
|
13
|
+
|
14
|
+
require 'simplecov'
|
15
|
+
SimpleCov.formatter = SimpleCov::Formatter::MultiFormatter[
|
16
|
+
SimpleCov::Formatter::HTMLFormatter,
|
17
|
+
Coveralls::SimpleCov::Formatter
|
18
|
+
]
|
19
|
+
|
20
|
+
SimpleCov.start do
|
21
|
+
add_filter 'spec'
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
STDERR.puts "Not running coverage..."
|
25
|
+
end
|
26
|
+
|
27
|
+
require 'yell'
|
28
|
+
|
12
29
|
RSpec.configure do |config|
|
13
30
|
config.mock_framework = :rr
|
14
31
|
|
@@ -19,8 +36,7 @@ RSpec.configure do |config|
|
|
19
36
|
end
|
20
37
|
|
21
38
|
config.after do
|
22
|
-
# release time after each test
|
23
|
-
Timecop.return
|
39
|
+
Timecop.return # release time after each test
|
24
40
|
end
|
25
41
|
|
26
42
|
|
@@ -30,9 +46,5 @@ RSpec.configure do |config|
|
|
30
46
|
File.expand_path( "fixtures", File.dirname(__FILE__) )
|
31
47
|
end
|
32
48
|
|
33
|
-
def datefile_filename( pattern = Yell::Adapters::Datefile::DefaultDatePattern )
|
34
|
-
fixture_path + "/test.#{Time.now.strftime(pattern)}.log"
|
35
|
-
end
|
36
|
-
|
37
49
|
end
|
38
50
|
|
@@ -2,57 +2,40 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Yell::Adapters::Base do
|
4
4
|
|
5
|
-
context "initialize
|
6
|
-
|
7
|
-
|
8
|
-
mock( base ).level= :info
|
9
|
-
end
|
10
|
-
end
|
5
|
+
context "initialize" do
|
6
|
+
context ":level" do
|
7
|
+
let(:level) { Yell::Level.new(:warn) }
|
11
8
|
|
12
|
-
|
13
|
-
|
14
|
-
end
|
15
|
-
end
|
9
|
+
it "should set the level" do
|
10
|
+
adapter = Yell::Adapters::Base.new(:level => level)
|
16
11
|
|
17
|
-
|
18
|
-
context :level do
|
19
|
-
before do
|
20
|
-
any_instance_of( Yell::Adapters::Base ) do |base|
|
21
|
-
mock( base ).level= :info
|
22
|
-
end
|
12
|
+
expect(adapter.level).to eq(level)
|
23
13
|
end
|
24
14
|
|
25
|
-
it "should set the level" do
|
26
|
-
Yell::Adapters::Base.new
|
15
|
+
it "should set the level when block was given" do
|
16
|
+
adapter = Yell::Adapters::Base.new { |a| a.level = level }
|
17
|
+
|
18
|
+
expect(adapter.level).to eq(level)
|
27
19
|
end
|
28
20
|
end
|
29
21
|
end
|
30
22
|
|
31
|
-
context
|
32
|
-
let(:options) { {:my => :options} }
|
33
|
-
let(:adapter) { Yell::Adapters::Base.new(options) }
|
34
|
-
|
35
|
-
it { options.should == options }
|
36
|
-
end
|
37
|
-
|
38
|
-
context :write do
|
23
|
+
context "#write" do
|
39
24
|
let(:logger) { Yell::Logger.new }
|
40
25
|
subject { Yell::Adapters::Base.new(:level => 1) }
|
41
26
|
|
42
27
|
it "should delegate :event to :write!" do
|
43
|
-
event = Yell::Event.new(
|
44
|
-
|
45
|
-
mock( subject ).write!( event )
|
28
|
+
event = Yell::Event.new(logger, 1, "Hello World!")
|
29
|
+
mock(subject).write!(event)
|
46
30
|
|
47
|
-
subject.write(
|
31
|
+
subject.write(event)
|
48
32
|
end
|
49
33
|
|
50
34
|
it "should not write when event does not have the right level" do
|
51
|
-
event = Yell::Event.new(
|
52
|
-
|
53
|
-
dont_allow( subject ).write!( event )
|
35
|
+
event = Yell::Event.new(logger, 0, "Hello World!")
|
36
|
+
dont_allow(subject).write!(event)
|
54
37
|
|
55
|
-
subject.write(
|
38
|
+
subject.write(event)
|
56
39
|
end
|
57
40
|
end
|
58
41
|
|
@@ -2,122 +2,165 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
describe Yell::Adapters::Datefile do
|
4
4
|
let(:logger) { Yell::Logger.new }
|
5
|
+
let(:message) { "Hello World" }
|
6
|
+
let(:event) { Yell::Event.new(logger, 1, message) }
|
7
|
+
|
8
|
+
let(:today) { Time.now }
|
9
|
+
let(:tomorrow) { Time.now + 86400 }
|
10
|
+
|
5
11
|
let(:filename) { fixture_path + '/test.log' }
|
6
|
-
let(:
|
12
|
+
let(:today_filename) { fixture_path + "/test.#{today.strftime(Yell::Adapters::Datefile::DefaultDatePattern)}.log" }
|
13
|
+
let(:tomorrow_filename) { fixture_path + "/test.#{tomorrow.strftime(Yell::Adapters::Datefile::DefaultDatePattern)}.log" }
|
14
|
+
|
15
|
+
let(:adapter) { Yell::Adapters::Datefile.new(:filename => filename, :format => "%m") }
|
7
16
|
|
8
17
|
before do
|
9
|
-
Timecop.freeze(
|
18
|
+
Timecop.freeze(today)
|
10
19
|
end
|
11
20
|
|
12
21
|
it { should be_kind_of Yell::Adapters::File }
|
13
22
|
|
14
|
-
describe
|
15
|
-
let(:
|
23
|
+
describe "#write" do
|
24
|
+
let(:today_lines) { File.readlines(today_filename) }
|
16
25
|
|
17
|
-
|
18
|
-
adapter.write(
|
19
|
-
|
20
|
-
File.exist?(datefile_filename).should be_true
|
26
|
+
before do
|
27
|
+
adapter.write(event)
|
21
28
|
end
|
22
29
|
|
23
|
-
it "should
|
24
|
-
|
30
|
+
it "should be output to filename with date pattern" do
|
31
|
+
expect(File.exist?(today_filename)).to be_true
|
25
32
|
|
26
|
-
|
27
|
-
|
33
|
+
expect(today_lines.size).to eq(2) # includes header line
|
34
|
+
expect(today_lines.last).to match(message)
|
28
35
|
end
|
29
36
|
|
30
|
-
|
31
|
-
|
32
|
-
let(:tomorrow_datefile_filename) { fixture_path + "/test.#{tomorrow.strftime(Yell::Adapters::Datefile::DefaultDatePattern)}.log" }
|
37
|
+
it "should output to the same file" do
|
38
|
+
adapter.write(event)
|
33
39
|
|
34
|
-
|
35
|
-
|
36
|
-
|
40
|
+
expect(File.exist?(today_filename)).to be_true
|
41
|
+
expect(today_lines.size).to eq(3) # includes header line
|
42
|
+
end
|
37
43
|
|
38
|
-
|
44
|
+
it "should not open file handle again" do
|
45
|
+
dont_allow(File).open(anything, anything)
|
39
46
|
|
40
|
-
|
41
|
-
adapter.write( event )
|
42
|
-
end
|
47
|
+
adapter.write(event)
|
43
48
|
end
|
44
|
-
end
|
45
49
|
|
46
|
-
|
47
|
-
|
50
|
+
context "on rollover" do
|
51
|
+
let(:tomorrow_lines) { File.readlines(tomorrow_filename) }
|
48
52
|
|
49
|
-
|
50
|
-
|
51
|
-
Dir[ fixture_path + '/*.log' ].size.should == 1
|
52
|
-
|
53
|
-
Timecop.freeze( Time.now + 60 ) do
|
54
|
-
adapter.write( event )
|
55
|
-
Dir[ fixture_path + '/*.log' ].size.should == 2
|
53
|
+
before do
|
54
|
+
Timecop.freeze(tomorrow) { adapter.write(event) }
|
56
55
|
end
|
57
56
|
|
58
|
-
|
59
|
-
|
60
|
-
|
57
|
+
it "should rotate file" do
|
58
|
+
expect(File.exist?(tomorrow_filename)).to be_true
|
59
|
+
|
60
|
+
expect(tomorrow_lines.size).to eq(2) # includes header line
|
61
|
+
expect(tomorrow_lines.last).to match(message)
|
61
62
|
end
|
62
63
|
end
|
63
64
|
end
|
64
65
|
|
65
|
-
describe
|
66
|
-
|
67
|
-
|
66
|
+
describe "#keep" do
|
67
|
+
before do
|
68
|
+
adapter.symlink = false # to not taint the Dir
|
69
|
+
adapter.keep = 2
|
70
|
+
|
71
|
+
adapter.write(event)
|
72
|
+
end
|
68
73
|
|
69
|
-
|
70
|
-
|
74
|
+
it "should keep the specified number or files upon rollover" do
|
75
|
+
expect(Dir[fixture_path + '/*.log'].size).to eq(1)
|
71
76
|
|
72
|
-
|
73
|
-
|
77
|
+
Timecop.freeze(tomorrow) { adapter.write(event) }
|
78
|
+
expect(Dir[fixture_path + '/*.log'].size).to eq(2)
|
74
79
|
|
75
|
-
|
76
|
-
|
80
|
+
Timecop.freeze(tomorrow + 86400 ) { adapter.write(event) }
|
81
|
+
expect(Dir[fixture_path + '/*.log'].size).to eq(2)
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
describe "#symlink" do
|
86
|
+
context "when true (default)" do
|
87
|
+
before do
|
88
|
+
adapter.write(event)
|
77
89
|
end
|
78
90
|
|
79
|
-
it "should
|
80
|
-
|
91
|
+
it "should be created on the original filename" do
|
92
|
+
expect(File.symlink?(filename)).to be_true
|
93
|
+
expect(File.readlink(filename)).to eq(today_filename)
|
94
|
+
end
|
81
95
|
|
82
|
-
|
83
|
-
|
96
|
+
it "should be recreated upon rollover" do
|
97
|
+
Timecop.freeze(tomorrow) { adapter.write(event) }
|
84
98
|
|
85
|
-
|
86
|
-
|
87
|
-
end
|
99
|
+
expect(File.symlink?(filename)).to be_true
|
100
|
+
expect(File.readlink(filename)).to eq(tomorrow_filename)
|
88
101
|
end
|
89
102
|
end
|
90
103
|
|
91
|
-
context "when
|
92
|
-
|
104
|
+
context "when false" do
|
105
|
+
before do
|
106
|
+
adapter.symlink = false
|
107
|
+
end
|
93
108
|
|
94
109
|
it "should not create the sylink the original filename" do
|
95
110
|
adapter.write( event )
|
96
111
|
|
97
|
-
File.symlink?(
|
112
|
+
expect(File.symlink?(filename)).to be_false
|
98
113
|
end
|
99
114
|
end
|
100
115
|
end
|
101
116
|
|
102
|
-
describe
|
103
|
-
let(:
|
104
|
-
let(:header) { File.open(datefile_filename, &:readline) }
|
117
|
+
describe "#header" do
|
118
|
+
let(:header) { File.open(today_filename, &:readline) }
|
105
119
|
|
106
|
-
|
107
|
-
|
120
|
+
context "when true (default)" do
|
121
|
+
before do
|
122
|
+
adapter.write(event)
|
123
|
+
end
|
124
|
+
|
125
|
+
it "should be written" do
|
126
|
+
expect(header).to match(Yell::Adapters::Datefile::HeaderRegexp)
|
127
|
+
end
|
128
|
+
|
129
|
+
it "should be rewritten upon rollover" do
|
130
|
+
Timecop.freeze(tomorrow) { adapter.write(event) }
|
131
|
+
|
132
|
+
expect(File.symlink?(filename)).to be_true
|
133
|
+
expect(File.readlink(filename)).to eq(tomorrow_filename)
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
context "when false" do
|
138
|
+
before do
|
139
|
+
adapter.header = false
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should not be written" do
|
143
|
+
adapter.write(event)
|
144
|
+
|
145
|
+
expect(header).to eq("Hello World\n")
|
146
|
+
end
|
108
147
|
end
|
148
|
+
end
|
109
149
|
|
110
|
-
|
111
|
-
|
150
|
+
context "another adapter with the same :filename" do
|
151
|
+
let(:another_adapter) { Yell::Adapters::Datefile.new(:filename => filename) }
|
112
152
|
|
113
|
-
|
153
|
+
before do
|
154
|
+
adapter.write(event)
|
114
155
|
end
|
115
156
|
|
116
|
-
it "should not
|
117
|
-
|
118
|
-
adapter.write( event )
|
157
|
+
it "should not write the header again" do
|
158
|
+
another_adapter.write(event)
|
119
159
|
|
120
|
-
|
160
|
+
# 1: header
|
161
|
+
# 2: adapter write
|
162
|
+
# 3: another_adapter: write
|
163
|
+
expect(File.readlines(today_filename).size).to eq(3)
|
121
164
|
end
|
122
165
|
end
|
123
166
|
|
@@ -4,18 +4,18 @@ describe Yell::Adapters::File do
|
|
4
4
|
let(:devnull) { File.new('/dev/null', 'w') }
|
5
5
|
|
6
6
|
before do
|
7
|
-
stub(
|
7
|
+
stub(File).open(anything, anything) { devnull }
|
8
8
|
end
|
9
9
|
|
10
|
-
it { should be_kind_of
|
10
|
+
it { should be_kind_of(Yell::Adapters::Io) }
|
11
11
|
|
12
|
-
context
|
13
|
-
subject { Yell::Adapters::File.new.send
|
12
|
+
context "#stream" do
|
13
|
+
subject { Yell::Adapters::File.new.send(:stream) }
|
14
14
|
|
15
|
-
it { should be_kind_of
|
15
|
+
it { should be_kind_of(File) }
|
16
16
|
end
|
17
17
|
|
18
|
-
context
|
18
|
+
context "#write" do
|
19
19
|
let(:logger) { Yell::Logger.new }
|
20
20
|
let(:event) { Yell::Event.new(logger, 1, "Hello World") }
|
21
21
|
|
@@ -24,20 +24,20 @@ describe Yell::Adapters::File do
|
|
24
24
|
let(:adapter) { Yell::Adapters::File.new }
|
25
25
|
|
26
26
|
it "should print to file" do
|
27
|
-
mock(
|
27
|
+
mock(File).open(filename, File::WRONLY|File::APPEND|File::CREAT) { devnull }
|
28
28
|
|
29
|
-
adapter.write(
|
29
|
+
adapter.write(event)
|
30
30
|
end
|
31
31
|
end
|
32
32
|
|
33
33
|
context "with given :filename" do
|
34
34
|
let(:filename) { fixture_path + '/filename.log' }
|
35
|
-
let(:adapter) { Yell::Adapters::File.new(
|
35
|
+
let(:adapter) { Yell::Adapters::File.new(:filename => filename) }
|
36
36
|
|
37
37
|
it "should print to file" do
|
38
|
-
mock(
|
38
|
+
mock(File).open(filename, File::WRONLY|File::APPEND|File::CREAT) { devnull }
|
39
39
|
|
40
|
-
adapter.write(
|
40
|
+
adapter.write(event)
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
@@ -46,27 +46,27 @@ describe Yell::Adapters::File do
|
|
46
46
|
let(:adapter) { Yell::Adapters::File.new( :filename => pathname ) }
|
47
47
|
|
48
48
|
it "should accept pathanme as filename" do
|
49
|
-
mock(
|
49
|
+
mock(File).open(pathname.to_s, File::WRONLY|File::APPEND|File::CREAT) { devnull }
|
50
50
|
|
51
|
-
adapter.write(
|
51
|
+
adapter.write(event)
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
55
|
-
context
|
55
|
+
context "#sync" do
|
56
56
|
let(:adapter) { Yell::Adapters::File.new }
|
57
57
|
|
58
58
|
it "should sync by default" do
|
59
|
-
mock(
|
59
|
+
mock(devnull).sync=(true)
|
60
60
|
|
61
|
-
adapter.write(
|
61
|
+
adapter.write(event)
|
62
62
|
end
|
63
63
|
|
64
64
|
it "pass the option to File" do
|
65
65
|
adapter.sync = false
|
66
66
|
|
67
|
-
mock(
|
67
|
+
mock(devnull).sync=(false)
|
68
68
|
|
69
|
-
adapter.write(
|
69
|
+
adapter.write(event)
|
70
70
|
end
|
71
71
|
end
|
72
72
|
end
|