ougai 1.1.0 → 1.2.0

Sign up to get free protection for your applications and to get access to all the features.
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