semantic_logger 2.6.1 → 2.7.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: 57d9f8129cdac0b2d839354b15da27622c0726a4
4
- data.tar.gz: ada6c3c38029da4532ca51f2c5a5f7234f1e1d00
3
+ metadata.gz: c16da0b153fc6641eb7fc40fdf7cb8ee2ffe74cd
4
+ data.tar.gz: 4907de6046cbbf1b7c5ea6f513faecc18bea3efb
5
5
  SHA512:
6
- metadata.gz: b8af90aa234d643efa2ba2a2e26d4c41be20af8b9621d570513e4715061af5d816e005c1d2c3c740a5f5b018b48defff44c259c1d8b3214abdfdea97fa5bbe2d
7
- data.tar.gz: 4bde8f95c0524a4b10b1ce800435ea796016d18a923fcdcd9d7e01b32e965c4f34c5703ce81bbab6b5208141f21a46cecb10fcf757d10cc53afac60ec9eecc9b
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 messag
314
+ Log the exception class and message
315
315
  The backtrace will not be logged
316
316
  :off
317
- Any unhandled exception from the block will not be logged
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: Syslog, hadoop, redis, etc..
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
 
@@ -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
- if exception.nil? && payload && payload.is_a?(Exception)
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 = nil)
106
- raise "Mandatory block missing" unless block_given?
86
+ def benchmark_#{level}(message, params = {}, &block)
107
87
  if @level_index <= #{index}
108
- log_exception = params.nil? ? :partial : (params[:log_exception] || :partial)
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
- yield
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
- Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception)
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 for logging and debugging purposes
21
- def name=(name)
22
- @name = name.to_s
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 = nil
112
- @@queue = Queue.new
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.info "Appender thread: Flushing appender: #{appender.name}"
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.info "Appender thread: All appenders flushed"
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
 
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger #:nodoc
2
- VERSION = "2.6.1"
2
+ VERSION = "2.7.0"
3
3
  end
@@ -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 = SemanticLogger::Logger.new(self.class, :trace)
22
- @hash = { :session_id => 'HSSKLEU@JDK767', :tracking_number => 12345 }
23
- @hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
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.6.1
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: 2013-12-11 00:00:00.000000000 Z
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.1.11
91
+ rubygems_version: 2.2.0
92
92
  signing_key:
93
93
  specification_version: 4
94
94
  summary: Improved logging for Ruby