semantic_logger 2.6.1 → 2.7.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 +4 -4
- data/README.md +63 -6
- data/lib/semantic_logger/appender/base.rb +2 -2
- data/lib/semantic_logger/base.rb +74 -57
- data/lib/semantic_logger/core_ext/thread.rb +11 -7
- data/lib/semantic_logger/logger.rb +34 -4
- data/lib/semantic_logger/semantic_logger.rb +15 -2
- data/lib/semantic_logger/version.rb +1 -1
- data/test/appender_file_test.rb +1 -1
- data/test/logger_test.rb +17 -3
- metadata +13 -13
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: c16da0b153fc6641eb7fc40fdf7cb8ee2ffe74cd
|
4
|
+
data.tar.gz: 4907de6046cbbf1b7c5ea6f513faecc18bea3efb
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b145848428794d626f5a5d3cd276c4d4929c868346962a24a502d618274c6cf967a7e6d028017c2c02b25a801b0dba014bb52a6cd29d8ef06153d5e9a9c25df7
|
7
|
+
data.tar.gz: bb09287501c04bb4c6db41231f8e3245a42f8b20d645d3fe63389dc875a27ba0f0187840a02756e05db346168435e755ab7f2a6f88d25340328a77115a1d06cf
|
data/README.md
CHANGED
@@ -311,20 +311,30 @@ Parameters
|
|
311
311
|
:full
|
312
312
|
Log the exception class, message, and backtrace
|
313
313
|
:partial
|
314
|
-
Log the exception class and
|
314
|
+
Log the exception class and message
|
315
315
|
The backtrace will not be logged
|
316
316
|
:off
|
317
|
-
Any unhandled exception
|
317
|
+
Any unhandled exception raised in the block will not be logged
|
318
|
+
Default: :partial
|
318
319
|
|
319
|
-
:min_duration
|
320
|
+
:min_duration [Float]
|
320
321
|
Only log if the block takes longer than this duration in ms
|
321
322
|
Default: 0.0
|
322
323
|
|
323
|
-
:payload
|
324
|
+
:payload [Hash]
|
324
325
|
Optional, Hash payload
|
325
326
|
|
326
|
-
:exception
|
327
|
+
:exception [Exception]
|
327
328
|
Optional, Ruby Exception object to log along with the duration of the supplied block
|
329
|
+
|
330
|
+
:duration [Float]
|
331
|
+
Optional, supply the duration in ms that is logged when a block is not supplied
|
332
|
+
If a block is not supplied then :duration is mandatory
|
333
|
+
If a block is supplied :duration is ignored
|
334
|
+
|
335
|
+
:metric [Object]
|
336
|
+
Optional, when this parameter is supplied all subscribers will be notified of this
|
337
|
+
metric, along with the Log Struct described below
|
328
338
|
```
|
329
339
|
|
330
340
|
### Logging levels
|
@@ -488,6 +498,9 @@ Sample output:
|
|
488
498
|
2013-11-07 16:26:02.744139 I [35841:User calculation thread 32] (0.0ms) ExternalSupplier -- Calling external interface
|
489
499
|
```
|
490
500
|
|
501
|
+
When running JRuby, Thread.current.name will also set the underlying thread name in the JVM
|
502
|
+
which is very useful when monitoring the JVM via JMX using tools such as jconsole.
|
503
|
+
|
491
504
|
#### NOTE:
|
492
505
|
|
493
506
|
Make sure that the assigned thread name is unique otherwise it will be difficult
|
@@ -499,6 +512,45 @@ For example, use the current thread object_id to ensure uniqueness:
|
|
499
512
|
Thread.current.name = "Worker Thread:#{Thread.current.object_id}"
|
500
513
|
```
|
501
514
|
|
515
|
+
### Metrics integration
|
516
|
+
|
517
|
+
In production environments it is often necessary to not only measure the performance of a
|
518
|
+
block of code using for example:
|
519
|
+
|
520
|
+
```ruby
|
521
|
+
logger.benchmark_info "Calling external interface" do
|
522
|
+
# Code to call the external supplier ...
|
523
|
+
end
|
524
|
+
```
|
525
|
+
|
526
|
+
Sending the performance information gathered above to something like NewRelic
|
527
|
+
is also very useful, and we can end up with:
|
528
|
+
|
529
|
+
```ruby
|
530
|
+
logger.benchmark_info "Calling external interface" do
|
531
|
+
self.class.trace_execution_scoped(['Custom/slow_action/beginning_work']) do
|
532
|
+
# Code to call the external supplier ...
|
533
|
+
end
|
534
|
+
end
|
535
|
+
```
|
536
|
+
|
537
|
+
Rather than wrapping the code everywhere with two blocks, a single subscriber can
|
538
|
+
be setup in config/initializers/semantic_logger_metrics.rb:
|
539
|
+
|
540
|
+
```ruby
|
541
|
+
SemanticLogger.on_metric do |log_struct|
|
542
|
+
::NewRelic::Agent.record_metric(log_struct.metric, log_struct.duration)
|
543
|
+
end
|
544
|
+
```
|
545
|
+
|
546
|
+
Then update the log entry as follows:
|
547
|
+
|
548
|
+
```ruby
|
549
|
+
logger.benchmark_info "Calling external interface", :metric => 'Custom/slow_action/beginning_work' do
|
550
|
+
# Code to call the external supplier ...
|
551
|
+
end
|
552
|
+
```
|
553
|
+
|
502
554
|
## Standalone SemanticLogger
|
503
555
|
|
504
556
|
When using SemanticLogger inside of Rails all we need to do is include the
|
@@ -843,6 +895,11 @@ Once the logging data is in the NOSQL data store it can be queried quickly and
|
|
843
895
|
efficiently. Some SQL data stores also allow complex data types that could be used
|
844
896
|
for storing and querying the logging data
|
845
897
|
|
898
|
+
Before writing SemanticLogger all of the following logging frameworks were thoroughly
|
899
|
+
evaluated. None of them met the above Semantic requirements, or the performance requirements
|
900
|
+
of hundreds of threads all logging at the same time:
|
901
|
+
logback, logging, log4r, central_logger, whoops
|
902
|
+
|
846
903
|
## Architecture & Performance
|
847
904
|
|
848
905
|
In order to ensure that logging does not hinder the performance of the application
|
@@ -931,7 +988,7 @@ To log to MongoDB, it also needs the Ruby Mongo Driver
|
|
931
988
|
|
932
989
|
- Add support for a configuration file that can set log level by class name
|
933
990
|
- Configuration file to support adding appenders
|
934
|
-
- Based on end-user demand add appenders for:
|
991
|
+
- Based on end-user demand add appenders for: hadoop, redis, etc..
|
935
992
|
|
936
993
|
Meta
|
937
994
|
----
|
@@ -36,7 +36,7 @@ module SemanticLogger
|
|
36
36
|
|
37
37
|
message = log.message.to_s.dup
|
38
38
|
message << " -- " << log.payload.inspect if log.payload
|
39
|
-
message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
39
|
+
message << " -- Exception: " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
40
40
|
|
41
41
|
duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
|
42
42
|
|
@@ -56,7 +56,7 @@ module SemanticLogger
|
|
56
56
|
|
57
57
|
message = log.message.to_s.dup
|
58
58
|
message << " -- " << log.payload.inspect if log.payload
|
59
|
-
message << " -- " << "#{colors::BOLD}#{log.exception.class}: #{log.exception.message}#{colors::CLEAR}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
59
|
+
message << " -- Exception: " << "#{colors::BOLD}#{log.exception.class}: #{log.exception.message}#{colors::CLEAR}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
|
60
60
|
|
61
61
|
duration_str = log.duration ? "(#{colors::BOLD}#{'%.1f' % log.duration}ms#{colors::CLEAR}) " : ''
|
62
62
|
|
data/lib/semantic_logger/base.rb
CHANGED
@@ -70,28 +70,9 @@ module SemanticLogger
|
|
70
70
|
#
|
71
71
|
SemanticLogger::LEVELS.each_with_index do |level, index|
|
72
72
|
class_eval <<-EOT, __FILE__, __LINE__
|
73
|
-
def #{level}(message=nil, payload=nil, exception=nil)
|
73
|
+
def #{level}(message=nil, payload=nil, exception=nil, &block)
|
74
74
|
if @level_index <= #{index}
|
75
|
-
|
76
|
-
exception = payload
|
77
|
-
payload = nil
|
78
|
-
end
|
79
|
-
|
80
|
-
if block_given? && (result = yield)
|
81
|
-
if result.is_a?(String)
|
82
|
-
message = message.nil? ? result : "\#{message} -- \#{result}"
|
83
|
-
elsif payload && payload.respond_to?(:merge)
|
84
|
-
payload.merge(result)
|
85
|
-
else
|
86
|
-
payload = result
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Add scoped payload
|
91
|
-
if self.payload
|
92
|
-
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
93
|
-
end
|
94
|
-
log Log.new(:#{level}, Thread.current.name, name, message, payload, Time.now, nil, tags, #{index}, exception)
|
75
|
+
log_internal(:#{level}, #{index}, message, payload, exception, &block)
|
95
76
|
true
|
96
77
|
else
|
97
78
|
false
|
@@ -102,41 +83,11 @@ module SemanticLogger
|
|
102
83
|
@level_index <= #{index}
|
103
84
|
end
|
104
85
|
|
105
|
-
def benchmark_#{level}(message, params =
|
106
|
-
raise "Mandatory block missing" unless block_given?
|
86
|
+
def benchmark_#{level}(message, params = {}, &block)
|
107
87
|
if @level_index <= #{index}
|
108
|
-
|
109
|
-
min_duration = params.nil? ? 0.0 : (params[:min_duration] || 0.0)
|
110
|
-
payload = params.nil? ? nil : params[:payload]
|
111
|
-
exception = params.nil? ? nil : params[:exception]
|
112
|
-
start = Time.now
|
113
|
-
begin
|
114
|
-
yield
|
115
|
-
rescue Exception => exc
|
116
|
-
exception = exc
|
117
|
-
ensure
|
118
|
-
end_time = Time.now
|
119
|
-
duration = 1000.0 * (end_time - start)
|
120
|
-
|
121
|
-
# Add scoped payload
|
122
|
-
if self.payload
|
123
|
-
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
124
|
-
end
|
125
|
-
if exception
|
126
|
-
case log_exception
|
127
|
-
when :full
|
128
|
-
log Log.new(:#{level}, Thread.current.name, name, message, payload, end_time, duration, tags, #{index}, exception)
|
129
|
-
when :partial
|
130
|
-
log Log.new(:#{level}, Thread.current.name, name, "\#{message} -- Exception: \#{exception.class}: \#{exception.message}", payload, end_time, duration, tags, #{index}, nil)
|
131
|
-
end
|
132
|
-
raise exception
|
133
|
-
elsif duration >= min_duration
|
134
|
-
# Only log if the block took longer than 'min_duration' to complete
|
135
|
-
log Log.new(:#{level}, Thread.current.name, name, message, payload, end_time, duration, tags, #{index}, nil)
|
136
|
-
end
|
137
|
-
end
|
88
|
+
benchmark_internal(:#{level}, #{index}, message, params, &block)
|
138
89
|
else
|
139
|
-
|
90
|
+
block.call(params) if block
|
140
91
|
end
|
141
92
|
end
|
142
93
|
EOT
|
@@ -213,8 +164,6 @@ module SemanticLogger
|
|
213
164
|
alias :unknown :error
|
214
165
|
alias :unknown? :error?
|
215
166
|
|
216
|
-
# #TODO implement a thread safe #silence method
|
217
|
-
|
218
167
|
# DEPRECATED See SemanticLogger.default_level=
|
219
168
|
def self.default_level=(level)
|
220
169
|
warn "[DEPRECATION] `SemanticLogger::Logger.default_level=` is deprecated. Please use `SemanticLogger.default_level=` instead."
|
@@ -272,7 +221,10 @@ module SemanticLogger
|
|
272
221
|
#
|
273
222
|
# level_index
|
274
223
|
# Internal index of the log level
|
275
|
-
|
224
|
+
#
|
225
|
+
# metric [Object]
|
226
|
+
# Object supplied when benchmark_x was called
|
227
|
+
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception, :metric)
|
276
228
|
|
277
229
|
# Internal method to return the log level as an internal index
|
278
230
|
# Also supports mapping the ::Logger levels to SemanticLogger levels
|
@@ -297,5 +249,70 @@ module SemanticLogger
|
|
297
249
|
index
|
298
250
|
end
|
299
251
|
|
252
|
+
# Log message at the specified level
|
253
|
+
def log_internal(level, index, message=nil, payload=nil, exception=nil, &block)
|
254
|
+
if exception.nil? && payload && payload.is_a?(Exception)
|
255
|
+
exception = payload
|
256
|
+
payload = nil
|
257
|
+
end
|
258
|
+
|
259
|
+
if block && (result = block.call)
|
260
|
+
if result.is_a?(String)
|
261
|
+
message = message.nil? ? result : "#{message} -- #{result}"
|
262
|
+
elsif payload && payload.respond_to?(:merge)
|
263
|
+
payload.merge(result)
|
264
|
+
else
|
265
|
+
payload = result
|
266
|
+
end
|
267
|
+
end
|
268
|
+
|
269
|
+
# Add scoped payload
|
270
|
+
if self.payload
|
271
|
+
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
272
|
+
end
|
273
|
+
log Log.new(level, Thread.current.name, name, message, payload, Time.now, nil, tags, index, exception)
|
274
|
+
end
|
275
|
+
|
276
|
+
# Measure the supplied block and log the message
|
277
|
+
def benchmark_internal(level, index, message, params, &block)
|
278
|
+
start = Time.now
|
279
|
+
begin
|
280
|
+
rc = block.call(params) if block
|
281
|
+
exception = params[:exception]
|
282
|
+
rc
|
283
|
+
rescue Exception => exc
|
284
|
+
exception = exc
|
285
|
+
ensure
|
286
|
+
end_time = Time.now
|
287
|
+
# Extract options after block completes so that block can modify any of the options
|
288
|
+
log_exception = params[:log_exception] || :partial
|
289
|
+
min_duration = params[:min_duration] || 0.0
|
290
|
+
payload = params[:payload]
|
291
|
+
metric = params[:metric]
|
292
|
+
duration = if block_given?
|
293
|
+
1000.0 * (end_time - start)
|
294
|
+
else
|
295
|
+
params[:duration] || raise("Mandatory block missing when :duration option is not supplied")
|
296
|
+
end
|
297
|
+
|
298
|
+
# Add scoped payload
|
299
|
+
if self.payload
|
300
|
+
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
301
|
+
end
|
302
|
+
if exception
|
303
|
+
case log_exception
|
304
|
+
when :full
|
305
|
+
log Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, exception, metric)
|
306
|
+
when :partial
|
307
|
+
log Log.new(level, Thread.current.name, name, "#{message} -- Exception: #{exception.class}: #{exception.message}", payload, end_time, duration, tags, index, nil, metric)
|
308
|
+
end
|
309
|
+
raise exception
|
310
|
+
elsif duration >= min_duration
|
311
|
+
# Only log if the block took longer than 'min_duration' to complete
|
312
|
+
log Log.new(level, Thread.current.name, name, message, payload, end_time, duration, tags, index, nil, metric)
|
313
|
+
end
|
314
|
+
end
|
315
|
+
end
|
316
|
+
|
300
317
|
end
|
301
318
|
end
|
@@ -2,12 +2,9 @@ require 'thread'
|
|
2
2
|
class Thread
|
3
3
|
# Returns the name of the current thread
|
4
4
|
# Default:
|
5
|
-
# JRuby: The Java thread name
|
5
|
+
# JRuby: The underlying Java thread name
|
6
6
|
# Other: String representation of this thread's object_id
|
7
7
|
if defined? JRuby
|
8
|
-
# Design Note:
|
9
|
-
# In JRuby with "thread.pool.enabled=true" each Ruby Thread instance is
|
10
|
-
# new, even though the Java threads are being re-used from the pool
|
11
8
|
def name
|
12
9
|
@name ||= JRuby.reference(self).native_thread.name
|
13
10
|
end
|
@@ -17,8 +14,15 @@ class Thread
|
|
17
14
|
end
|
18
15
|
end
|
19
16
|
|
20
|
-
# Set the name of this thread
|
21
|
-
|
22
|
-
|
17
|
+
# Set the name of this thread
|
18
|
+
# On JRuby it also sets the underlying Java Thread name
|
19
|
+
if defined? JRuby
|
20
|
+
def name=(name)
|
21
|
+
JRuby.reference(self).native_thread.name = @name = name.to_s
|
22
|
+
end
|
23
|
+
else
|
24
|
+
def name=(name)
|
25
|
+
@name = name.to_s
|
26
|
+
end
|
23
27
|
end
|
24
28
|
end
|
@@ -105,11 +105,26 @@ module SemanticLogger
|
|
105
105
|
queue_size
|
106
106
|
end
|
107
107
|
|
108
|
+
# Supply a block to be called whenever a metric is seen during benchmark logging
|
109
|
+
#
|
110
|
+
# Parameters
|
111
|
+
# block
|
112
|
+
# The block to be called
|
113
|
+
#
|
114
|
+
# Example:
|
115
|
+
# SemanticLogger.on_metric do |log_struct|
|
116
|
+
# puts "#{log_struct.metric} was received. Log Struct: #{log_struct.inspect}"
|
117
|
+
# end
|
118
|
+
def self.on_metric(&block)
|
119
|
+
(@@metric_subscribers ||= ThreadSafe::Array.new) << block
|
120
|
+
end
|
121
|
+
|
108
122
|
############################################################################
|
109
123
|
protected
|
110
124
|
|
111
|
-
@@appender_thread
|
112
|
-
@@queue
|
125
|
+
@@appender_thread = nil
|
126
|
+
@@queue = Queue.new
|
127
|
+
@@metric_subscribers = nil
|
113
128
|
|
114
129
|
# Queue to hold messages that need to be logged to the various appenders
|
115
130
|
def self.queue
|
@@ -167,6 +182,7 @@ module SemanticLogger
|
|
167
182
|
logger.error "Appender thread: Failed to log to appender: #{appender.inspect}", exc
|
168
183
|
end
|
169
184
|
end
|
185
|
+
call_metric_subscribers(message) if message.metric
|
170
186
|
count += 1
|
171
187
|
# Check every few log messages whether this appender thread is falling behind
|
172
188
|
if count > lag_check_interval
|
@@ -180,7 +196,7 @@ module SemanticLogger
|
|
180
196
|
when :flush
|
181
197
|
SemanticLogger.appenders.each do |appender|
|
182
198
|
begin
|
183
|
-
logger.
|
199
|
+
logger.debug "Appender thread: Flushing appender: #{appender.name}"
|
184
200
|
appender.flush
|
185
201
|
rescue Exception => exc
|
186
202
|
logger.error "Appender thread: Failed to flush appender: #{appender.inspect}", exc
|
@@ -188,7 +204,7 @@ module SemanticLogger
|
|
188
204
|
end
|
189
205
|
|
190
206
|
message[:reply_queue] << true if message[:reply_queue]
|
191
|
-
logger.
|
207
|
+
logger.debug "Appender thread: All appenders flushed"
|
192
208
|
else
|
193
209
|
logger.warn "Appender thread: Ignoring unknown command: #{message[:command]}"
|
194
210
|
end
|
@@ -213,5 +229,19 @@ module SemanticLogger
|
|
213
229
|
end
|
214
230
|
end
|
215
231
|
|
232
|
+
# Call Metric subscribers
|
233
|
+
def self.call_metric_subscribers(log_struct)
|
234
|
+
# If no subscribers registered, then return immediately
|
235
|
+
return unless @@metric_subscribers
|
236
|
+
|
237
|
+
@@metric_subscribers.each do |subscriber|
|
238
|
+
begin
|
239
|
+
subscriber.call(log_struct)
|
240
|
+
rescue Exception => exc
|
241
|
+
logger.error "Exception calling subscriber", exc
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
|
216
246
|
end
|
217
247
|
end
|
@@ -102,13 +102,12 @@ module SemanticLogger
|
|
102
102
|
|
103
103
|
# Start appender thread if it is not already running
|
104
104
|
SemanticLogger::Logger.start_appender_thread
|
105
|
-
|
105
|
+
|
106
106
|
appender_instance
|
107
107
|
end
|
108
108
|
|
109
109
|
# Remove an existing appender
|
110
110
|
# Currently only supports appender instances
|
111
|
-
# TODO allow removing by filename, STDOUT etc..
|
112
111
|
def self.remove_appender(appender)
|
113
112
|
@@appenders.delete(appender)
|
114
113
|
end
|
@@ -137,6 +136,20 @@ module SemanticLogger
|
|
137
136
|
SemanticLogger::Logger.start_appender_thread
|
138
137
|
end
|
139
138
|
|
139
|
+
# Supply a block to be called whenever a metric is seen during benchmark logging
|
140
|
+
#
|
141
|
+
# Parameters
|
142
|
+
# block
|
143
|
+
# The block to be called
|
144
|
+
#
|
145
|
+
# Example:
|
146
|
+
# SemanticLogger.on_metric do |log_struct|
|
147
|
+
# puts "#{log_struct.metric} was received. Log Struct: #{log_struct.inspect}"
|
148
|
+
# end
|
149
|
+
def self.on_metric(&block)
|
150
|
+
SemanticLogger::Logger.on_metric(&block)
|
151
|
+
end
|
152
|
+
|
140
153
|
############################################################################
|
141
154
|
protected
|
142
155
|
|
data/test/appender_file_test.rb
CHANGED
@@ -39,7 +39,7 @@ class AppenderFileTest < Test::Unit::TestCase
|
|
39
39
|
|
40
40
|
should "handle message, payload, and exception" do
|
41
41
|
@appender.debug 'hello world', @hash, StandardError.new("StandardError")
|
42
|
-
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ D \[\d+:#{@thread_name}\] SemanticLogger::Appender::File -- hello world -- #{@hash_str} -- StandardError: StandardError\n\n/, @io.string
|
42
|
+
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ D \[\d+:#{@thread_name}\] SemanticLogger::Appender::File -- hello world -- #{@hash_str} -- Exception: StandardError: StandardError\n\n/, @io.string
|
43
43
|
end
|
44
44
|
end
|
45
45
|
|
data/test/logger_test.rb
CHANGED
@@ -17,10 +17,16 @@ class LoggerTest < Test::Unit::TestCase
|
|
17
17
|
@mock_logger = MockLogger.new
|
18
18
|
SemanticLogger.add_appender(@mock_logger)
|
19
19
|
|
20
|
+
# Add mock metric subscriber
|
21
|
+
$last_metric = nil
|
22
|
+
SemanticLogger.on_metric do |log_struct|
|
23
|
+
$last_metric = log_struct.dup
|
24
|
+
end
|
25
|
+
|
20
26
|
# Use this test's class name as the application name in the log output
|
21
|
-
@logger
|
22
|
-
@hash
|
23
|
-
@hash_str
|
27
|
+
@logger = SemanticLogger::Logger.new(self.class, :trace)
|
28
|
+
@hash = { :session_id => 'HSSKLEU@JDK767', :tracking_number => 12345 }
|
29
|
+
@hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
|
24
30
|
assert_equal [], @logger.tags
|
25
31
|
end
|
26
32
|
|
@@ -120,6 +126,14 @@ class LoggerTest < Test::Unit::TestCase
|
|
120
126
|
SemanticLogger.flush
|
121
127
|
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- Exception: RuntimeError: Test -- #{@hash_str}/, @mock_logger.message
|
122
128
|
end
|
129
|
+
|
130
|
+
should "log #{level} info with metric" do
|
131
|
+
metric_name = '/my/custom/metric'
|
132
|
+
assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', metric: metric_name) { "result" } # Measure duration of the supplied block
|
133
|
+
SemanticLogger.flush
|
134
|
+
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world/, @mock_logger.message
|
135
|
+
assert metric_name, $last_metric.metric
|
136
|
+
end
|
123
137
|
end
|
124
138
|
|
125
139
|
should "log when the block performs a return" do
|
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semantic_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.
|
4
|
+
version: 2.7.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Reid Morrison
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2014-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: sync_attr
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '1.0'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '1.0'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: thread_safe
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- -
|
31
|
+
- - ">="
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: 0.1.0
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- -
|
38
|
+
- - ">="
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: 0.1.0
|
41
41
|
description: Semantic Logger takes logging in Ruby to a new level by adding several
|
@@ -46,6 +46,10 @@ executables: []
|
|
46
46
|
extensions: []
|
47
47
|
extra_rdoc_files: []
|
48
48
|
files:
|
49
|
+
- LICENSE.txt
|
50
|
+
- README.md
|
51
|
+
- Rakefile
|
52
|
+
- lib/semantic_logger.rb
|
49
53
|
- lib/semantic_logger/appender/base.rb
|
50
54
|
- lib/semantic_logger/appender/file.rb
|
51
55
|
- lib/semantic_logger/appender/mongodb.rb
|
@@ -57,10 +61,6 @@ files:
|
|
57
61
|
- lib/semantic_logger/logger.rb
|
58
62
|
- lib/semantic_logger/semantic_logger.rb
|
59
63
|
- lib/semantic_logger/version.rb
|
60
|
-
- lib/semantic_logger.rb
|
61
|
-
- LICENSE.txt
|
62
|
-
- Rakefile
|
63
|
-
- README.md
|
64
64
|
- test/appender_file_test.rb
|
65
65
|
- test/appender_mongodb_test.rb
|
66
66
|
- test/appender_syslog_test.rb
|
@@ -78,17 +78,17 @@ require_paths:
|
|
78
78
|
- lib
|
79
79
|
required_ruby_version: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
85
85
|
requirements:
|
86
|
-
- -
|
86
|
+
- - ">="
|
87
87
|
- !ruby/object:Gem::Version
|
88
88
|
version: '0'
|
89
89
|
requirements: []
|
90
90
|
rubyforge_project:
|
91
|
-
rubygems_version: 2.
|
91
|
+
rubygems_version: 2.2.0
|
92
92
|
signing_key:
|
93
93
|
specification_version: 4
|
94
94
|
summary: Improved logging for Ruby
|