ougai 1.6.3 → 1.6.4
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 +4 -4
- data/Gemfile +1 -0
- data/Gemfile.lock +3 -1
- data/lib/ougai/formatters/bunyan.rb +2 -17
- data/lib/ougai/formatters/for_json.rb +26 -1
- data/lib/ougai/formatters/pino.rb +3 -18
- data/lib/ougai/formatters/readable.rb +1 -2
- data/lib/ougai/version.rb +1 -1
- data/spec/formatters/base_spec.rb +13 -13
- data/spec/formatters/bunyan_spec.rb +90 -75
- data/spec/formatters/pino_spec.rb +109 -83
- data/spec/formatters/readable_spec.rb +19 -0
- data/spec/logging_spec.rb +39 -3
- data/spec/spec_helper.rb +71 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 023fe0a75fea490d495f73f3ba484240d1b9de15
|
4
|
+
data.tar.gz: e91f1dbf146eafb6e889b2a8efd87e93c13da3c1
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 27498f3e30636bc343f07d70c088c5801f72d859c93039505f7d566a5c73c0c4443486f6a3d2075ccae1dd7cee38fa009d64413b0d8f3f835e6bd07bd70c7752
|
7
|
+
data.tar.gz: f6600fda8275ffd90f48a0720c768c64cc7d8e0e35c9992dd8d3c496910d64160a445525c53ad6ce0449068d2571d7b5192ec3e23be9ef1cbb93d71ee72e1b0d
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
ougai (1.6.
|
4
|
+
ougai (1.6.4)
|
5
5
|
oj (~> 3.4)
|
6
6
|
|
7
7
|
GEM
|
@@ -31,6 +31,7 @@ GEM
|
|
31
31
|
json (>= 1.8, < 3)
|
32
32
|
simplecov-html (~> 0.10.0)
|
33
33
|
simplecov-html (0.10.1)
|
34
|
+
timecop (0.9.1)
|
34
35
|
yard (0.9.12)
|
35
36
|
|
36
37
|
PLATFORMS
|
@@ -43,6 +44,7 @@ DEPENDENCIES
|
|
43
44
|
rake (~> 10.0)
|
44
45
|
rspec (~> 3.0)
|
45
46
|
simplecov
|
47
|
+
timecop
|
46
48
|
yard
|
47
49
|
|
48
50
|
BUNDLED WITH
|
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'ougai/formatters/base'
|
2
|
-
require 'oj'
|
3
2
|
|
4
3
|
module Ougai
|
5
4
|
module Formatters
|
6
5
|
# A JSON formatter compatible with node-bunyan
|
7
|
-
# @attr [Boolean] jsonize Whether log should converts JSON
|
8
|
-
# @attr [Boolean] with_newline Whether tailing NL should be appended
|
9
6
|
class Bunyan < Base
|
10
7
|
include ForJson
|
11
8
|
|
12
|
-
attr_accessor :jsonize, :with_newline
|
13
|
-
|
14
9
|
# Intialize a formatter
|
15
10
|
# @param [String] app_name application name (execution program name if nil)
|
16
11
|
# @param [String] hostname hostname (hostname if nil)
|
@@ -23,8 +18,7 @@ module Ougai
|
|
23
18
|
def initialize(app_name = nil, hostname = nil, opts = {})
|
24
19
|
aname, hname, opts = Base.parse_new_params([app_name, hostname, opts])
|
25
20
|
super(aname, hname, opts)
|
26
|
-
|
27
|
-
@with_newline = opts.fetch(:with_newline, true)
|
21
|
+
init_opts_for_json(opts)
|
28
22
|
end
|
29
23
|
|
30
24
|
def _call(severity, time, progname, data)
|
@@ -38,17 +32,8 @@ module Ougai
|
|
38
32
|
}.merge(data))
|
39
33
|
end
|
40
34
|
|
41
|
-
|
42
|
-
|
43
|
-
OJ_OPTIONS = { mode: :custom, time_format: :xmlschema,
|
44
|
-
use_as_json: true, use_to_hash: true, use_to_json: true }
|
45
|
-
|
46
|
-
def dump(data)
|
47
|
-
return data unless @jsonize
|
35
|
+
def convert_time(data)
|
48
36
|
data[:time] = format_datetime(data[:time])
|
49
|
-
str = Oj.dump(data, OJ_OPTIONS)
|
50
|
-
str << "\n" if @with_newline
|
51
|
-
str
|
52
37
|
end
|
53
38
|
end
|
54
39
|
end
|
@@ -1,6 +1,19 @@
|
|
1
|
+
require 'oj'
|
2
|
+
|
1
3
|
module Ougai
|
2
|
-
# The features for JSON
|
4
|
+
# The features for JSON formatter
|
5
|
+
# @attr [Boolean] jsonize Whether log should converts JSON
|
6
|
+
# @attr [Boolean] with_newline Whether tailing NL should be appended
|
3
7
|
module Formatters::ForJson
|
8
|
+
attr_accessor :jsonize, :with_newline
|
9
|
+
|
10
|
+
protected
|
11
|
+
|
12
|
+
def init_opts_for_json(opts)
|
13
|
+
@jsonize = opts.fetch(:jsonize, true)
|
14
|
+
@with_newline = opts.fetch(:with_newline, true)
|
15
|
+
end
|
16
|
+
|
4
17
|
def to_level(severity)
|
5
18
|
case severity
|
6
19
|
when 'TRACE'
|
@@ -19,5 +32,17 @@ module Ougai
|
|
19
32
|
70
|
20
33
|
end
|
21
34
|
end
|
35
|
+
|
36
|
+
OJ_OPTIONS = { mode: :custom, time_format: :xmlschema,
|
37
|
+
use_as_json: true, use_to_hash: true, use_to_json: true }
|
38
|
+
|
39
|
+
# requires convert_time(data) method
|
40
|
+
def dump(data)
|
41
|
+
return data unless @jsonize
|
42
|
+
convert_time(data)
|
43
|
+
str = Oj.dump(data, OJ_OPTIONS)
|
44
|
+
str << "\n" if @with_newline
|
45
|
+
str
|
46
|
+
end
|
22
47
|
end
|
23
48
|
end
|
@@ -1,16 +1,11 @@
|
|
1
1
|
require 'ougai/formatters/base'
|
2
|
-
require 'oj'
|
3
2
|
|
4
3
|
module Ougai
|
5
4
|
module Formatters
|
6
5
|
# A JSON formatter compatible with pino
|
7
|
-
# @attr [Boolean] jsonize Whether log should converts JSON
|
8
|
-
# @attr [Boolean] with_newline Whether tailing NL should be appended
|
9
6
|
class Pino < Base
|
10
7
|
include ForJson
|
11
8
|
|
12
|
-
attr_accessor :jsonize, :with_newline
|
13
|
-
|
14
9
|
# Intialize a formatter
|
15
10
|
# @param [String] app_name application name (execution program name if nil)
|
16
11
|
# @param [String] hostname hostname (hostname if nil)
|
@@ -23,8 +18,7 @@ module Ougai
|
|
23
18
|
def initialize(app_name = nil, hostname = nil, opts = {})
|
24
19
|
aname, hname, opts = Base.parse_new_params([app_name, hostname, opts])
|
25
20
|
super(aname, hname, opts)
|
26
|
-
|
27
|
-
@with_newline = opts.fetch(:with_newline, true)
|
21
|
+
init_opts_for_json(opts)
|
28
22
|
@trace_indent = opts.fetch(:trace_indent, 4)
|
29
23
|
@serialize_backtrace = true
|
30
24
|
end
|
@@ -45,8 +39,6 @@ module Ougai
|
|
45
39
|
}.merge(data))
|
46
40
|
end
|
47
41
|
|
48
|
-
private
|
49
|
-
|
50
42
|
def flat_err(data)
|
51
43
|
return unless data.key?(:err)
|
52
44
|
err = data.delete(:err)
|
@@ -58,15 +50,8 @@ module Ougai
|
|
58
50
|
data[:stack] ||= stack
|
59
51
|
end
|
60
52
|
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
def dump(data)
|
65
|
-
return data unless @jsonize
|
66
|
-
data[:time] = data[:time].to_i * 1000
|
67
|
-
str = Oj.dump(data, OJ_OPTIONS)
|
68
|
-
str << "\n" if @with_newline
|
69
|
-
str
|
53
|
+
def convert_time(data)
|
54
|
+
data[:time] = (data[:time].to_f * 1000).to_i
|
70
55
|
end
|
71
56
|
end
|
72
57
|
end
|
@@ -14,7 +14,6 @@ module Ougai
|
|
14
14
|
# @param [Hash] opts the initial values of attributes
|
15
15
|
# @option opts [String] :trace_indent (4) the value of trace_indent attribute
|
16
16
|
# @option opts [String] :trace_max_lines (100) the value of trace_max_lines attribute
|
17
|
-
# @option opts [String] :serialize_backtrace (true) the value of serialize_backtrace attribute
|
18
17
|
# @option opts [String] :plain (false) the value of plain attribute
|
19
18
|
# @option opts [String] :excluded_fields ([]) the value of excluded_fields attribute
|
20
19
|
def initialize(app_name = nil, hostname = nil, opts = {})
|
@@ -39,7 +38,7 @@ module Ougai
|
|
39
38
|
end
|
40
39
|
|
41
40
|
def serialize_backtrace=(value)
|
42
|
-
raise
|
41
|
+
raise NotImplementedError, 'Not support serialize_backtrace'
|
43
42
|
end
|
44
43
|
|
45
44
|
protected
|
data/lib/ougai/version.rb
CHANGED
@@ -4,8 +4,8 @@ describe Ougai::Formatters::Base do
|
|
4
4
|
subject { described_class.new(app_name, hostname) }
|
5
5
|
|
6
6
|
context 'default' do
|
7
|
-
let
|
8
|
-
let
|
7
|
+
let!(:app_name) { nil }
|
8
|
+
let!(:hostname) { nil }
|
9
9
|
|
10
10
|
it 'has datetime format default ISO8601' do
|
11
11
|
expect(subject.datetime_format).to match(/^\%FT\%T\.\%3N(Z|\%\:z)$/)
|
@@ -22,8 +22,8 @@ describe Ougai::Formatters::Base do
|
|
22
22
|
end
|
23
23
|
|
24
24
|
context 'without arguments and hostname contains a UTF-8 char' do
|
25
|
-
let
|
26
|
-
let
|
25
|
+
let!(:app_name) { nil }
|
26
|
+
let!(:hostname) { nil }
|
27
27
|
|
28
28
|
it 'has default app_name and default hostname' do
|
29
29
|
myhostname = "Taro\xE2\x80\x99s-MacBook".force_encoding('ASCII-8BIT')
|
@@ -34,8 +34,8 @@ describe Ougai::Formatters::Base do
|
|
34
34
|
end
|
35
35
|
|
36
36
|
context 'with app_name' do
|
37
|
-
let
|
38
|
-
let
|
37
|
+
let!(:app_name) { 'myapp' }
|
38
|
+
let!(:hostname) { nil }
|
39
39
|
|
40
40
|
it 'has specified app_name and default hostname' do
|
41
41
|
myhostname = "Hanako's PC".encode('ASCII-8BIT')
|
@@ -46,8 +46,8 @@ describe Ougai::Formatters::Base do
|
|
46
46
|
end
|
47
47
|
|
48
48
|
context 'with hostname' do
|
49
|
-
let
|
50
|
-
let
|
49
|
+
let!(:app_name) { nil }
|
50
|
+
let!(:hostname) { 'myhost' }
|
51
51
|
|
52
52
|
it 'has default app_name and specified hostname' do
|
53
53
|
expect(subject.app_name).to eq('rspec')
|
@@ -56,8 +56,8 @@ describe Ougai::Formatters::Base do
|
|
56
56
|
end
|
57
57
|
|
58
58
|
context 'with app_name and hostname' do
|
59
|
-
let
|
60
|
-
let
|
59
|
+
let!(:app_name) { 'myapp' }
|
60
|
+
let!(:hostname) { 'myhost' }
|
61
61
|
|
62
62
|
it 'has specified app_name and specified hostname' do
|
63
63
|
expect(subject.app_name).to eq('myapp')
|
@@ -66,9 +66,9 @@ describe Ougai::Formatters::Base do
|
|
66
66
|
end
|
67
67
|
|
68
68
|
describe '#serialize_exc' do
|
69
|
-
let
|
70
|
-
let
|
71
|
-
let
|
69
|
+
let!(:app_name) { 'myapp' }
|
70
|
+
let!(:hostname) { 'myhost' }
|
71
|
+
let!(:errmsg) { 'dummy error' }
|
72
72
|
|
73
73
|
it 'returning data with stack as String' do
|
74
74
|
begin
|
@@ -10,130 +10,145 @@ describe Ougai::Formatters::Bunyan do
|
|
10
10
|
}
|
11
11
|
end
|
12
12
|
|
13
|
+
let(:stack) { "error1.rb\n error2.rb" }
|
14
|
+
|
13
15
|
let(:err) do
|
14
16
|
{
|
15
17
|
name: 'DummyError',
|
16
18
|
message: 'it is dummy.',
|
17
|
-
stack:
|
19
|
+
stack: stack
|
18
20
|
}
|
19
21
|
end
|
20
22
|
|
21
23
|
let(:formatter) { described_class.new }
|
22
24
|
|
23
|
-
|
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
|
+
}
|
25
37
|
|
26
|
-
|
27
|
-
|
28
|
-
expect(fmt.app_name).to eq(appname)
|
29
|
-
end
|
30
|
-
end
|
38
|
+
describe '#call' do
|
39
|
+
subject { formatter.call(severity, Time.now, nil, data) }
|
31
40
|
|
32
|
-
|
33
|
-
|
41
|
+
context 'jsonize is true and with_newline is true' do
|
42
|
+
let!(:severity) { 'DEBUG' }
|
34
43
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
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
|
40
50
|
end
|
41
|
-
end
|
42
51
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
52
|
+
context 'jsonize is false' do
|
53
|
+
before do
|
54
|
+
formatter.jsonize = false
|
55
|
+
end
|
47
56
|
|
48
|
-
|
49
|
-
|
57
|
+
context 'when severity is TRACE' do
|
58
|
+
let!(:severity) { 'TRACE' }
|
50
59
|
|
51
|
-
|
52
|
-
|
53
|
-
|
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
|
54
64
|
end
|
55
|
-
end
|
56
65
|
|
57
|
-
|
58
|
-
|
66
|
+
context 'when severity is DEBUG' do
|
67
|
+
let!(:severity) { 'DEBUG' }
|
59
68
|
|
60
|
-
|
61
|
-
|
62
|
-
|
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
|
63
73
|
end
|
64
|
-
end
|
65
74
|
|
66
|
-
|
67
|
-
|
75
|
+
context 'when severity is INFO' do
|
76
|
+
let!(:severity) { 'INFO' }
|
68
77
|
|
69
|
-
|
70
|
-
|
71
|
-
|
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
|
72
82
|
end
|
73
|
-
end
|
74
83
|
|
75
|
-
|
76
|
-
|
84
|
+
context 'when severity is WARN' do
|
85
|
+
let!(:severity) { 'WARN' }
|
77
86
|
|
78
|
-
|
79
|
-
|
80
|
-
|
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
|
81
91
|
end
|
82
|
-
end
|
83
92
|
|
84
|
-
|
85
|
-
|
93
|
+
context 'when severity is ERROR' do
|
94
|
+
let!(:severity) { 'ERROR' }
|
95
|
+
|
96
|
+
before { data.merge!({ err: err }) }
|
86
97
|
|
87
|
-
|
88
|
-
|
89
|
-
|
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
|
90
102
|
end
|
91
|
-
end
|
92
103
|
|
93
|
-
|
94
|
-
|
104
|
+
context 'when severity is FATAL' do
|
105
|
+
let!(:severity) { 'FATAL' }
|
106
|
+
let!(:data) do
|
107
|
+
{ msg: 'TheEnd', err: err }
|
108
|
+
end
|
95
109
|
|
96
|
-
|
97
|
-
|
98
|
-
|
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
|
99
114
|
end
|
100
|
-
end
|
101
115
|
|
102
|
-
|
103
|
-
|
116
|
+
context 'when severity is UNKNOWN' do
|
117
|
+
let!(:severity) { 'ANY' }
|
118
|
+
let!(:data) do
|
119
|
+
{ msg: 'unknown msg' }
|
120
|
+
end
|
104
121
|
|
105
|
-
|
106
|
-
|
122
|
+
it 'includes valid hash' do
|
123
|
+
expect(subject).to include(pid: $$, level: 70, msg: 'unknown msg', v: 0)
|
124
|
+
end
|
107
125
|
end
|
108
126
|
end
|
109
|
-
end
|
110
127
|
|
111
|
-
|
112
|
-
|
113
|
-
formatter.with_newline = false
|
114
|
-
end
|
128
|
+
context 'with_newline is false' do
|
129
|
+
let!(:severity) { 'INFO' }
|
115
130
|
|
116
|
-
|
131
|
+
before do
|
132
|
+
formatter.with_newline = false
|
133
|
+
end
|
117
134
|
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
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
|
123
141
|
end
|
124
142
|
end
|
125
143
|
|
126
144
|
describe '#datetime_format' do
|
127
|
-
subject do
|
128
|
-
formatter.call('DEBUG', Time.now, nil, data)
|
129
|
-
end
|
130
|
-
|
131
145
|
context 'is time AM/PM format' do
|
132
146
|
before do
|
133
147
|
formatter.datetime_format = '%I:%M:%S %p'
|
134
148
|
end
|
135
149
|
|
136
150
|
it 'applys output' do
|
151
|
+
subject = formatter.call('DEBUG', Time.now, nil, data)
|
137
152
|
result = JSON.parse(subject, symbolize_names: true)
|
138
153
|
expect(result[:time]).to match(/^\d{2}:\d{2}:\d{2} [AP]M$/)
|
139
154
|
end
|
@@ -10,127 +10,153 @@ describe Ougai::Formatters::Pino do
|
|
10
10
|
}
|
11
11
|
end
|
12
12
|
|
13
|
+
let(:stack) { "error1.rb\n error2.rb" }
|
14
|
+
|
13
15
|
let(:err) do
|
14
16
|
{
|
15
17
|
name: 'DummyError',
|
16
18
|
message: 'it is dummy.',
|
17
|
-
stack:
|
19
|
+
stack: stack
|
18
20
|
}
|
19
21
|
end
|
20
22
|
|
21
23
|
let(:formatter) { described_class.new }
|
22
24
|
|
23
|
-
|
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
|
+
}
|
25
37
|
|
26
|
-
|
27
|
-
|
28
|
-
expect(fmt.app_name).to eq(appname)
|
29
|
-
end
|
30
|
-
end
|
38
|
+
describe '#call' do
|
39
|
+
let!(:time_epoc_msec) { 1518710101026 }
|
31
40
|
|
32
|
-
|
33
|
-
|
41
|
+
before { Timecop.freeze(Time.at(time_epoc_msec / 1000.0)) }
|
42
|
+
after { Timecop.return }
|
34
43
|
|
35
|
-
|
36
|
-
expect(subject).to end_with("\n")
|
37
|
-
result = JSON.parse(subject.chomp, symbolize_names: true)
|
38
|
-
expect(result).to include(data.merge(level: 20))
|
39
|
-
expect(result[:time]).to be > 1518710101026
|
40
|
-
end
|
41
|
-
end
|
44
|
+
subject { formatter.call(severity, Time.now, nil, data) }
|
42
45
|
|
43
|
-
|
44
|
-
|
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
|
46
54
|
end
|
47
55
|
|
48
|
-
context '
|
49
|
-
|
56
|
+
context 'jsonize is false' do
|
57
|
+
let!(:time) { Time.at(time_epoc_msec / 1000.0) }
|
50
58
|
|
51
|
-
|
52
|
-
|
53
|
-
expect(subject[:time]).to be_an_instance_of(Time)
|
59
|
+
before do
|
60
|
+
formatter.jsonize = false
|
54
61
|
end
|
55
|
-
end
|
56
62
|
|
57
|
-
|
58
|
-
|
63
|
+
context 'when severity is TRACE' do
|
64
|
+
let!(:severity) { 'TRACE' }
|
59
65
|
|
60
|
-
|
61
|
-
|
62
|
-
|
66
|
+
it 'includes valid hash' do
|
67
|
+
expect(subject).to include(data.merge(pid: $$, level: 10, time: time, v: 1))
|
68
|
+
end
|
63
69
|
end
|
64
|
-
end
|
65
70
|
|
66
|
-
|
67
|
-
|
71
|
+
context 'when severity is DEBUG' do
|
72
|
+
let!(:severity) { 'DEBUG' }
|
68
73
|
|
69
|
-
|
70
|
-
|
71
|
-
|
74
|
+
it 'includes valid hash' do
|
75
|
+
expect(subject).to include(data.merge(pid: $$, level: 20, time: time, v: 1))
|
76
|
+
end
|
72
77
|
end
|
73
|
-
end
|
74
78
|
|
75
|
-
|
76
|
-
|
79
|
+
context 'when severity is INFO' do
|
80
|
+
let!(:severity) { 'INFO' }
|
77
81
|
|
78
|
-
|
79
|
-
|
80
|
-
|
82
|
+
it 'includes valid hash' do
|
83
|
+
expect(subject).to include(data.merge(pid: $$, level: 30, time: time, v: 1))
|
84
|
+
end
|
81
85
|
end
|
82
|
-
end
|
83
86
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
it 'includes valid hash' do
|
91
|
-
expect(subject).to include({
|
92
|
-
level: 50, type: 'Error',
|
93
|
-
msg: 'it is dummy.',
|
94
|
-
stack: "DummyError: it is dummy.\n error1.rb\n error2.rb"
|
95
|
-
})
|
96
|
-
expect(subject[:time]).to be_an_instance_of(Time)
|
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
|
97
93
|
end
|
98
|
-
end
|
99
94
|
|
100
|
-
|
101
|
-
|
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
|
102
112
|
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
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
|
110
133
|
end
|
111
|
-
end
|
112
134
|
|
113
|
-
|
114
|
-
|
135
|
+
context 'when severity is UNKNOWN' do
|
136
|
+
let!(:severity) { 'ANY' }
|
115
137
|
|
116
|
-
|
117
|
-
|
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
|
118
145
|
end
|
119
146
|
end
|
120
|
-
end
|
121
147
|
|
122
|
-
|
123
|
-
|
124
|
-
formatter.with_newline = false
|
125
|
-
end
|
148
|
+
context 'with_newline is false' do
|
149
|
+
let!(:severity) { 'INFO' }
|
126
150
|
|
127
|
-
|
151
|
+
before do
|
152
|
+
formatter.with_newline = false
|
153
|
+
end
|
128
154
|
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
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
|
134
160
|
end
|
135
161
|
end
|
136
162
|
|
@@ -22,6 +22,19 @@ describe Ougai::Formatters::Readable do
|
|
22
22
|
|
23
23
|
let(:formatter) { described_class.new }
|
24
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
|
+
|
25
38
|
context 'when severity is TRACE' do
|
26
39
|
subject { formatter.call('TRACE', Time.now, nil, data) }
|
27
40
|
|
@@ -120,4 +133,10 @@ describe Ougai::Formatters::Readable do
|
|
120
133
|
end
|
121
134
|
end
|
122
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
|
123
142
|
end
|
data/spec/logging_spec.rb
CHANGED
@@ -1,12 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Ougai::Logging do
|
4
|
-
|
5
|
-
|
4
|
+
subject do
|
5
|
+
m = described_class
|
6
|
+
Class.new { include m }.new
|
7
|
+
end
|
6
8
|
|
9
|
+
describe '#weak_merge!' do
|
7
10
|
it 'merges with unique elements in array' do
|
8
11
|
result = nil
|
9
|
-
|
12
|
+
subject.instance_eval do
|
10
13
|
result = weak_merge!({ foo: [1, 2], bar: 'base', baz: ['A'] },
|
11
14
|
{ foo: [2, 3], bar: 'inferior', baz: ['B'] })
|
12
15
|
end
|
@@ -15,4 +18,37 @@ describe Ougai::Logging do
|
|
15
18
|
expect(result[:baz]).to eq(['B', 'A'])
|
16
19
|
end
|
17
20
|
end
|
21
|
+
|
22
|
+
describe '#child' do
|
23
|
+
let!(:fields) { double('fields') }
|
24
|
+
let!(:child_logger) { double('child logger') }
|
25
|
+
|
26
|
+
context 'block is not given' do
|
27
|
+
it 'returns child logger' do
|
28
|
+
expect(Ougai::ChildLogger).to receive(:new).with(subject, fields).and_return(child_logger)
|
29
|
+
expect(subject.child(fields)).to eq(child_logger)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context 'block is given' do
|
34
|
+
it 'passes child logger' do
|
35
|
+
expect(Ougai::ChildLogger).to receive(:new).with(subject, fields).and_return(child_logger)
|
36
|
+
subject.child(fields) do |cl|
|
37
|
+
expect(cl).to eq(child_logger)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
describe '#chain' do
|
44
|
+
it 'is not implemented' do
|
45
|
+
expect{ subject.chain(:arg1, :arg2, :arg3, :arg4) }.to raise_error(NotImplementedError)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
describe '#append' do
|
50
|
+
it 'is not implemented' do
|
51
|
+
expect{ subject.send(:append, :arg1, :arg2) }.to raise_error(NotImplementedError)
|
52
|
+
end
|
53
|
+
end
|
18
54
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -1,3 +1,4 @@
|
|
1
|
+
require 'timecop'
|
1
2
|
require 'simplecov'
|
2
3
|
SimpleCov.start do
|
3
4
|
add_filter "/spec/"
|
@@ -5,3 +6,73 @@ end
|
|
5
6
|
|
6
7
|
$LOAD_PATH.unshift File.expand_path('../../lib', __FILE__)
|
7
8
|
require 'ougai'
|
9
|
+
|
10
|
+
RSpec.shared_examples 'formatter#initialize' do |params|
|
11
|
+
describe '#initialize' do
|
12
|
+
let(:app_name) { 'dummy app name' }
|
13
|
+
let(:hostname) { 'dummyhost' }
|
14
|
+
let(:options) { params[:options] }
|
15
|
+
|
16
|
+
subject { described_class.new(*arguments) }
|
17
|
+
|
18
|
+
context 'with app_name' do
|
19
|
+
let!(:arguments) { [app_name] }
|
20
|
+
|
21
|
+
it 'creates an instance with valid app_name and hostname' do
|
22
|
+
expect(subject.app_name).to eq(app_name)
|
23
|
+
expect(subject.hostname).to eq(Socket.gethostname.force_encoding('UTF-8'))
|
24
|
+
params[:default_opts].each do |key, val|
|
25
|
+
expect(subject.send(key)).to eq(val)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
context 'with options' do
|
31
|
+
let!(:arguments) { [options] }
|
32
|
+
|
33
|
+
it 'creates an instance with valid values for attributes' do
|
34
|
+
expect(subject.app_name).to eq('rspec')
|
35
|
+
expect(subject.hostname).to eq(Socket.gethostname.force_encoding('UTF-8'))
|
36
|
+
options.each do |key, val|
|
37
|
+
expect(subject.send(key)).to eq(val)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'with app_name and hostname' do
|
43
|
+
let!(:arguments) { [app_name, hostname] }
|
44
|
+
|
45
|
+
it 'creates an instance with valid app_name and hostname' do
|
46
|
+
expect(subject.app_name).to eq(app_name)
|
47
|
+
expect(subject.hostname).to eq(hostname)
|
48
|
+
params[:default_opts].each do |key, val|
|
49
|
+
expect(subject.send(key)).to eq(val)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
context 'with app_name and options' do
|
55
|
+
let!(:arguments) { [app_name, options] }
|
56
|
+
|
57
|
+
it 'creates an instance with valid values for attributes' do
|
58
|
+
expect(subject.app_name).to eq(app_name)
|
59
|
+
expect(subject.hostname).to eq(Socket.gethostname.force_encoding('UTF-8'))
|
60
|
+
options.each do |key, val|
|
61
|
+
expect(subject.send(key)).to eq(val)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
context 'with app_name, hostname and options' do
|
67
|
+
let!(:arguments) { [app_name, hostname, options] }
|
68
|
+
|
69
|
+
it 'creates an instance with valid values for attributes' do
|
70
|
+
expect(subject.app_name).to eq(app_name)
|
71
|
+
expect(subject.hostname).to eq(hostname)
|
72
|
+
options.each do |key, val|
|
73
|
+
expect(subject.send(key)).to eq(val)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ougai
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.6.
|
4
|
+
version: 1.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Toshimitsu Takahashi
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2018-02-
|
11
|
+
date: 2018-02-18 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oj
|