ougai 1.7.1-java
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/Gemfile +11 -0
- data/Gemfile.lock +51 -0
- data/LICENSE.txt +21 -0
- data/README.md +363 -0
- data/Rakefile +17 -0
- data/lib/ougai.rb +11 -0
- data/lib/ougai/child_logger.rb +62 -0
- data/lib/ougai/formatters/base.rb +84 -0
- data/lib/ougai/formatters/bunyan.rb +42 -0
- data/lib/ougai/formatters/for_json.rb +46 -0
- data/lib/ougai/formatters/pino.rb +60 -0
- data/lib/ougai/formatters/readable.rb +96 -0
- data/lib/ougai/logger.rb +158 -0
- data/lib/ougai/logging.rb +125 -0
- data/lib/ougai/serializer.rb +15 -0
- data/lib/ougai/serializers/json_jr_jackson.rb +11 -0
- data/lib/ougai/serializers/json_oj.rb +14 -0
- data/lib/ougai/version.rb +5 -0
- data/spec/child_logger_spec.rb +439 -0
- data/spec/formatters/base_spec.rb +98 -0
- data/spec/formatters/bunyan_spec.rb +157 -0
- data/spec/formatters/pino_spec.rb +168 -0
- data/spec/formatters/readable_spec.rb +142 -0
- data/spec/logger_spec.rb +688 -0
- data/spec/logging_spec.rb +54 -0
- data/spec/ougai_spec.rb +7 -0
- data/spec/spec_helper.rb +78 -0
- metadata +139 -0
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ougai::Formatters::Base do
|
4
|
+
subject { described_class.new(app_name, hostname) }
|
5
|
+
|
6
|
+
context 'default' do
|
7
|
+
let!(:app_name) { nil }
|
8
|
+
let!(:hostname) { nil }
|
9
|
+
|
10
|
+
it 'has datetime format default ISO8601' do
|
11
|
+
expect(subject.datetime_format).to match(/^\%FT\%T\.\%3N(Z|\%\:z)$/)
|
12
|
+
end
|
13
|
+
|
14
|
+
it 'has datetime_format accessor' do
|
15
|
+
subject.datetime_format = '%I:%M:%S %p'
|
16
|
+
expect(subject.datetime_format).to eq('%I:%M:%S %p')
|
17
|
+
|
18
|
+
# revert default format by to set nil
|
19
|
+
subject.datetime_format = nil
|
20
|
+
expect(subject.datetime_format).to match(/^\%FT\%T\.\%3N(Z|\%\:z)$/)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
context 'without arguments and hostname contains a UTF-8 char' do
|
25
|
+
let!(:app_name) { nil }
|
26
|
+
let!(:hostname) { nil }
|
27
|
+
|
28
|
+
it 'has default app_name and default hostname' do
|
29
|
+
myhostname = "Taro\xE2\x80\x99s-MacBook".force_encoding('ASCII-8BIT')
|
30
|
+
allow(Socket).to receive(:gethostname).and_return(myhostname)
|
31
|
+
expect(subject.app_name).to eq('rspec')
|
32
|
+
expect(subject.hostname).to eq("Taro’s-MacBook")
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with app_name' do
|
37
|
+
let!(:app_name) { 'myapp' }
|
38
|
+
let!(:hostname) { nil }
|
39
|
+
|
40
|
+
it 'has specified app_name and default hostname' do
|
41
|
+
myhostname = "Hanako's PC".encode('ASCII-8BIT')
|
42
|
+
allow(Socket).to receive(:gethostname).and_return(myhostname)
|
43
|
+
expect(subject.app_name).to eq('myapp')
|
44
|
+
expect(subject.hostname).to eq("Hanako's PC")
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with hostname' do
|
49
|
+
let!(:app_name) { nil }
|
50
|
+
let!(:hostname) { 'myhost' }
|
51
|
+
|
52
|
+
it 'has default app_name and specified hostname' do
|
53
|
+
expect(subject.app_name).to eq('rspec')
|
54
|
+
expect(subject.hostname).to eq('myhost')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'with app_name and hostname' do
|
59
|
+
let!(:app_name) { 'myapp' }
|
60
|
+
let!(:hostname) { 'myhost' }
|
61
|
+
|
62
|
+
it 'has specified app_name and specified hostname' do
|
63
|
+
expect(subject.app_name).to eq('myapp')
|
64
|
+
expect(subject.hostname).to eq('myhost')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
describe '#serialize_exc' do
|
69
|
+
let!(:app_name) { 'myapp' }
|
70
|
+
let!(:hostname) { 'myhost' }
|
71
|
+
let!(:errmsg) { 'dummy error' }
|
72
|
+
|
73
|
+
it 'returning data with stack as String' do
|
74
|
+
begin
|
75
|
+
raise errmsg
|
76
|
+
rescue => e
|
77
|
+
result = subject.serialize_exc(e)
|
78
|
+
end
|
79
|
+
expect(result[:message]).to eq(errmsg)
|
80
|
+
expect(result[:stack]).to be_instance_of(String)
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'not serialize backtrace' do
|
84
|
+
it 'returning data with stack as Array' do
|
85
|
+
subject.serialize_backtrace = false
|
86
|
+
subject.trace_max_lines = 6
|
87
|
+
begin
|
88
|
+
raise errmsg
|
89
|
+
rescue => e
|
90
|
+
result = subject.serialize_exc(e)
|
91
|
+
end
|
92
|
+
expect(result[:message]).to eq(errmsg)
|
93
|
+
expect(result[:stack]).to be_instance_of(Array)
|
94
|
+
expect(result[:stack].size).to eq(6)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,157 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ougai::Formatters::Bunyan do
|
4
|
+
let(:data) do
|
5
|
+
{
|
6
|
+
msg: 'Log Message!',
|
7
|
+
status: 200,
|
8
|
+
method: 'GET',
|
9
|
+
path: '/'
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:stack) { "error1.rb\n error2.rb" }
|
14
|
+
|
15
|
+
let(:err) do
|
16
|
+
{
|
17
|
+
name: 'DummyError',
|
18
|
+
message: 'it is dummy.',
|
19
|
+
stack: stack
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:formatter) { described_class.new }
|
24
|
+
|
25
|
+
include_examples 'formatter#initialize',
|
26
|
+
default_opts: {
|
27
|
+
trace_indent: 2,
|
28
|
+
trace_max_lines: 100,
|
29
|
+
serialize_backtrace: true,
|
30
|
+
jsonize: true,
|
31
|
+
with_newline: true
|
32
|
+
},
|
33
|
+
options: {
|
34
|
+
jsonize: false,
|
35
|
+
with_newline: false
|
36
|
+
}
|
37
|
+
|
38
|
+
describe '#call' do
|
39
|
+
subject { formatter.call(severity, Time.now, nil, data) }
|
40
|
+
|
41
|
+
context 'jsonize is true and with_newline is true' do
|
42
|
+
let!(:severity) { 'DEBUG' }
|
43
|
+
|
44
|
+
it 'includes valid strings' do
|
45
|
+
expect(subject).to end_with("\n")
|
46
|
+
result = JSON.parse(subject.chomp, symbolize_names: true)
|
47
|
+
expect(result).to include(data.merge(pid: $$, level: 20, v: 0))
|
48
|
+
expect(result[:time]).to match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'jsonize is false' do
|
53
|
+
before do
|
54
|
+
formatter.jsonize = false
|
55
|
+
end
|
56
|
+
|
57
|
+
context 'when severity is TRACE' do
|
58
|
+
let!(:severity) { 'TRACE' }
|
59
|
+
|
60
|
+
it 'includes valid hash' do
|
61
|
+
expect(subject).to include(data.merge(pid: $$, level: 10, v: 0))
|
62
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'when severity is DEBUG' do
|
67
|
+
let!(:severity) { 'DEBUG' }
|
68
|
+
|
69
|
+
it 'includes valid hash' do
|
70
|
+
expect(subject).to include(data.merge(pid: $$, level: 20, v: 0))
|
71
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'when severity is INFO' do
|
76
|
+
let!(:severity) { 'INFO' }
|
77
|
+
|
78
|
+
it 'includes valid hash' do
|
79
|
+
expect(subject).to include(data.merge(pid: $$, level: 30, v: 0))
|
80
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
context 'when severity is WARN' do
|
85
|
+
let!(:severity) { 'WARN' }
|
86
|
+
|
87
|
+
it 'includes valid hash' do
|
88
|
+
expect(subject).to include(data.merge(pid: $$, level: 40, v: 0))
|
89
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
context 'when severity is ERROR' do
|
94
|
+
let!(:severity) { 'ERROR' }
|
95
|
+
|
96
|
+
before { data.merge!({ err: err }) }
|
97
|
+
|
98
|
+
it 'includes valid hash' do
|
99
|
+
expect(subject).to include(pid: $$, level: 50, v: 0, err: err)
|
100
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
104
|
+
context 'when severity is FATAL' do
|
105
|
+
let!(:severity) { 'FATAL' }
|
106
|
+
let!(:data) do
|
107
|
+
{ msg: 'TheEnd', err: err }
|
108
|
+
end
|
109
|
+
|
110
|
+
it 'includes valid hash' do
|
111
|
+
expect(subject).to include(pid: $$, level: 60, v: 0, err: err)
|
112
|
+
expect(subject[:time]).to be_an_instance_of(Time)
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
context 'when severity is UNKNOWN' do
|
117
|
+
let!(:severity) { 'ANY' }
|
118
|
+
let!(:data) do
|
119
|
+
{ msg: 'unknown msg' }
|
120
|
+
end
|
121
|
+
|
122
|
+
it 'includes valid hash' do
|
123
|
+
expect(subject).to include(pid: $$, level: 70, msg: 'unknown msg', v: 0)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
context 'with_newline is false' do
|
129
|
+
let!(:severity) { 'INFO' }
|
130
|
+
|
131
|
+
before do
|
132
|
+
formatter.with_newline = false
|
133
|
+
end
|
134
|
+
|
135
|
+
it 'includes valid strings' do
|
136
|
+
expect(subject).not_to end_with("\n")
|
137
|
+
result = JSON.parse(subject, symbolize_names: true)
|
138
|
+
expect(result).to include(data.merge(pid: $$, level: 30, v: 0))
|
139
|
+
expect(result[:time]).to match(/^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
describe '#datetime_format' do
|
145
|
+
context 'is time AM/PM format' do
|
146
|
+
before do
|
147
|
+
formatter.datetime_format = '%I:%M:%S %p'
|
148
|
+
end
|
149
|
+
|
150
|
+
it 'applys output' do
|
151
|
+
subject = formatter.call('DEBUG', Time.now, nil, data)
|
152
|
+
result = JSON.parse(subject, symbolize_names: true)
|
153
|
+
expect(result[:time]).to match(/^\d{2}:\d{2}:\d{2} [AP]M$/)
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
@@ -0,0 +1,168 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ougai::Formatters::Pino do
|
4
|
+
let(:data) do
|
5
|
+
{
|
6
|
+
msg: 'Log Message!',
|
7
|
+
status: 200,
|
8
|
+
method: 'GET',
|
9
|
+
path: '/'
|
10
|
+
}
|
11
|
+
end
|
12
|
+
|
13
|
+
let(:stack) { "error1.rb\n error2.rb" }
|
14
|
+
|
15
|
+
let(:err) do
|
16
|
+
{
|
17
|
+
name: 'DummyError',
|
18
|
+
message: 'it is dummy.',
|
19
|
+
stack: stack
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:formatter) { described_class.new }
|
24
|
+
|
25
|
+
include_examples 'formatter#initialize',
|
26
|
+
default_opts: {
|
27
|
+
trace_indent: 4,
|
28
|
+
trace_max_lines: 100,
|
29
|
+
serialize_backtrace: true,
|
30
|
+
jsonize: true,
|
31
|
+
with_newline: true
|
32
|
+
},
|
33
|
+
options: {
|
34
|
+
jsonize: false,
|
35
|
+
with_newline: false
|
36
|
+
}
|
37
|
+
|
38
|
+
describe '#call' do
|
39
|
+
let!(:time_epoc_msec) { 1518710101026 }
|
40
|
+
|
41
|
+
before { Timecop.freeze(Time.at(time_epoc_msec / 1000.0)) }
|
42
|
+
after { Timecop.return }
|
43
|
+
|
44
|
+
subject { formatter.call(severity, Time.now, nil, data) }
|
45
|
+
|
46
|
+
context 'jsonize is true and with_newline is true' do
|
47
|
+
let!(:severity) { 'DEBUG' }
|
48
|
+
|
49
|
+
it 'includes valid strings' do
|
50
|
+
expect(subject).to end_with("\n")
|
51
|
+
result = JSON.parse(subject.chomp, symbolize_names: true)
|
52
|
+
expect(result).to include(data.merge(pid: $$, level: 20, time: time_epoc_msec, v: 1))
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'jsonize is false' do
|
57
|
+
let!(:time) { Time.at(time_epoc_msec / 1000.0) }
|
58
|
+
|
59
|
+
before do
|
60
|
+
formatter.jsonize = false
|
61
|
+
end
|
62
|
+
|
63
|
+
context 'when severity is TRACE' do
|
64
|
+
let!(:severity) { 'TRACE' }
|
65
|
+
|
66
|
+
it 'includes valid hash' do
|
67
|
+
expect(subject).to include(data.merge(pid: $$, level: 10, time: time, v: 1))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
context 'when severity is DEBUG' do
|
72
|
+
let!(:severity) { 'DEBUG' }
|
73
|
+
|
74
|
+
it 'includes valid hash' do
|
75
|
+
expect(subject).to include(data.merge(pid: $$, level: 20, time: time, v: 1))
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
context 'when severity is INFO' do
|
80
|
+
let!(:severity) { 'INFO' }
|
81
|
+
|
82
|
+
it 'includes valid hash' do
|
83
|
+
expect(subject).to include(data.merge(pid: $$, level: 30, time: time, v: 1))
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
context 'when severity is WARN' do
|
88
|
+
let!(:severity) { 'WARN' }
|
89
|
+
|
90
|
+
it 'includes valid hash' do
|
91
|
+
expect(subject).to include(data.merge(pid: $$, level: 40, time: time, v: 1))
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
context 'when severity is ERROR' do
|
96
|
+
let!(:severity) { 'ERROR' }
|
97
|
+
|
98
|
+
before do
|
99
|
+
data.delete(:msg)
|
100
|
+
data.merge!({ err: err })
|
101
|
+
end
|
102
|
+
|
103
|
+
it 'includes valid hash' do
|
104
|
+
expect(subject).to include({
|
105
|
+
pid: $$, level: 50, time: time, v: 1,
|
106
|
+
type: 'Error',
|
107
|
+
msg: 'it is dummy.',
|
108
|
+
stack: "DummyError: it is dummy.\n #{stack}"
|
109
|
+
})
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
context 'when severity is FATAL and trace_indent = 2' do
|
114
|
+
let!(:severity) { 'FATAL' }
|
115
|
+
|
116
|
+
let!(:data) do
|
117
|
+
{ msg: 'TheEnd', err: err }
|
118
|
+
end
|
119
|
+
|
120
|
+
before do
|
121
|
+
formatter.trace_indent = 2
|
122
|
+
stack.gsub!(/ /, ' ')
|
123
|
+
end
|
124
|
+
|
125
|
+
it 'includes valid hash' do
|
126
|
+
expect(subject).to include({
|
127
|
+
pid: $$, level: 60, time: time, v: 1,
|
128
|
+
type: 'Error',
|
129
|
+
msg: 'TheEnd',
|
130
|
+
stack: "DummyError: it is dummy.\n #{stack}",
|
131
|
+
})
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
context 'when severity is UNKNOWN' do
|
136
|
+
let!(:severity) { 'ANY' }
|
137
|
+
|
138
|
+
let!(:data) do
|
139
|
+
{ msg: 'unknown msg' }
|
140
|
+
end
|
141
|
+
|
142
|
+
it 'includes valid hash' do
|
143
|
+
expect(subject).to include(pid: $$, level: 70, time: time, msg: 'unknown msg')
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
context 'with_newline is false' do
|
149
|
+
let!(:severity) { 'INFO' }
|
150
|
+
|
151
|
+
before do
|
152
|
+
formatter.with_newline = false
|
153
|
+
end
|
154
|
+
|
155
|
+
it 'includes valid strings' do
|
156
|
+
expect(subject).not_to end_with("\n")
|
157
|
+
result = JSON.parse(subject, symbolize_names: true)
|
158
|
+
expect(result).to include(data.merge(level: 30, time: time_epoc_msec))
|
159
|
+
end
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
describe '#datetime_format' do
|
164
|
+
it 'is not supported' do
|
165
|
+
expect{ formatter.datetime_format = '%I:%M:%S %p' }.to raise_error(NotImplementedError)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
end
|
@@ -0,0 +1,142 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Ougai::Formatters::Readable do
|
4
|
+
let!(:re_start_with_datetime) { /^\[\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}\.\d{3}(Z|[\+\-\:0-9]{4,6})\]/ }
|
5
|
+
|
6
|
+
let(:data) do
|
7
|
+
{
|
8
|
+
msg: 'Log Message!',
|
9
|
+
status: 200,
|
10
|
+
method: 'GET',
|
11
|
+
path: '/'
|
12
|
+
}
|
13
|
+
end
|
14
|
+
|
15
|
+
let(:err) do
|
16
|
+
{
|
17
|
+
name: 'DummyError',
|
18
|
+
message: 'it is dummy.',
|
19
|
+
stack: "error1.rb\n error2.rb"
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
let(:formatter) { described_class.new }
|
24
|
+
|
25
|
+
include_examples 'formatter#initialize',
|
26
|
+
default_opts: {
|
27
|
+
trace_indent: 4,
|
28
|
+
trace_max_lines: 100,
|
29
|
+
serialize_backtrace: true,
|
30
|
+
plain: false,
|
31
|
+
excluded_fields: []
|
32
|
+
},
|
33
|
+
options: {
|
34
|
+
plain: true,
|
35
|
+
excluded_fields: [:card_number]
|
36
|
+
}
|
37
|
+
|
38
|
+
context 'when severity is TRACE' do
|
39
|
+
subject { formatter.call('TRACE', Time.now, nil, data) }
|
40
|
+
|
41
|
+
it 'includes valid strings' do
|
42
|
+
expect(subject).to match(re_start_with_datetime)
|
43
|
+
expect(subject).to include("\e[0;34mTRACE\e[0m: Log Message!")
|
44
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include(':status => 200')
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'when severity is DEBUG' do
|
49
|
+
subject { formatter.call('DEBUG', Time.now, nil, data) }
|
50
|
+
|
51
|
+
it 'includes valid strings' do
|
52
|
+
expect(subject).to match(re_start_with_datetime)
|
53
|
+
expect(subject).to include("\e[0;37mDEBUG\e[0m: Log Message!")
|
54
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include(':status => 200')
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
context 'when severity is INFO' do
|
59
|
+
subject { formatter.call('INFO', Time.now, nil, data) }
|
60
|
+
|
61
|
+
it 'includes valid strings' do
|
62
|
+
expect(subject).to match(re_start_with_datetime)
|
63
|
+
expect(subject).to include("\e[0;36mINFO\e[0m: Log Message!")
|
64
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include(':method => "GET"')
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when severity is WARN' do
|
69
|
+
subject { formatter.call('WARN', Time.now, nil, data) }
|
70
|
+
|
71
|
+
it 'includes valid strings' do
|
72
|
+
expect(subject).to match(re_start_with_datetime)
|
73
|
+
expect(subject).to include("\e[0;33mWARN\e[0m: Log Message!")
|
74
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include(':path => "/"')
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'when severity is ERROR' do
|
79
|
+
subject { formatter.call('ERROR', Time.now, nil, data.merge({ err: err })) }
|
80
|
+
|
81
|
+
it 'includes valid strings' do
|
82
|
+
expect(subject).to match(re_start_with_datetime)
|
83
|
+
expect(subject).to include("\e[0;31mERROR\e[0m: Log Message!")
|
84
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include('DummyError (it is dummy.):')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'when severity is FATAL' do
|
89
|
+
subject { formatter.call('FATAL', Time.now, nil, { msg: 'TheEnd', err: err }) }
|
90
|
+
|
91
|
+
it 'includes valid strings' do
|
92
|
+
expect(subject).to match(re_start_with_datetime)
|
93
|
+
expect(subject).to include("\e[0;35mFATAL\e[0m: TheEnd")
|
94
|
+
expect(subject.gsub(/\e\[([;\d]+)?m/, '')).to include("error1.rb\n error2.rb")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'when severity is UNKNOWN' do
|
99
|
+
subject { formatter.call('ANY', Time.now, nil, { msg: 'unknown msg' }) }
|
100
|
+
|
101
|
+
it 'includes valid strings' do
|
102
|
+
expect(subject).to match(re_start_with_datetime)
|
103
|
+
expect(subject).to include("\e[0;32mANY\e[0m: unknown msg")
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
107
|
+
context 'when logger has excluded_fields' do
|
108
|
+
subject do
|
109
|
+
described_class.new(excluded_fields: [:status, :method]).call('DEBUG', Time.now, nil, data)
|
110
|
+
end
|
111
|
+
|
112
|
+
it 'includes valid strings' do
|
113
|
+
expect(subject).to include("\e[0;37mDEBUG\e[0m: Log Message!")
|
114
|
+
plain_subject = subject.gsub(/\e\[([;\d]+)?m/, '')
|
115
|
+
expect(plain_subject).to include(':path => "/"')
|
116
|
+
expect(plain_subject).not_to include(':status => 200')
|
117
|
+
expect(plain_subject).not_to include(':method => "GET"')
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
describe '#datetime_format' do
|
122
|
+
subject do
|
123
|
+
formatter.call('DEBUG', Time.now, nil, data)
|
124
|
+
end
|
125
|
+
|
126
|
+
context 'is time AM/PM format' do
|
127
|
+
before do
|
128
|
+
formatter.datetime_format = '%I:%M:%S %p'
|
129
|
+
end
|
130
|
+
|
131
|
+
it 'applys output' do
|
132
|
+
expect(subject).to match(/^\[\d{2}:\d{2}:\d{2} [AP]M\]/)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
137
|
+
describe '#serialize_backtrace' do
|
138
|
+
it 'is not supported' do
|
139
|
+
expect{ formatter.serialize_backtrace = false }.to raise_error(NotImplementedError)
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|