ougai 1.1.0 → 1.2.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 54135d508028ceae123d4ac6554fdcfce52709c5
4
- data.tar.gz: 9e7701c90d42b6db02d05d2c845687ac62bd60a5
3
+ metadata.gz: 457d3322926c875ce7c6b72b7ae0f192a96788fe
4
+ data.tar.gz: eb2e3121f6a0b6367d7608b72344ca27ecb764ed
5
5
  SHA512:
6
- metadata.gz: 4a52e06b9b082e80e7df479a073e390df104e5066ce434eb4c12edb8bbf56250c7ef46908cee56cb6130724da7671c3a4f86a52e297b5f983379cd18839b4f23
7
- data.tar.gz: 3a84a43bbd5d6207b102794d210cc4dd9fdb74426dc3890663d12f6b40b8a326211c56d3510b76c88626481718782da5aff69692ee17b42de707f3f5bdb4d91a
6
+ metadata.gz: eb7ebaf9a4b3bd092410aef5778152f378e53a2a059cb450170e536bea78c6a64919be9325cc285e6b9978dfbf51d551e21155d544c492f9ea58904652acb5e6
7
+ data.tar.gz: 0f0d12daf3ad7959e8fb7c65599d07af6b427bdd8be262904b87781d6a439a9ba453a738387a496ee3bf677471609de9e6ebe64f7ea125dd957d1964c150a649
data/README.md CHANGED
@@ -184,6 +184,35 @@ logger.info('Hello!', user: { name: 'Jiro' }, version: '2.3')
184
184
  ```
185
185
 
186
186
  If any field of with_fields is specified in each log, the field is overridden.
187
+ But if the field's type is *Array*, both with_field value and logging value are merged with `concat` and `uniq`.
188
+
189
+ ### Create a child logger
190
+
191
+ `logger.child(with_fields)` creates a child logger of self. Its argument `with_fields` add to all logs the child logger outputs. A child logger can also create its child logger.
192
+
193
+ ```ruby
194
+ logger = Ougai::Logger.new(STDOUT)
195
+ logger.with_fields = { app: 'yourapp', tags: ['service'], kind: 'main' }
196
+
197
+ child_logger = logger.child({ tags:['user'], kind: 'logic' })
198
+ logger.info('Created child logger')
199
+
200
+ child_logger.info('Created a user', name: 'Mike')
201
+
202
+ gc_logger = child_logger.child({ kind: 'detail' })
203
+ child_logger.info('Created grand child logger')
204
+
205
+ gc_logger.debug('something detail', age: 34, weight: 72)
206
+ ```
207
+
208
+ ```json
209
+ {"name":"main","hostname":"mint2","pid":8342,"level":30,"time":"2017-08-01T22:07:20.400+09:00","v":0,"app":"yourapp","tags":["service"],"kind":"main","msg":"Created child logger"}
210
+ {"name":"Mike","hostname":"mint2","pid":8342,"level":30,"time":"2017-08-01T22:07:20.400+09:00","v":0,"app":"yourapp","tags":["service","user"],"kind":"logic","msg":"Created a user"}
211
+ {"name":"main","hostname":"mint2","pid":8342,"level":30,"time":"2017-08-01T22:07:20.400+09:00","v":0,"app":"yourapp","tags":["service","user"],"kind":"logic","msg":"Created grand child logger"}
212
+ {"name":"main","hostname":"mint2","pid":8342,"level":20,"time":"2017-08-01T22:07:20.400+09:00","v":0,"app":"yourapp","tags":["service","user"],"kind":"detail","age":34,"weight":72,"msg":"something detail"}
213
+ ```
214
+
215
+ If any field exists in both parent log and child log, the parent value is overridden or merged by child value.
187
216
 
188
217
  ## View log by node-bunyan
189
218
 
@@ -1,5 +1,8 @@
1
+ require 'logger'
1
2
  require 'ougai/version'
2
3
  require 'ougai/formatters/base'
3
4
  require 'ougai/formatters/bunyan'
4
5
  require 'ougai/formatters/readable'
6
+ require 'ougai/logging'
7
+ require 'ougai/child_logger'
5
8
  require 'ougai/logger'
@@ -0,0 +1,24 @@
1
+ module Ougai
2
+ class ChildLogger
3
+ include Logging
4
+
5
+ def initialize(parent, fields)
6
+ @parent = parent
7
+ @with_fields = fields
8
+ end
9
+
10
+ def level
11
+ @parent.level
12
+ end
13
+
14
+ def chain(severity, args, fields)
15
+ @parent.chain(severity, args, merge_fields(@with_fields, fields))
16
+ end
17
+
18
+ protected
19
+
20
+ def append(severity, args)
21
+ @parent.chain(severity, args, @with_fields)
22
+ end
23
+ end
24
+ end
@@ -1,9 +1,8 @@
1
- require 'ougai/formatters/bunyan'
2
- require 'logger'
3
-
4
1
  module Ougai
5
2
  class Logger < ::Logger
6
- attr_accessor :default_message, :exc_key, :with_fields
3
+ include Logging
4
+
5
+ attr_accessor :default_message, :exc_key
7
6
 
8
7
  def initialize(*args)
9
8
  super(*args)
@@ -13,41 +12,6 @@ module Ougai
13
12
  @formatter = create_formatter
14
13
  end
15
14
 
16
- def debug(message = nil, ex = nil, data = nil, &block)
17
- return true if level > DEBUG
18
- args = block ? yield : [message, ex, data]
19
- add(DEBUG, build_log(args))
20
- end
21
-
22
- def info(message = nil, ex = nil, data = nil, &block)
23
- return true if level > INFO
24
- args = block ? yield : [message, ex, data]
25
- add(INFO, build_log(args))
26
- end
27
-
28
- def warn(message = nil, ex = nil, data = nil, &block)
29
- return true if level > WARN
30
- args = block ? yield : [message, ex, data]
31
- add(WARN, build_log(args))
32
- end
33
-
34
- def error(message = nil, ex = nil, data = nil, &block)
35
- return true if level > ERROR
36
- args = block ? yield : [message, ex, data]
37
- add(ERROR, build_log(args))
38
- end
39
-
40
- def fatal(message = nil, ex = nil, data = nil, &block)
41
- return true if level > FATAL
42
- args = block ? yield : [message, ex, data]
43
- add(FATAL, build_log(args))
44
- end
45
-
46
- def unknown(message = nil, ex = nil, data = nil, &block)
47
- args = block ? yield : [message, ex, data]
48
- add(UNKNOWN, build_log(args))
49
- end
50
-
51
15
  def self.broadcast(logger)
52
16
  Module.new do |mdl|
53
17
  ::Logger::Severity.constants.each do |severity|
@@ -61,16 +25,22 @@ module Ougai
61
25
  end
62
26
  end
63
27
 
28
+ def chain(severity, args, fields)
29
+ write(severity, args, merge_fields(@with_fields, fields))
30
+ end
31
+
64
32
  protected
65
33
 
34
+ def append(severity, args)
35
+ write(severity, args, @with_fields)
36
+ end
37
+
66
38
  def create_formatter
67
39
  Formatters::Bunyan.new
68
40
  end
69
41
 
70
- private
71
-
72
- def build_log(args)
73
- @with_fields.merge(to_item(args))
42
+ def write(severity, args, fields)
43
+ add(severity, merge_fields(fields, to_item(args)))
74
44
  end
75
45
 
76
46
  def to_item(args)
@@ -87,6 +57,8 @@ module Ougai
87
57
  end
88
58
  end
89
59
 
60
+ private
61
+
90
62
  def create_item_with_1arg(msg)
91
63
  item = {}
92
64
  if msg.is_a?(Exception)
@@ -0,0 +1,64 @@
1
+ module Ougai
2
+ module Logging
3
+ attr_accessor :with_fields
4
+
5
+ def debug(message = nil, ex = nil, data = nil, &block)
6
+ return true if level > Logger::DEBUG
7
+ args = block ? yield : [message, ex, data]
8
+ append(Logger::DEBUG, args)
9
+ end
10
+
11
+ def info(message = nil, ex = nil, data = nil, &block)
12
+ return true if level > Logger::INFO
13
+ args = block ? yield : [message, ex, data]
14
+ append(Logger::INFO, args)
15
+ end
16
+
17
+ def warn(message = nil, ex = nil, data = nil, &block)
18
+ return true if level > Logger::WARN
19
+ args = block ? yield : [message, ex, data]
20
+ append(Logger::WARN, args)
21
+ end
22
+
23
+ def error(message = nil, ex = nil, data = nil, &block)
24
+ return true if level > Logger::ERROR
25
+ args = block ? yield : [message, ex, data]
26
+ append(Logger::ERROR, args)
27
+ end
28
+
29
+ def fatal(message = nil, ex = nil, data = nil, &block)
30
+ return true if level > Logger::FATAL
31
+ args = block ? yield : [message, ex, data]
32
+ append(Logger::FATAL, args)
33
+ end
34
+
35
+ def unknown(message = nil, ex = nil, data = nil, &block)
36
+ args = block ? yield : [message, ex, data]
37
+ append(Logger::UNKNOWN, args)
38
+ end
39
+
40
+ def child(fields = {})
41
+ ChildLogger.new(self, fields)
42
+ end
43
+
44
+ def chain(severity, args, fields)
45
+ raise NotImplementedError
46
+ end
47
+
48
+ protected
49
+
50
+ def append(severity, args)
51
+ raise NotImplementedError
52
+ end
53
+
54
+ def merge_fields(base_data, new_data)
55
+ base_data.merge(new_data) do |_, base_val, new_val|
56
+ if base_val.is_a?(Array) and new_val.is_a?(Array)
57
+ (base_val + new_val).uniq
58
+ else
59
+ new_val
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -1,3 +1,3 @@
1
1
  module Ougai
2
- VERSION = "1.1.0"
2
+ VERSION = "1.2.0"
3
3
  end
@@ -0,0 +1,300 @@
1
+ require 'spec_helper'
2
+ require 'stringio'
3
+ require 'json'
4
+
5
+ describe Ougai::ChildLogger do
6
+ let(:pid) { Process.pid }
7
+
8
+ matcher :be_log_message do |message, level|
9
+ match do |actual|
10
+ actual[:name] == 'rspec' \
11
+ && actual[:msg] == message \
12
+ && actual[:level] == level \
13
+ && actual[:pid] == pid \
14
+ && actual[:v] == 0
15
+ end
16
+ end
17
+
18
+ let(:io) { StringIO.new }
19
+ let(:parent_logger) { Ougai::Logger.new(io) }
20
+
21
+ let(:items) do
22
+ io.rewind
23
+ io.readlines.map do |line|
24
+ JSON.parse(line.chomp, symbolize_names: true)
25
+ end
26
+ end
27
+
28
+ let(:item) {
29
+ items[0]
30
+ }
31
+
32
+ describe '#level propagated from parent one' do
33
+ let(:logger) { parent_logger.child }
34
+
35
+ context 'DEBUG' do
36
+ let(:log_msg) { 'log message' }
37
+ before { parent_logger.level = Logger::DEBUG }
38
+
39
+ it 'outputs debug message' do
40
+ logger.debug(log_msg)
41
+ expect(item).to be_log_message(log_msg, 20)
42
+ end
43
+
44
+ it 'outputs info message' do
45
+ logger.info(log_msg)
46
+ expect(item).to be_log_message(log_msg, 30)
47
+ end
48
+ end
49
+
50
+ context 'INFO' do
51
+ let(:log_msg) { 'log message' }
52
+ before { parent_logger.level = Logger::INFO }
53
+
54
+ it 'does not output debug message' do
55
+ logger.debug(log_msg)
56
+ expect(item).to be_nil
57
+ end
58
+
59
+ it 'outputs info message' do
60
+ logger.info(log_msg)
61
+ expect(item).to be_log_message(log_msg, 30)
62
+ end
63
+
64
+ it 'outputs warning message' do
65
+ logger.warn(log_msg)
66
+ expect(item).to be_log_message(log_msg, 40)
67
+ end
68
+ end
69
+
70
+ context 'WARN' do
71
+ let(:log_msg) { 'log message' }
72
+ before { parent_logger.level = Logger::WARN }
73
+
74
+ it 'does not output info message' do
75
+ logger.info(log_msg)
76
+ expect(item).to be_nil
77
+ end
78
+
79
+ it 'outputs warning message' do
80
+ logger.warn(log_msg)
81
+ expect(item).to be_log_message(log_msg, 40)
82
+ end
83
+
84
+ it 'outputs error message' do
85
+ logger.error(log_msg)
86
+ expect(item).to be_log_message(log_msg, 50)
87
+ end
88
+ end
89
+
90
+ context 'ERROR' do
91
+ let(:log_msg) { 'log message' }
92
+ before { parent_logger.level = Logger::ERROR }
93
+
94
+ it 'does not output warning message' do
95
+ logger.warn(log_msg)
96
+ expect(item).to be_nil
97
+ end
98
+
99
+ it 'outputs error message' do
100
+ logger.error(log_msg)
101
+ expect(item).to be_log_message(log_msg, 50)
102
+ end
103
+
104
+ it 'outputs fatal message' do
105
+ logger.fatal(log_msg)
106
+ expect(item).to be_log_message(log_msg, 60)
107
+ end
108
+ end
109
+
110
+ context 'FATAL' do
111
+ let(:log_msg) { 'log message' }
112
+ before { parent_logger.level = Logger::FATAL }
113
+
114
+ it 'does not output error message' do
115
+ logger.error(log_msg)
116
+ expect(item).to be_nil
117
+ end
118
+
119
+ it 'outputs fatal message' do
120
+ logger.fatal(log_msg)
121
+ expect(item).to be_log_message(log_msg, 60)
122
+ end
123
+
124
+ it 'outputs unknown message' do
125
+ logger.unknown(log_msg)
126
+ expect(item).to be_log_message(log_msg, 70)
127
+ end
128
+ end
129
+
130
+ context 'UNKNOWN' do
131
+ let(:log_msg) { 'log message' }
132
+ before { parent_logger.level = Logger::UNKNOWN }
133
+
134
+ it 'does not output fatal message' do
135
+ logger.fatal(log_msg)
136
+ expect(item).to be_nil
137
+ end
138
+
139
+ it 'outputs unknown message' do
140
+ logger.unknown(log_msg)
141
+ expect(item).to be_log_message(log_msg, 70)
142
+ end
143
+ end
144
+ end
145
+
146
+ describe '#chain' do
147
+ let(:log_level) { 30 }
148
+ let(:log_msg) { 'log message' }
149
+ let(:parent_log_msg) { 'parent log message' }
150
+
151
+ context 'parent with fields, child with fields' do
152
+ before do
153
+ parent_logger.with_fields = { foo: 1, pos: 'parent' }
154
+ end
155
+
156
+ let(:logger) { parent_logger.child(bar: '1', pos: 'child') }
157
+
158
+ it 'outputs with merged parent and child fields' do
159
+ logger.info(log_msg)
160
+ parent_logger.info(parent_log_msg)
161
+
162
+ expect(items[0]).to be_log_message(log_msg, log_level)
163
+ expect(items[0]).to include(foo: 1, bar: '1', pos: 'child')
164
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
165
+ expect(items[1]).to include(foo: 1, pos: 'parent')
166
+ expect(items[1]).not_to include(:bar)
167
+ end
168
+
169
+ context 'after updating with_fieldses of parent and child' do
170
+ before do
171
+ parent_logger.with_fields = { foo: 11 }
172
+ logger.with_fields = { bar: '11' }
173
+ end
174
+
175
+ it 'outputs with child fields' do
176
+ logger.info(log_msg)
177
+ parent_logger.info(parent_log_msg)
178
+
179
+ expect(items[0]).to be_log_message(log_msg, log_level)
180
+ expect(items[0]).to include(foo: 11, bar: '11')
181
+ expect(items[0]).not_to include(:pos)
182
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
183
+ expect(items[1]).to include(foo: 11)
184
+ expect(items[1]).not_to include(:bar, :pos)
185
+ end
186
+ end
187
+ end
188
+
189
+ context 'parent with fields, child without fields' do
190
+ before do
191
+ parent_logger.with_fields = { foo: 2, pos: 'parent' }
192
+ end
193
+
194
+ let(:logger) { parent_logger.child }
195
+
196
+ it 'output valid' do
197
+ logger.info(log_msg)
198
+ parent_logger.info(parent_log_msg)
199
+
200
+ expect(items[0]).to be_log_message(log_msg, log_level)
201
+ expect(items[0]).to include(foo: 2, pos: 'parent')
202
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
203
+ expect(items[1]).to include(foo: 2, pos: 'parent')
204
+ end
205
+
206
+ context 'after updating parent logger with_fields' do
207
+ before do
208
+ parent_logger.with_fields = { foo: 22 }
209
+ end
210
+
211
+ it 'output with new parent fields' do
212
+ logger.info(log_msg)
213
+ parent_logger.info(parent_log_msg)
214
+
215
+ expect(items[0]).to be_log_message(log_msg, log_level)
216
+ expect(items[0]).to include(foo: 22)
217
+ expect(items[0]).not_to include(:pos)
218
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
219
+ expect(items[1]).to include(foo: 22)
220
+ expect(items[1]).not_to include(:pos)
221
+ end
222
+ end
223
+ end
224
+
225
+ context 'parent without fields, child with fields' do
226
+ before do
227
+ parent_logger.with_fields = {}
228
+ end
229
+
230
+ let(:logger) { parent_logger.child(bar: '3', pos: 'child') }
231
+
232
+ it 'output valid' do
233
+ logger.info(log_msg)
234
+ parent_logger.info(parent_log_msg)
235
+
236
+ expect(items[0]).to be_log_message(log_msg, log_level)
237
+ expect(items[0]).to include(bar: '3', pos: 'child')
238
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
239
+ expect(items[1]).not_to include(:bar, :pos)
240
+ end
241
+
242
+ context 'after updating child logger with_fields' do
243
+ before do
244
+ logger.with_fields = { bar: '33' }
245
+ end
246
+
247
+ it 'output valid' do
248
+ logger.info(log_msg)
249
+ parent_logger.info(parent_log_msg)
250
+
251
+ expect(items[0]).to be_log_message(log_msg, log_level)
252
+ expect(items[0]).to include(bar: '33')
253
+ expect(items[0]).not_to include(:pos)
254
+ expect(items[1]).to be_log_message(parent_log_msg, log_level)
255
+ expect(items[1]).not_to include(:bar, :pos)
256
+ end
257
+ end
258
+ end
259
+
260
+ context 'grandchild logger' do
261
+ before do
262
+ parent_logger.with_fields = { tag: 'parent', tags: ['parent'] }
263
+ end
264
+
265
+ let(:logger) { parent_logger.child(tag: 'child', tags: ['child']) }
266
+ let(:grand_logger) { logger.child(tag: 'grandchild', tags: ['grandchild']) }
267
+
268
+ it 'outputs with all merged fields' do
269
+ grand_logger.info('Hi', foo: 3)
270
+ logger.info(log_msg, foo: 2)
271
+ parent_logger.info(parent_log_msg, foo: 10)
272
+ parent_logger.info('Good evening!', foo: 11)
273
+
274
+ expect(items[0]).to be_log_message('Hi', log_level)
275
+ expect(items[0]).to include(tag: 'grandchild', tags: ['parent', 'child', 'grandchild'], foo: 3)
276
+
277
+ expect(items[1]).to be_log_message(log_msg, log_level)
278
+ expect(items[1]).to include(tag: 'child', tags: ['parent', 'child'], foo: 2)
279
+
280
+ expect(items[2]).to be_log_message(parent_log_msg, log_level)
281
+ expect(items[2]).to include(tag: 'parent', tags: ['parent'], foo: 10)
282
+ expect(items[3]).to be_log_message('Good evening!', log_level)
283
+ expect(items[3]).to include(tag: 'parent', tags: ['parent'], foo: 11)
284
+ end
285
+
286
+ context 'after updating child logger with_fields' do
287
+ before do
288
+ logger.with_fields = { bar: '33' }
289
+ end
290
+
291
+ it 'outputs with child fields' do
292
+ logger.info(log_msg)
293
+ expect(items[0]).to be_log_message(log_msg, log_level)
294
+ expect(items[0]).to include(bar: '33')
295
+ expect(items[0]).not_to include(:pos)
296
+ end
297
+ end
298
+ end
299
+ end
300
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Ougai::Logging do
4
+ describe '#merge_fields' do
5
+ let(:target) { m = described_class; Class.new{ include m }.new }
6
+
7
+ it 'merges with unique elements in array' do
8
+ result = nil
9
+ target.instance_eval do
10
+ result = merge_fields({ foo: [1, 2], bar: 'base', baz: ['A'] },
11
+ { foo: [2, 3], bar: 'over', baz: ['B'] })
12
+ end
13
+ expect(result[:foo]).to eq([1, 2, 3])
14
+ expect(result[:bar]).to eq('over')
15
+ expect(result[:baz]).to eq(['A', 'B'])
16
+ end
17
+ end
18
+ 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.1.0
4
+ version: 1.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Toshimitsu Takahashi
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-07-24 00:00:00.000000000 Z
11
+ date: 2017-08-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -68,14 +68,18 @@ files:
68
68
  - README.md
69
69
  - Rakefile
70
70
  - lib/ougai.rb
71
+ - lib/ougai/child_logger.rb
71
72
  - lib/ougai/formatters/base.rb
72
73
  - lib/ougai/formatters/bunyan.rb
73
74
  - lib/ougai/formatters/readable.rb
74
75
  - lib/ougai/logger.rb
76
+ - lib/ougai/logging.rb
75
77
  - lib/ougai/version.rb
78
+ - spec/child_logger_spec.rb
76
79
  - spec/formatters/base_spec.rb
77
80
  - spec/formatters/readable_spec.rb
78
81
  - spec/logger_spec.rb
82
+ - spec/logging_spec.rb
79
83
  - spec/ougai_spec.rb
80
84
  - spec/spec_helper.rb
81
85
  homepage: https://github.com/tilfin/ougai
@@ -105,6 +109,8 @@ summary: JSON logger compatible with node-bunyan is capable of handling data eas
105
109
  test_files:
106
110
  - spec/formatters/base_spec.rb
107
111
  - spec/formatters/readable_spec.rb
112
+ - spec/child_logger_spec.rb
113
+ - spec/logging_spec.rb
108
114
  - spec/logger_spec.rb
109
115
  - spec/ougai_spec.rb
110
116
  - spec/spec_helper.rb