lenjador 1.2.1 → 2.1.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 +5 -5
- data/.rubocop.yml +41 -0
- data/.ruby-version +1 -1
- data/.travis.yml +1 -3
- data/Gemfile +1 -6
- data/Rakefile +6 -4
- data/benchmark/whitelisting.rb +7 -7
- data/lenjador.gemspec +21 -26
- data/lib/lenjador.rb +38 -23
- data/lib/lenjador/adapters.rb +9 -14
- data/lib/lenjador/adapters/stdout_adapter.rb +6 -9
- data/lib/lenjador/adapters/stdout_json_adapter.rb +10 -36
- data/lib/lenjador/null_logger.rb +7 -10
- data/lib/lenjador/preprocessors.rb +2 -0
- data/lib/lenjador/preprocessors/blacklist.rb +11 -9
- data/lib/lenjador/preprocessors/json_pointer_trie.rb +4 -2
- data/lib/lenjador/preprocessors/strategies/mask.rb +3 -1
- data/lib/lenjador/preprocessors/strategies/prune.rb +2 -0
- data/lib/lenjador/preprocessors/whitelist.rb +6 -6
- data/lib/lenjador/utils.rb +42 -43
- data/profiler/logs.rb +19 -0
- data/spec/lenjador/adapters/stdout_adapter_spec.rb +48 -0
- data/spec/lenjador/adapters/stdout_json_adapter_spec.rb +46 -0
- data/spec/{preprocessors → lenjador/preprocessors}/blacklist_spec.rb +18 -14
- data/spec/{preprocessors/json_pointer_trie.rb → lenjador/preprocessors/json_pointer_trie_spec.rb} +4 -4
- data/spec/lenjador/preprocessors/whitelist_spec.rb +319 -0
- data/spec/lenjador/utils_spec.rb +99 -0
- data/spec/lenjador_spec.rb +41 -33
- data/spec/spec_helper.rb +1 -1
- metadata +67 -24
- data/spec/adapters/stdout_adapter_spec.rb +0 -48
- data/spec/adapters/stdout_json_adapter_spec.rb +0 -62
- data/spec/preprocessors/whitelist_spec.rb +0 -335
- data/spec/utils_spec.rb +0 -84
@@ -0,0 +1,319 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
require_relative '../../../lib/lenjador/preprocessors/whitelist'
|
3
|
+
|
4
|
+
RSpec.describe Lenjador::Preprocessors::Whitelist do
|
5
|
+
context 'when :action is :mask or omitted' do
|
6
|
+
subject(:processed_data) { described_class.new(config).process(data) }
|
7
|
+
|
8
|
+
let(:config) { {pointers: pointers} }
|
9
|
+
let(:pointers) { [] }
|
10
|
+
let(:data) do
|
11
|
+
{
|
12
|
+
field: 'secret',
|
13
|
+
data: {
|
14
|
+
field: 'secret'
|
15
|
+
},
|
16
|
+
array: [{field: 'secret'}]
|
17
|
+
}
|
18
|
+
end
|
19
|
+
|
20
|
+
it 'masks all non-whitelisted fields' do
|
21
|
+
expect(processed_data).to eq(
|
22
|
+
field: '*****',
|
23
|
+
data: '*****',
|
24
|
+
array: '*****'
|
25
|
+
)
|
26
|
+
end
|
27
|
+
|
28
|
+
context 'when pointer has trailing slash' do
|
29
|
+
let(:pointers) { ['/field/'] }
|
30
|
+
|
31
|
+
it 'throws exception' do
|
32
|
+
expect { processed_data }.to raise_exception(Lenjador::Preprocessors::Whitelist::InvalidPointerFormatException)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
context 'with whitelisted field' do
|
37
|
+
let(:pointers) { ['/field'] }
|
38
|
+
|
39
|
+
it 'includes the field' do
|
40
|
+
expect(processed_data).to eq(
|
41
|
+
field: 'secret',
|
42
|
+
data: '*****',
|
43
|
+
array: '*****'
|
44
|
+
)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
context 'with whitelisted nested field' do
|
49
|
+
let(:pointers) { ['/data/field'] }
|
50
|
+
|
51
|
+
it 'includes nested field' do
|
52
|
+
expect(processed_data).to eq(
|
53
|
+
field: '*****',
|
54
|
+
data: {
|
55
|
+
field: 'secret'
|
56
|
+
},
|
57
|
+
array: '*****'
|
58
|
+
)
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'with whitelisted array element field' do
|
63
|
+
let(:pointers) { ['/array/0/field'] }
|
64
|
+
|
65
|
+
it 'includes array element' do
|
66
|
+
expect(processed_data).to eq(
|
67
|
+
field: '*****',
|
68
|
+
data: '*****',
|
69
|
+
array: [{field: 'secret'}]
|
70
|
+
)
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
context 'with whitelisted hash' do
|
75
|
+
it 'includes all whitelisted hash elements' do
|
76
|
+
source = {foo: {bar: 'baz'}}
|
77
|
+
target = {foo: {bar: 'baz'}}
|
78
|
+
expect(process(['/foo/~'], source)).to eq(target)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'does not include nested elements' do
|
82
|
+
source = {foo: {bar: {baz: 'asd'}}}
|
83
|
+
target = {foo: {bar: {baz: '*****'}}}
|
84
|
+
expect(process(['/foo/~'], source)).to eq(target)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'with whitelisted array elements field with wildcard' do
|
89
|
+
let(:data) do
|
90
|
+
{
|
91
|
+
array: [
|
92
|
+
{field: 'data1', secret: 'secret1'},
|
93
|
+
{field: 'data2', secret: 'secret2'}
|
94
|
+
]
|
95
|
+
}
|
96
|
+
end
|
97
|
+
let(:pointers) { ['/array/~/field'] }
|
98
|
+
|
99
|
+
it 'includes array elements field' do
|
100
|
+
expect(processed_data).to include(
|
101
|
+
array: [
|
102
|
+
{field: 'data1', secret: '*****'},
|
103
|
+
{field: 'data2', secret: '*****'}
|
104
|
+
]
|
105
|
+
)
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
context 'with whitelisted string array elements with wildcard' do
|
110
|
+
let(:data) do
|
111
|
+
{array: %w[secret secret]}
|
112
|
+
end
|
113
|
+
let(:pointers) { ['/array/~'] }
|
114
|
+
|
115
|
+
it 'includes array elements' do
|
116
|
+
expect(processed_data).to include(array: %w[secret secret])
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
context 'with whitelisted string array elements in an array with wildcard' do
|
121
|
+
let(:data) do
|
122
|
+
{
|
123
|
+
nested: [{array: %w[secret secret]}]
|
124
|
+
}
|
125
|
+
end
|
126
|
+
let(:pointers) { ['/nested/~/array/~'] }
|
127
|
+
|
128
|
+
it 'includes array elements' do
|
129
|
+
expect(processed_data).to include(nested: [{array: %w[secret secret]}])
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
context 'with whitelisted array element' do
|
134
|
+
let(:pointers) { ['/array/0'] }
|
135
|
+
|
136
|
+
it 'masks array element' do
|
137
|
+
expect(processed_data).to include(array: [{field: '*****'}])
|
138
|
+
end
|
139
|
+
end
|
140
|
+
|
141
|
+
context 'with whitelisted array' do
|
142
|
+
let(:pointers) { ['/array'] }
|
143
|
+
|
144
|
+
it 'masks array' do
|
145
|
+
expect(processed_data).to include(array: ['*****'])
|
146
|
+
end
|
147
|
+
end
|
148
|
+
|
149
|
+
context 'when boolean present' do
|
150
|
+
let(:data) { {bool: true} }
|
151
|
+
|
152
|
+
it 'masks it with asteriks' do
|
153
|
+
expect(processed_data).to eq(bool: '*****')
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
context 'when field has slash in the name' do
|
158
|
+
let(:data) do
|
159
|
+
{'field_with_/' => 'secret'}
|
160
|
+
end
|
161
|
+
let(:pointers) { ['/field_with_~1'] }
|
162
|
+
|
163
|
+
it 'includes field' do
|
164
|
+
expect(processed_data).to include('field_with_/' => 'secret')
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
168
|
+
context 'when field has tilde in the name' do
|
169
|
+
let(:data) do
|
170
|
+
{'field_with_~' => 'secret'}
|
171
|
+
end
|
172
|
+
let(:pointers) { ['/field_with_~0'] }
|
173
|
+
|
174
|
+
it 'includes field' do
|
175
|
+
expect(processed_data).to include('field_with_~' => 'secret')
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
context 'when field has tilde and 1' do
|
180
|
+
let(:data) do
|
181
|
+
{'field_with_~1' => 'secret'}
|
182
|
+
end
|
183
|
+
let(:pointers) { ['/field_with_~01'] }
|
184
|
+
|
185
|
+
it 'includes field' do
|
186
|
+
expect(processed_data).to include('field_with_~1' => 'secret')
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def process(pointers, data)
|
191
|
+
described_class.new(pointers: pointers).process(data)
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
context 'when :action is :exclude or :prune' do
|
196
|
+
subject(:processed_data) { described_class.new(config).process(data) }
|
197
|
+
|
198
|
+
let(:config) { {pointers: pointers, action: :prune} }
|
199
|
+
let(:pointers) { [] }
|
200
|
+
let(:data) do
|
201
|
+
{
|
202
|
+
field: 'secret',
|
203
|
+
data: {
|
204
|
+
field: 'secret'
|
205
|
+
},
|
206
|
+
array: [{field: 'secret'}, {field2: 'secret'}]
|
207
|
+
}
|
208
|
+
end
|
209
|
+
|
210
|
+
context 'when pointers is empty' do
|
211
|
+
it 'prunes all fields from the input' do
|
212
|
+
expect(processed_data).to eq({})
|
213
|
+
end
|
214
|
+
end
|
215
|
+
|
216
|
+
context 'with whitelisted field' do
|
217
|
+
let(:pointers) { ['/field'] }
|
218
|
+
|
219
|
+
it 'includes the field' do
|
220
|
+
expect(processed_data).to eq(field: 'secret')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
context 'with whitelisted nested field' do
|
225
|
+
let(:pointers) { ['/data/field'] }
|
226
|
+
|
227
|
+
it 'includes nested field' do
|
228
|
+
expect(processed_data).to eq(data: {field: 'secret'})
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
context 'with whitelisted array element field' do
|
233
|
+
let(:pointers) { ['/array/0/field'] }
|
234
|
+
|
235
|
+
it 'includes array element' do
|
236
|
+
expect(processed_data).to eq(array: [{field: 'secret'}])
|
237
|
+
end
|
238
|
+
end
|
239
|
+
|
240
|
+
context 'with whitelisted hash' do
|
241
|
+
it 'includes all whitelisted hash elements' do
|
242
|
+
source = {foo: {bar: 'baz'}}
|
243
|
+
target = {foo: {bar: 'baz'}}
|
244
|
+
expect(process(['/foo/~'], source)).to eq(target)
|
245
|
+
end
|
246
|
+
|
247
|
+
it 'does not include nested elements' do
|
248
|
+
source = {foo: {bar: {baz: 'asd'}}}
|
249
|
+
target = {foo: {bar: {}}}
|
250
|
+
expect(process(['/foo/~'], source)).to eq(target)
|
251
|
+
end
|
252
|
+
end
|
253
|
+
|
254
|
+
context 'with whitelisted array elements field with wildcard' do
|
255
|
+
let(:data) do
|
256
|
+
{
|
257
|
+
array: [
|
258
|
+
{field: 'data1', secret: 'secret1'},
|
259
|
+
{field: 'data2', secret: 'secret2'}
|
260
|
+
]
|
261
|
+
}
|
262
|
+
end
|
263
|
+
let(:pointers) { ['/array/~/field'] }
|
264
|
+
|
265
|
+
it 'includes array elements field' do
|
266
|
+
expect(processed_data).to include(
|
267
|
+
array: [
|
268
|
+
{field: 'data1'},
|
269
|
+
{field: 'data2'}
|
270
|
+
]
|
271
|
+
)
|
272
|
+
end
|
273
|
+
end
|
274
|
+
|
275
|
+
context 'with whitelisted string array elements with wildcard' do
|
276
|
+
let(:data) do
|
277
|
+
{array: %w[secret1 secret2]}
|
278
|
+
end
|
279
|
+
let(:pointers) { ['/array/~'] }
|
280
|
+
|
281
|
+
it 'includes array elements' do
|
282
|
+
expect(processed_data).to include(array: %w[secret1 secret2])
|
283
|
+
end
|
284
|
+
end
|
285
|
+
|
286
|
+
context 'with whitelisted string array elements in an array with wildcard' do
|
287
|
+
let(:data) do
|
288
|
+
{
|
289
|
+
nested: [{array: %w[secret1 secret2]}]
|
290
|
+
}
|
291
|
+
end
|
292
|
+
let(:pointers) { ['/nested/~/array/~'] }
|
293
|
+
|
294
|
+
it 'includes array elements' do
|
295
|
+
expect(processed_data).to include(nested: [{array: %w[secret1 secret2]}])
|
296
|
+
end
|
297
|
+
end
|
298
|
+
|
299
|
+
context 'with whitelisted array element' do
|
300
|
+
let(:pointers) { ['/array/0'] }
|
301
|
+
|
302
|
+
it 'masks array element' do
|
303
|
+
expect(processed_data).to eq(array: [{}])
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
context 'with whitelisted array' do
|
308
|
+
let(:pointers) { ['/array'] }
|
309
|
+
|
310
|
+
it 'masks array' do
|
311
|
+
expect(processed_data).to include(array: [])
|
312
|
+
end
|
313
|
+
end
|
314
|
+
|
315
|
+
def process(pointers, data)
|
316
|
+
described_class.new(pointers: pointers, action: :prune).process(data)
|
317
|
+
end
|
318
|
+
end
|
319
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'spec_helper'
|
4
|
+
|
5
|
+
describe Lenjador::Utils do
|
6
|
+
let(:now) { Time.utc(2015, 10, 11, 23, 10, 21, 123_456) }
|
7
|
+
|
8
|
+
before do
|
9
|
+
allow(Time).to receive(:now) { now }
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.build_event' do
|
13
|
+
subject(:event) { described_class.build_event(metadata, level, application_name) }
|
14
|
+
|
15
|
+
let(:application_name) { 'test_service' }
|
16
|
+
let(:level) { :info }
|
17
|
+
let(:metadata) { {x: 'y'} }
|
18
|
+
|
19
|
+
it 'includes it in the event as application' do
|
20
|
+
expect(event[:application]).to eq(application_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'includes log level' do
|
24
|
+
expect(event[:level]).to eq(:info)
|
25
|
+
end
|
26
|
+
|
27
|
+
it 'includes timestamp' do
|
28
|
+
expect(event[:@timestamp]).to eq(now)
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when @timestamp provided' do
|
32
|
+
let(:metadata) { {message: 'test', :@timestamp => 'a timestamp'} }
|
33
|
+
|
34
|
+
it 'overwrites @timestamp' do
|
35
|
+
expect(event[:message]).to eq('test')
|
36
|
+
expect(event[:@timestamp]).to eq('a timestamp')
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context 'when host provided' do
|
41
|
+
let(:metadata) { {message: 'test', host: 'xyz'} }
|
42
|
+
|
43
|
+
it 'overwrites host' do
|
44
|
+
expect(event[:message]).to eq('test')
|
45
|
+
expect(event[:host]).to eq('xyz')
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
context 'when OpenTracing is defined' do # rubocop:disable RSpec/MultipleMemoizedHelpers
|
50
|
+
let(:trace_id) { 'trace-id' }
|
51
|
+
let(:span_id) { 'span-id' }
|
52
|
+
|
53
|
+
it 'includes tracing data in the event when active span is present' do
|
54
|
+
span_context = double(trace_id: trace_id, span_id: span_id)
|
55
|
+
span = double(context: span_context)
|
56
|
+
open_tracing = double(active_span: span)
|
57
|
+
stub_const('OpenTracing', open_tracing)
|
58
|
+
|
59
|
+
expect(event).to include(
|
60
|
+
trace_id: trace_id,
|
61
|
+
span_id: span_id
|
62
|
+
)
|
63
|
+
end
|
64
|
+
|
65
|
+
it 'does not include tracing data if active span is not present' do
|
66
|
+
open_tracing = double(active_span: nil)
|
67
|
+
stub_const('OpenTracing', open_tracing)
|
68
|
+
|
69
|
+
expect(event).not_to include(:trace_id, :span_id)
|
70
|
+
end
|
71
|
+
|
72
|
+
it 'does not include tracing data if active span does not respond to trace_id' do
|
73
|
+
span_context = double(span_id: span_id)
|
74
|
+
span = double(context: span_context)
|
75
|
+
open_tracing = double(active_span: span)
|
76
|
+
stub_const('OpenTracing', open_tracing)
|
77
|
+
|
78
|
+
expect(event).not_to include(:trace_id, :span_id)
|
79
|
+
end
|
80
|
+
|
81
|
+
it 'does not include tracing data if active span does not respond to span_id' do
|
82
|
+
span_context = double(trace_id: trace_id)
|
83
|
+
span = double(context: span_context)
|
84
|
+
open_tracing = double(active_span: span)
|
85
|
+
stub_const('OpenTracing', open_tracing)
|
86
|
+
|
87
|
+
expect(event).not_to include(:trace_id, :span_id)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
describe '.generate_json' do
|
93
|
+
it 'serializes time objects to iso8601' do
|
94
|
+
serialized_time = now.iso8601(3)
|
95
|
+
json = described_class.generate_json(time: now)
|
96
|
+
expect(json).to eq(%({"time":"#{serialized_time}"}))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
data/spec/lenjador_spec.rb
CHANGED
@@ -3,34 +3,31 @@ require 'spec_helper'
|
|
3
3
|
describe Lenjador do
|
4
4
|
describe '.build' do
|
5
5
|
it 'creates stdout logger' do
|
6
|
-
expect(described_class).to receive(:new) do |
|
7
|
-
expect(
|
8
|
-
expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
|
6
|
+
expect(described_class).to receive(:new) do |adapter|
|
7
|
+
expect(adapter).to be_a(described_class::Adapters::StdoutAdapter)
|
9
8
|
end
|
10
9
|
|
11
|
-
described_class.build('test_service',
|
10
|
+
described_class.build('test_service', {})
|
12
11
|
end
|
13
12
|
|
14
13
|
it 'creates stdout json logger' do
|
15
|
-
expect(described_class).to receive(:new) do |
|
16
|
-
expect(
|
17
|
-
expect(adapters.first).to be_a(described_class::Adapters::StdoutJsonAdapter)
|
14
|
+
expect(described_class).to receive(:new) do |adapter|
|
15
|
+
expect(adapter).to be_a(described_class::Adapters::StdoutJsonAdapter)
|
18
16
|
end
|
19
17
|
|
20
|
-
described_class.build('test_service',
|
18
|
+
described_class.build('test_service', json: true)
|
21
19
|
end
|
22
20
|
|
23
21
|
it 'creates stdout logger when no loggers are specified' do
|
24
|
-
expect(described_class).to receive(:new) do |
|
25
|
-
expect(
|
26
|
-
expect(adapters.first).to be_a(described_class::Adapters::StdoutAdapter)
|
22
|
+
expect(described_class).to receive(:new) do |adapter|
|
23
|
+
expect(adapter).to be_a(described_class::Adapters::StdoutAdapter)
|
27
24
|
end
|
28
25
|
|
29
26
|
described_class.build('test_service', nil)
|
30
27
|
end
|
31
28
|
|
32
29
|
it 'creates preprocessor when preprocessor defined' do
|
33
|
-
expect(described_class).to receive(:new) do |
|
30
|
+
expect(described_class).to receive(:new) do |_adapter, _level, preprocessors|
|
34
31
|
expect(preprocessors.count).to be(1)
|
35
32
|
expect(preprocessors.first).to be_a(described_class::Preprocessors::Blacklist)
|
36
33
|
end
|
@@ -41,74 +38,74 @@ describe Lenjador do
|
|
41
38
|
end
|
42
39
|
|
43
40
|
context 'when preprocessor defined' do
|
44
|
-
let(:lenjador) { described_class.new(
|
41
|
+
let(:lenjador) { described_class.new(adapter, level, [preprocessor]) }
|
45
42
|
let(:adapter) { double }
|
43
|
+
let(:level) { Lenjador::Severity::DEBUG }
|
46
44
|
let(:preprocessor) { double }
|
47
45
|
let(:data) { {data: 'data'} }
|
48
46
|
|
49
47
|
it 'preprocesses data before logging' do
|
50
48
|
expect(preprocessor).to receive(:process).with(data).and_return(data.merge(processed: true)).ordered
|
51
|
-
expect(adapter).to receive(:log).with(
|
49
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, data.merge(processed: true)).ordered
|
52
50
|
|
53
51
|
lenjador.info(data)
|
54
52
|
end
|
55
53
|
end
|
56
54
|
|
57
55
|
context 'when parsing log data' do
|
58
|
-
let(:lenjador) { described_class.new(
|
56
|
+
let(:lenjador) { described_class.new(adapter, level, preprocessors) }
|
59
57
|
let(:adapter) { double }
|
58
|
+
let(:level) { Lenjador::Severity::DEBUG }
|
60
59
|
let(:preprocessors) { [] }
|
61
60
|
|
62
61
|
it 'parses empty string with nil metadata' do
|
63
|
-
expect(adapter).to receive(:log).with(
|
62
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: '')
|
64
63
|
|
65
64
|
lenjador.info('', nil)
|
66
65
|
end
|
67
66
|
|
68
67
|
it 'parses nil as metadata' do
|
69
|
-
expect(adapter).to receive(:log).with(
|
68
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: nil)
|
70
69
|
|
71
70
|
lenjador.info(nil)
|
72
71
|
end
|
73
72
|
|
74
73
|
it 'parses only message' do
|
75
|
-
expect(adapter).to receive(:log).with(
|
74
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: 'test message')
|
76
75
|
|
77
76
|
lenjador.info 'test message'
|
78
77
|
end
|
79
78
|
|
80
79
|
it 'parses only metadata' do
|
81
|
-
expect(adapter).to receive(:log).with(
|
80
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, test: 'data')
|
82
81
|
|
83
82
|
lenjador.info test: 'data'
|
84
83
|
end
|
85
84
|
|
86
85
|
it 'parses message and metadata' do
|
87
|
-
expect(adapter).to receive(:log).with(
|
86
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: 'test message', test: 'data')
|
88
87
|
|
89
88
|
lenjador.info 'test message', test: 'data'
|
90
89
|
end
|
91
90
|
|
92
91
|
it 'parses block as a message' do
|
93
92
|
message = 'test message'
|
94
|
-
expect(adapter).to receive(:log).with(
|
93
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: message)
|
95
94
|
|
96
95
|
lenjador.info { message }
|
97
96
|
end
|
98
97
|
|
99
98
|
it 'ignores progname on block syntax' do
|
100
99
|
message = 'test message'
|
101
|
-
expect(adapter).to receive(:log).with(
|
100
|
+
expect(adapter).to receive(:log).with(described_class::Severity::INFO, message: message)
|
102
101
|
|
103
102
|
lenjador.info('progname') { message }
|
104
103
|
end
|
105
104
|
end
|
106
105
|
|
107
|
-
context 'log level
|
106
|
+
context 'with log level' do
|
108
107
|
context 'when adapter has debug level' do
|
109
|
-
let(:logger)
|
110
|
-
described_class.build('test_service', stdout: {level: 'debug'})
|
111
|
-
end
|
108
|
+
let(:logger) { described_class.build('test_service', level: 'debug') }
|
112
109
|
|
113
110
|
it 'responds true to debug? and higher levels' do
|
114
111
|
expect(logger.debug?).to be(true)
|
@@ -120,9 +117,7 @@ describe Lenjador do
|
|
120
117
|
end
|
121
118
|
|
122
119
|
context 'when adapter has info level' do
|
123
|
-
let(:logger)
|
124
|
-
described_class.build('test_service', stdout: {level: 'info'})
|
125
|
-
end
|
120
|
+
let(:logger) { described_class.build('test_service', level: 'info') }
|
126
121
|
|
127
122
|
it 'responds true to info? and higher levels' do
|
128
123
|
expect(logger.debug?).to be(false)
|
@@ -134,9 +129,22 @@ describe Lenjador do
|
|
134
129
|
end
|
135
130
|
end
|
136
131
|
|
137
|
-
it '
|
138
|
-
|
139
|
-
|
140
|
-
|
132
|
+
it 'allows changing log level on existing instance' do
|
133
|
+
logger = described_class.build('test_service', level: 'info')
|
134
|
+
|
135
|
+
logger.level = ::Logger::DEBUG
|
136
|
+
expect(logger.debug?).to eq(true)
|
137
|
+
|
138
|
+
logger.level = ::Logger::INFO
|
139
|
+
expect(logger.debug?).to eq(false)
|
140
|
+
expect(logger.info?).to eq(true)
|
141
|
+
|
142
|
+
logger.level = ::Logger::WARN
|
143
|
+
expect(logger.info?).to eq(false)
|
144
|
+
expect(logger.warn?).to eq(true)
|
145
|
+
|
146
|
+
logger.level = ::Logger::ERROR
|
147
|
+
expect(logger.warn?).to eq(false)
|
148
|
+
expect(logger.error?).to eq(true)
|
141
149
|
end
|
142
150
|
end
|