semantic_logger 4.1.1 → 4.2.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/semantic_logger.rb +6 -13
- data/lib/semantic_logger/ansi_colors.rb +10 -10
- data/lib/semantic_logger/appender.rb +42 -26
- data/lib/semantic_logger/appender/async.rb +179 -0
- data/lib/semantic_logger/appender/async_batch.rb +95 -0
- data/lib/semantic_logger/appender/bugsnag.rb +2 -1
- data/lib/semantic_logger/appender/elasticsearch.rb +113 -81
- data/lib/semantic_logger/appender/elasticsearch_http.rb +1 -3
- data/lib/semantic_logger/appender/file.rb +1 -3
- data/lib/semantic_logger/appender/graylog.rb +6 -5
- data/lib/semantic_logger/appender/honeybadger.rb +0 -2
- data/lib/semantic_logger/appender/http.rb +25 -10
- data/lib/semantic_logger/appender/kafka.rb +1 -3
- data/lib/semantic_logger/appender/mongodb.rb +1 -3
- data/lib/semantic_logger/appender/new_relic.rb +7 -3
- data/lib/semantic_logger/appender/sentry.rb +6 -7
- data/lib/semantic_logger/appender/splunk.rb +1 -2
- data/lib/semantic_logger/appender/splunk_http.rb +3 -4
- data/lib/semantic_logger/appender/syslog.rb +1 -3
- data/lib/semantic_logger/appender/tcp.rb +7 -9
- data/lib/semantic_logger/appender/udp.rb +0 -2
- data/lib/semantic_logger/appender/wrapper.rb +0 -2
- data/lib/semantic_logger/base.rb +76 -19
- data/lib/semantic_logger/formatters.rb +37 -0
- data/lib/semantic_logger/formatters/base.rb +10 -3
- data/lib/semantic_logger/formatters/json.rb +2 -6
- data/lib/semantic_logger/formatters/one_line.rb +18 -0
- data/lib/semantic_logger/formatters/raw.rb +8 -2
- data/lib/semantic_logger/formatters/signalfx.rb +169 -0
- data/lib/semantic_logger/log.rb +23 -14
- data/lib/semantic_logger/loggable.rb +88 -15
- data/lib/semantic_logger/logger.rb +0 -20
- data/lib/semantic_logger/metric/new_relic.rb +75 -0
- data/lib/semantic_logger/metric/signalfx.rb +123 -0
- data/lib/semantic_logger/{metrics → metric}/statsd.rb +20 -8
- data/lib/semantic_logger/processor.rb +67 -169
- data/lib/semantic_logger/semantic_logger.rb +7 -31
- data/lib/semantic_logger/subscriber.rb +32 -36
- data/lib/semantic_logger/utils.rb +47 -0
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender/async_batch_test.rb +61 -0
- data/test/appender/async_test.rb +45 -0
- data/test/appender/elasticsearch_http_test.rb +3 -3
- data/test/appender/elasticsearch_test.rb +211 -49
- data/test/appender/file_test.rb +9 -8
- data/test/appender/mongodb_test.rb +3 -3
- data/test/appender/newrelic_rpm.rb +6 -0
- data/test/appender/sentry_test.rb +3 -1
- data/test/appender/wrapper_test.rb +29 -0
- data/test/concerns/compatibility_test.rb +64 -60
- data/test/debug_as_trace_logger_test.rb +62 -77
- data/test/formatters/one_line_test.rb +61 -0
- data/test/formatters/signalfx_test.rb +200 -0
- data/test/formatters_test.rb +36 -0
- data/test/in_memory_appender.rb +9 -0
- data/test/in_memory_appender_helper.rb +43 -0
- data/test/in_memory_batch_appender.rb +9 -0
- data/test/in_memory_metrics_appender.rb +14 -0
- data/test/loggable_test.rb +15 -30
- data/test/logger_test.rb +181 -135
- data/test/measure_test.rb +212 -113
- data/test/metric/new_relic_test.rb +36 -0
- data/test/metric/signalfx_test.rb +78 -0
- data/test/semantic_logger_test.rb +58 -65
- data/test/test_helper.rb +19 -2
- metadata +33 -7
- data/lib/semantic_logger/metrics/new_relic.rb +0 -30
- data/lib/semantic_logger/metrics/udp.rb +0 -80
- data/test/mock_logger.rb +0 -29
data/test/measure_test.rb
CHANGED
@@ -2,201 +2,297 @@ require_relative 'test_helper'
|
|
2
2
|
|
3
3
|
class MeasureTest < Minitest::Test
|
4
4
|
describe 'Measure' do
|
5
|
-
|
6
|
-
SemanticLogger.default_level = :trace
|
7
|
-
SemanticLogger.backtrace_level = nil
|
8
|
-
@mock_logger = MockLogger.new
|
9
|
-
@appender = SemanticLogger.add_appender(logger: @mock_logger)
|
10
|
-
@logger = SemanticLogger['LoggerTest']
|
11
|
-
@hash = {session_id: 'HSSKLEU@JDK767', tracking_number: 12345}
|
12
|
-
@hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
|
13
|
-
@thread_name = Thread.current.name
|
14
|
-
@file_name_reg_exp = " #{File.basename(__FILE__)}:\d+"
|
15
|
-
|
16
|
-
# Add mock metric subscriber
|
17
|
-
$last_metric = nil
|
18
|
-
SemanticLogger.on_metric do |log|
|
19
|
-
$last_metric = log.dup
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
after do
|
24
|
-
SemanticLogger.remove_appender(@appender)
|
25
|
-
end
|
5
|
+
include InMemoryAppenderHelper
|
26
6
|
|
27
7
|
# Ensure that any log level can be measured and logged
|
28
8
|
SemanticLogger::LEVELS.each do |level|
|
29
|
-
level_char = level.to_s.upcase[0]
|
30
9
|
measure_level = "measure_#{level}".to_sym
|
31
10
|
|
32
11
|
describe "##{measure_level}" do
|
33
12
|
it ':message' do
|
34
|
-
assert_equal 'result',
|
35
|
-
|
36
|
-
|
13
|
+
assert_equal 'result', logger.send(measure_level, 'hello world') { 'result' }
|
14
|
+
|
15
|
+
assert log = log_message
|
16
|
+
assert_equal 'hello world', log.message
|
17
|
+
end
|
18
|
+
|
19
|
+
it ':level' do
|
20
|
+
assert_equal 'result', logger.send(measure_level, 'hello world') { 'result' }
|
21
|
+
|
22
|
+
assert log = log_message
|
23
|
+
assert_equal level, log.level
|
37
24
|
end
|
38
25
|
|
39
26
|
it ':payload' do
|
40
|
-
assert_equal 'result',
|
41
|
-
|
42
|
-
|
27
|
+
assert_equal 'result', logger.send(measure_level, 'hello world', payload: payload) { 'result' }
|
28
|
+
|
29
|
+
assert log = log_message
|
30
|
+
assert_equal payload, log.payload
|
43
31
|
end
|
44
32
|
|
45
33
|
describe ':min_duration' do
|
46
34
|
it 'not log when faster' do
|
47
|
-
assert_equal 'result',
|
48
|
-
|
49
|
-
assert_nil @mock_logger.message
|
35
|
+
assert_equal 'result', logger.send(measure_level, 'hello world', min_duration: 2000) { 'result' }
|
36
|
+
refute log_message
|
50
37
|
end
|
51
38
|
|
52
39
|
it 'log when slower' do
|
53
|
-
assert_equal 'result',
|
54
|
-
|
55
|
-
|
40
|
+
assert_equal 'result', logger.send(measure_level, 'hello world', min_duration: 200, payload: payload) { sleep 0.5; 'result' }
|
41
|
+
|
42
|
+
assert log = log_message
|
43
|
+
assert_equal 'hello world', log.message
|
56
44
|
end
|
57
45
|
end
|
58
46
|
|
59
47
|
it ':exception' do
|
60
48
|
assert_raises RuntimeError do
|
61
|
-
|
49
|
+
logger.send(measure_level, 'hello world', payload: payload) { raise RuntimeError.new('Test') }
|
62
50
|
end
|
63
|
-
|
64
|
-
|
51
|
+
|
52
|
+
assert log = log_message
|
53
|
+
refute log.exception
|
54
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
55
|
+
assert_equal level, log.level
|
65
56
|
end
|
66
57
|
|
67
58
|
it ':on_exception_level' do
|
68
59
|
assert_raises RuntimeError do
|
69
|
-
|
60
|
+
logger.measure(level, 'hello world', payload: payload, on_exception_level: :fatal) { raise RuntimeError.new('Test') }
|
61
|
+
end
|
62
|
+
|
63
|
+
assert log = log_message
|
64
|
+
refute log.exception
|
65
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
66
|
+
assert_equal :fatal, log.level
|
67
|
+
end
|
68
|
+
|
69
|
+
describe 'log_exception' do
|
70
|
+
it 'default' do
|
71
|
+
assert_raises RuntimeError do
|
72
|
+
logger.send(measure_level, 'hello world') { raise RuntimeError.new('Test') }
|
73
|
+
end
|
74
|
+
|
75
|
+
assert log = log_message
|
76
|
+
refute log.exception
|
77
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
78
|
+
end
|
79
|
+
|
80
|
+
it ':full' do
|
81
|
+
assert_raises RuntimeError do
|
82
|
+
logger.send(measure_level, 'hello world', log_exception: :full) { raise RuntimeError.new('Test') }
|
83
|
+
end
|
84
|
+
|
85
|
+
assert log = log_message
|
86
|
+
assert log.exception.is_a?(RuntimeError)
|
87
|
+
assert log.exception.backtrace
|
88
|
+
assert_equal level, log.level
|
89
|
+
assert_equal 'hello world', log.message
|
90
|
+
end
|
91
|
+
|
92
|
+
it ':partial' do
|
93
|
+
assert_raises RuntimeError do
|
94
|
+
logger.send(measure_level, 'hello world', log_exception: :partial) { raise RuntimeError.new('Test') }
|
95
|
+
end
|
96
|
+
|
97
|
+
assert log = log_message
|
98
|
+
refute log.exception
|
99
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
100
|
+
end
|
101
|
+
|
102
|
+
it ':none' do
|
103
|
+
assert_raises RuntimeError do
|
104
|
+
logger.send(measure_level, 'hello world', log_exception: :none) { raise RuntimeError.new('Test') }
|
105
|
+
end
|
106
|
+
|
107
|
+
assert log = log_message
|
108
|
+
refute log.exception
|
109
|
+
assert_equal 'hello world', log.message
|
70
110
|
end
|
71
|
-
SemanticLogger.flush
|
72
|
-
assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ F \[\d+:#{@thread_name}\] \((\d+\.\d+)|(\d+)ms\) LoggerTest -- hello world -- Exception: RuntimeError: Test -- #{@hash_str}/, @mock_logger.message)
|
73
111
|
end
|
74
112
|
|
75
113
|
it ':metric' do
|
76
114
|
metric_name = '/my/custom/metric'
|
77
|
-
assert_equal 'result',
|
78
|
-
|
79
|
-
|
80
|
-
|
115
|
+
assert_equal 'result', logger.send(measure_level, 'hello world', metric: metric_name) { 'result' }
|
116
|
+
|
117
|
+
assert log = log_message
|
118
|
+
assert_equal metric_name, log.metric
|
81
119
|
end
|
82
120
|
|
83
121
|
it ':backtrace_level' do
|
84
122
|
SemanticLogger.stub(:backtrace_level_index, 0) do
|
85
|
-
assert_equal 'result',
|
86
|
-
|
87
|
-
|
123
|
+
assert_equal 'result', logger.send(measure_level, 'hello world') { 'result' }
|
124
|
+
|
125
|
+
assert log = log_message
|
126
|
+
assert log.backtrace
|
127
|
+
assert log.backtrace.size > 0
|
128
|
+
|
129
|
+
# Extract file name and line number from backtrace
|
130
|
+
h = log.to_h
|
131
|
+
assert_match /measure_test.rb/, h[:file], h
|
132
|
+
assert h[:line].is_a?(Integer)
|
88
133
|
end
|
89
134
|
end
|
90
135
|
end
|
91
136
|
|
92
137
|
describe "#measure(#{level})" do
|
93
138
|
it ':message' do
|
94
|
-
assert_equal 'result',
|
95
|
-
|
96
|
-
|
139
|
+
assert_equal 'result', logger.measure(level, 'hello world') { 'result' }
|
140
|
+
|
141
|
+
assert log = log_message
|
142
|
+
assert_equal 'hello world', log.message
|
143
|
+
end
|
144
|
+
|
145
|
+
it ':level' do
|
146
|
+
assert_equal 'result', logger.measure(level, 'hello world') { 'result' }
|
147
|
+
|
148
|
+
assert log = log_message
|
149
|
+
assert_equal level, log.level
|
97
150
|
end
|
98
151
|
|
99
152
|
it ':payload' do
|
100
|
-
assert_equal 'result',
|
101
|
-
|
102
|
-
|
153
|
+
assert_equal 'result', logger.measure(level, 'hello world', payload: payload) { 'result' }
|
154
|
+
|
155
|
+
assert log = log_message
|
156
|
+
assert_equal payload, log.payload
|
103
157
|
end
|
104
158
|
|
105
159
|
describe ':min_duration' do
|
106
160
|
it 'not log when faster' do
|
107
|
-
assert_equal 'result',
|
108
|
-
|
109
|
-
assert_nil @mock_logger.message
|
161
|
+
assert_equal 'result', logger.measure(level, 'hello world', min_duration: 2000) { 'result' }
|
162
|
+
refute log_message
|
110
163
|
end
|
111
164
|
|
112
165
|
it 'log when slower' do
|
113
|
-
assert_equal 'result',
|
114
|
-
|
115
|
-
|
166
|
+
assert_equal 'result', logger.measure(level, 'hello world', min_duration: 200, payload: payload) { sleep 0.5; 'result' }
|
167
|
+
assert log = log_message
|
168
|
+
assert_equal 'hello world', log.message
|
116
169
|
end
|
117
170
|
end
|
118
171
|
|
119
172
|
it ':exception' do
|
120
173
|
assert_raises RuntimeError do
|
121
|
-
|
174
|
+
logger.measure(level, 'hello world', payload: payload) { raise RuntimeError.new('Test') }
|
122
175
|
end
|
123
|
-
|
124
|
-
|
176
|
+
|
177
|
+
assert log = log_message
|
178
|
+
refute log.exception
|
179
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
180
|
+
assert_equal level, log.level
|
181
|
+
end
|
182
|
+
|
183
|
+
it ':on_exception_level' do
|
184
|
+
assert_raises RuntimeError do
|
185
|
+
logger.measure(level, 'hello world', payload: payload, on_exception_level: :fatal) { raise RuntimeError.new('Test') }
|
186
|
+
end
|
187
|
+
|
188
|
+
assert log = log_message
|
189
|
+
refute log.exception
|
190
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
191
|
+
assert_equal :fatal, log.level
|
125
192
|
end
|
126
193
|
|
127
194
|
it ':metric' do
|
128
195
|
metric_name = '/my/custom/metric'
|
129
|
-
assert_equal 'result',
|
130
|
-
|
131
|
-
|
132
|
-
|
196
|
+
assert_equal 'result', logger.measure(level, 'hello world', metric: metric_name) { 'result' }
|
197
|
+
|
198
|
+
assert log = log_message
|
199
|
+
assert_equal metric_name, log.metric
|
133
200
|
end
|
134
201
|
|
135
|
-
it
|
202
|
+
it ':backtrace_level' do
|
136
203
|
SemanticLogger.stub(:backtrace_level_index, 0) do
|
137
|
-
assert_equal 'result',
|
138
|
-
|
139
|
-
|
204
|
+
assert_equal 'result', logger.measure(level, 'hello world') { 'result' }
|
205
|
+
|
206
|
+
assert log = log_message
|
207
|
+
assert log.backtrace
|
208
|
+
assert log.backtrace.size > 0
|
209
|
+
|
210
|
+
# Extract file name and line number from backtrace
|
211
|
+
h = log.to_h
|
212
|
+
assert_match /measure_test.rb/, h[:file], h
|
213
|
+
assert h[:line].is_a?(Integer)
|
140
214
|
end
|
141
215
|
end
|
142
216
|
end
|
143
217
|
|
144
|
-
describe "##{measure_level}
|
218
|
+
describe "##{measure_level} keyword arguments" do
|
145
219
|
it ':message' do
|
146
|
-
assert_equal 'result',
|
147
|
-
|
148
|
-
|
220
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world') { 'result' }
|
221
|
+
|
222
|
+
assert log = log_message
|
223
|
+
assert_equal 'hello world', log.message
|
224
|
+
end
|
225
|
+
|
226
|
+
it ':level' do
|
227
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world') { 'result' }
|
228
|
+
|
229
|
+
assert log = log_message
|
230
|
+
assert_equal level, log.level
|
149
231
|
end
|
150
232
|
|
151
233
|
it ':payload' do
|
152
|
-
assert_equal 'result',
|
153
|
-
|
154
|
-
|
234
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world', payload: payload) { 'result' }
|
235
|
+
|
236
|
+
assert log = log_message
|
237
|
+
assert_equal payload, log.payload
|
155
238
|
end
|
156
239
|
|
157
240
|
describe ':min_duration' do
|
158
241
|
it 'not log when faster' do
|
159
|
-
assert_equal 'result',
|
160
|
-
|
161
|
-
assert_nil @mock_logger.message
|
242
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world', min_duration: 2000) { 'result' }
|
243
|
+
refute log_message
|
162
244
|
end
|
163
245
|
|
164
246
|
it 'log when slower' do
|
165
|
-
assert_equal 'result',
|
166
|
-
|
167
|
-
|
247
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world', min_duration: 200, payload: payload) { sleep 0.5; 'result' }
|
248
|
+
|
249
|
+
assert log = log_message
|
250
|
+
assert_equal 'hello world', log.message
|
168
251
|
end
|
169
252
|
end
|
170
253
|
|
171
254
|
it ':exception' do
|
172
255
|
assert_raises RuntimeError do
|
173
|
-
|
256
|
+
logger.send(measure_level, message: 'hello world', payload: payload) { raise RuntimeError.new('Test') }
|
174
257
|
end
|
175
|
-
|
176
|
-
|
258
|
+
|
259
|
+
assert log = log_message
|
260
|
+
refute log.exception
|
261
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
262
|
+
assert_equal level, log.level
|
177
263
|
end
|
178
264
|
|
179
265
|
it ':on_exception_level' do
|
180
266
|
assert_raises RuntimeError do
|
181
|
-
|
267
|
+
logger.send(measure_level, message: 'hello world', payload: payload, on_exception_level: :fatal) { raise RuntimeError.new('Test') }
|
182
268
|
end
|
183
|
-
|
184
|
-
|
269
|
+
|
270
|
+
assert log = log_message
|
271
|
+
refute log.exception
|
272
|
+
assert_equal 'hello world -- Exception: RuntimeError: Test', log.message
|
273
|
+
assert_equal :fatal, log.level
|
185
274
|
end
|
186
275
|
|
187
276
|
it ':metric' do
|
188
277
|
metric_name = '/my/custom/metric'
|
189
|
-
assert_equal 'result',
|
190
|
-
|
191
|
-
|
192
|
-
|
278
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world', metric: metric_name) { 'result' }
|
279
|
+
|
280
|
+
assert log = log_message
|
281
|
+
assert_equal metric_name, log.metric
|
193
282
|
end
|
194
283
|
|
195
284
|
it ':backtrace_level' do
|
196
285
|
SemanticLogger.stub(:backtrace_level_index, 0) do
|
197
|
-
assert_equal 'result',
|
198
|
-
|
199
|
-
|
286
|
+
assert_equal 'result', logger.send(measure_level, message: 'hello world') { 'result' }
|
287
|
+
|
288
|
+
assert log = log_message
|
289
|
+
assert log.backtrace
|
290
|
+
assert log.backtrace.size > 0
|
291
|
+
|
292
|
+
# Extract file name and line number from backtrace
|
293
|
+
h = log.to_h
|
294
|
+
assert_match /measure_test.rb/, h[:file], h
|
295
|
+
assert h[:line].is_a?(Integer)
|
200
296
|
end
|
201
297
|
end
|
202
298
|
end
|
@@ -205,41 +301,44 @@ class MeasureTest < Minitest::Test
|
|
205
301
|
|
206
302
|
describe 'return' do
|
207
303
|
it 'log when the block performs a return' do
|
208
|
-
assert_equal 'Good', function_with_return(
|
209
|
-
|
210
|
-
|
304
|
+
assert_equal 'Good', function_with_return(logger)
|
305
|
+
|
306
|
+
assert log = log_message
|
307
|
+
assert_equal 'hello world', log.message
|
211
308
|
end
|
212
309
|
end
|
213
310
|
|
214
311
|
describe ':silence' do
|
215
312
|
it 'silences messages' do
|
216
313
|
SemanticLogger.default_level = :info
|
217
|
-
|
218
|
-
|
314
|
+
logger.measure_info('hello world', silence: :error) do
|
315
|
+
logger.warn "don't log me"
|
219
316
|
end
|
220
|
-
|
221
|
-
|
317
|
+
|
318
|
+
assert log = log_message
|
319
|
+
assert_equal 'hello world', log.message
|
222
320
|
end
|
223
321
|
|
224
|
-
it 'does not silence
|
322
|
+
it 'does not silence higher level messages' do
|
225
323
|
SemanticLogger.default_level = :info
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
first_message = @mock_logger.message
|
324
|
+
first = nil
|
325
|
+
logger.measure_info('hello world', silence: :trace) do
|
326
|
+
logger.debug('hello world', payload) { 'Calculations' }
|
327
|
+
first = log_message
|
231
328
|
end
|
232
|
-
|
329
|
+
assert_equal 'hello world -- Calculations', first.message
|
330
|
+
assert_equal payload, first.payload
|
331
|
+
|
233
332
|
SemanticLogger.flush
|
234
|
-
|
235
|
-
|
333
|
+
assert log = appender.message
|
334
|
+
assert_equal 'hello world', log.message
|
236
335
|
end
|
237
336
|
end
|
238
337
|
|
239
338
|
# Make sure that measure still logs when a block uses return to return from
|
240
339
|
# a function
|
241
340
|
def function_with_return(logger)
|
242
|
-
logger.measure_info('hello world', payload:
|
341
|
+
logger.measure_info('hello world', payload: payload) do
|
243
342
|
return 'Good'
|
244
343
|
end
|
245
344
|
'Bad'
|