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.
@@ -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