semantic_logger 0.8.1 → 0.9.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.
- data/README.md +3 -2
- data/lib/semantic_logger.rb +1 -0
- data/lib/semantic_logger/appender/base.rb +83 -0
- data/lib/semantic_logger/appender/file.rb +1 -1
- data/lib/semantic_logger/appender/mongodb.rb +1 -1
- data/lib/semantic_logger/appender/wrapper.rb +1 -3
- data/lib/semantic_logger/base.rb +31 -70
- data/lib/semantic_logger/logger.rb +10 -26
- data/lib/semantic_logger/version.rb +1 -1
- data/semantic_logger-0.8.1.gem +0 -0
- data/test/appender_mongodb_test.rb +5 -5
- metadata +5 -3
data/README.md
CHANGED
@@ -725,15 +725,16 @@ Basic outline for an Appender:
|
|
725
725
|
```ruby
|
726
726
|
require 'semantic_logger'
|
727
727
|
|
728
|
-
class SimpleAppender < SemanticLogger::Base
|
728
|
+
class SimpleAppender < SemanticLogger::Appender::Base
|
729
729
|
def initialize(level=nil, &block)
|
730
730
|
# Set the log level and formatter if supplied
|
731
731
|
super(level, &block)
|
732
732
|
end
|
733
733
|
|
734
|
-
#
|
734
|
+
# Display the log struct and the text formatted output
|
735
735
|
def log(log)
|
736
736
|
p log
|
737
|
+
puts @formatter.call(log)
|
737
738
|
end
|
738
739
|
|
739
740
|
# Optional
|
data/lib/semantic_logger.rb
CHANGED
@@ -3,6 +3,7 @@ module SemanticLogger
|
|
3
3
|
autoload :Logger, 'semantic_logger/logger'
|
4
4
|
|
5
5
|
module Appender
|
6
|
+
autoload :Base, 'semantic_logger/appender/base'
|
6
7
|
autoload :File, 'semantic_logger/appender/file'
|
7
8
|
autoload :Wrapper, 'semantic_logger/appender/wrapper'
|
8
9
|
autoload :MongoDB, 'semantic_logger/appender/mongodb'
|
@@ -0,0 +1,83 @@
|
|
1
|
+
# Base appender
|
2
|
+
#
|
3
|
+
# Abstract base class for appenders
|
4
|
+
#
|
5
|
+
# Implements common behavior such as default text formatter etc
|
6
|
+
#
|
7
|
+
# Note: Do not create instances of this class directly
|
8
|
+
#
|
9
|
+
module SemanticLogger
|
10
|
+
module Appender
|
11
|
+
class Base < SemanticLogger::Base
|
12
|
+
attr_accessor :formatter
|
13
|
+
|
14
|
+
# Default log formatter
|
15
|
+
# Replace this formatter by supplying a Block to the initializer
|
16
|
+
# Generates logs of the form:
|
17
|
+
# 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
|
18
|
+
def default_formatter
|
19
|
+
Proc.new do |log|
|
20
|
+
message = log.message.to_s
|
21
|
+
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
22
|
+
|
23
|
+
if log.payload
|
24
|
+
if log.payload.is_a?(Exception)
|
25
|
+
exception = log.payload
|
26
|
+
message << " -- " << "#{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
|
27
|
+
else
|
28
|
+
message << " -- " << self.class.inspect_payload(log.payload)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
|
33
|
+
|
34
|
+
"#{SemanticLogger::Appender::Base.formatted_time(log.time)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{duration_str}#{log.name} -- #{message}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
############################################################################
|
39
|
+
protected
|
40
|
+
|
41
|
+
# By default the appender should log everything that is sent to it by
|
42
|
+
# the loggers. That way the loggers control the log level
|
43
|
+
# By setting the log level to a higher value the appender can be setup
|
44
|
+
# to log for example only :warn or higher while other appenders
|
45
|
+
# are able to log lower level information
|
46
|
+
def initialize(level, &block)
|
47
|
+
# Set the formatter to the supplied block
|
48
|
+
@formatter = block || default_formatter
|
49
|
+
|
50
|
+
# Appenders don't take a class name, so use this class name if an appender
|
51
|
+
# is logged to directly
|
52
|
+
super(self.class, level || :trace)
|
53
|
+
end
|
54
|
+
|
55
|
+
# For JRuby include the Thread name rather than its id
|
56
|
+
if defined? Java
|
57
|
+
# Return the Time as a formatted string
|
58
|
+
# JRuby only supports time in ms
|
59
|
+
def self.formatted_time(time)
|
60
|
+
"#{time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (time.usec/1000)}"
|
61
|
+
end
|
62
|
+
else
|
63
|
+
# Return the Time as a formatted string
|
64
|
+
# Ruby MRI supports micro seconds
|
65
|
+
def self.formatted_time(time)
|
66
|
+
"#{time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%06d" % (time.usec)}"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if RUBY_VERSION.to_f >= 1.9
|
71
|
+
# With Ruby 1.9 calling .to_s on a hash now returns { 'a' => 1 }
|
72
|
+
def self.inspect_payload(payload)
|
73
|
+
payload.to_s
|
74
|
+
end
|
75
|
+
else
|
76
|
+
def self.inspect_payload(payload)
|
77
|
+
payload.inspect
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -42,7 +42,7 @@ module SemanticLogger
|
|
42
42
|
# params: Hash
|
43
43
|
#
|
44
44
|
# tracking_number: 'user defined tracking number'
|
45
|
-
class MongoDB < SemanticLogger::Base
|
45
|
+
class MongoDB < SemanticLogger::Appender::Base
|
46
46
|
attr_reader :db, :collection_name
|
47
47
|
attr_accessor :host_name, :safe, :application
|
48
48
|
|
@@ -4,7 +4,7 @@
|
|
4
4
|
#
|
5
5
|
module SemanticLogger
|
6
6
|
module Appender
|
7
|
-
class Wrapper < SemanticLogger::Base
|
7
|
+
class Wrapper < SemanticLogger::Appender::Base
|
8
8
|
attr_reader :logger
|
9
9
|
|
10
10
|
# Create a Logger or Rails Logger appender instance
|
@@ -36,8 +36,6 @@ module SemanticLogger
|
|
36
36
|
super(:trace, &block)
|
37
37
|
end
|
38
38
|
|
39
|
-
# TODO Compatible calls to #level and #level= against the underlying Rails/Ruby logger
|
40
|
-
|
41
39
|
# Pass log calls to the underlying Rails, log4j or Ruby logger
|
42
40
|
# trace entries are mapped to debug since :trace is not supported by the
|
43
41
|
# Ruby or Rails Loggers
|
data/lib/semantic_logger/base.rb
CHANGED
@@ -1,6 +1,6 @@
|
|
1
|
-
# Base
|
1
|
+
# Base logger
|
2
2
|
#
|
3
|
-
# Abstract base class for
|
3
|
+
# Abstract base class for loggers
|
4
4
|
#
|
5
5
|
# Implements common behavior such as log level, default text formatter etc
|
6
6
|
#
|
@@ -8,47 +8,12 @@
|
|
8
8
|
#
|
9
9
|
module SemanticLogger
|
10
10
|
class Base
|
11
|
-
|
12
|
-
|
11
|
+
# Class name to be logged
|
12
|
+
attr_accessor :name
|
13
13
|
|
14
|
-
|
15
|
-
# Set the formatter to the supplied block
|
16
|
-
@formatter = block || default_formatter
|
14
|
+
attr_reader :level
|
17
15
|
|
18
|
-
|
19
|
-
self.level = level || :trace
|
20
|
-
end
|
21
|
-
|
22
|
-
# Default log formatter
|
23
|
-
# Replace this formatter by supplying a Block to the initializer
|
24
|
-
# Generates logs of the form:
|
25
|
-
# 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
|
26
|
-
def default_formatter
|
27
|
-
Proc.new do |log|
|
28
|
-
message = log.message.to_s
|
29
|
-
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
30
|
-
|
31
|
-
if log.payload
|
32
|
-
if log.payload.is_a?(Exception)
|
33
|
-
exception = log.payload
|
34
|
-
message << " -- " << "#{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
|
35
|
-
else
|
36
|
-
message << " -- " << self.class.inspect_payload(log.payload)
|
37
|
-
end
|
38
|
-
end
|
39
|
-
|
40
|
-
duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
|
41
|
-
|
42
|
-
"#{SemanticLogger::Base.formatted_time(log.time)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{duration_str}#{log.name} -- #{message}"
|
43
|
-
end
|
44
|
-
end
|
45
|
-
|
46
|
-
# Write log data to underlying data storage
|
47
|
-
def log(log_)
|
48
|
-
raise "Logging Appender must implement #log(log)"
|
49
|
-
end
|
50
|
-
|
51
|
-
# Set the logging level for this appender
|
16
|
+
# Set the logging level for this logger
|
52
17
|
#
|
53
18
|
# Note: This level is only for this particular appender. It does not override
|
54
19
|
# the log level in any logging instance or the default log level
|
@@ -209,9 +174,34 @@ module SemanticLogger
|
|
209
174
|
|
210
175
|
# #TODO implement a thread safe #silence method
|
211
176
|
|
177
|
+
# Initial default Level for all new instances of SemanticLogger::Logger
|
178
|
+
@@default_level = :info
|
179
|
+
|
180
|
+
# Allow for setting the global default log level
|
181
|
+
# This change only applies to _new_ loggers, existing logger levels
|
182
|
+
# will not be changed in any way
|
183
|
+
def self.default_level=(level)
|
184
|
+
@@default_level = level
|
185
|
+
end
|
186
|
+
|
187
|
+
# Returns the global default log level for new Logger instances
|
188
|
+
def self.default_level
|
189
|
+
@@default_level
|
190
|
+
end
|
191
|
+
|
212
192
|
############################################################################
|
213
193
|
protected
|
214
194
|
|
195
|
+
def initialize(klass, level=nil)
|
196
|
+
@name = klass.is_a?(String) ? klass : klass.name
|
197
|
+
self.level = level || self.class.default_level
|
198
|
+
end
|
199
|
+
|
200
|
+
# Write log data to underlying data storage
|
201
|
+
def log(log_)
|
202
|
+
raise "Logging Appender must implement #log(log)"
|
203
|
+
end
|
204
|
+
|
215
205
|
# Return the level index for fast comparisons
|
216
206
|
attr_reader :level_index
|
217
207
|
|
@@ -252,33 +242,10 @@ module SemanticLogger
|
|
252
242
|
def self.thread_name
|
253
243
|
Java::java.lang::Thread.current_thread.name
|
254
244
|
end
|
255
|
-
|
256
|
-
# Return the Time as a formatted string
|
257
|
-
# JRuby only supports time in ms
|
258
|
-
def self.formatted_time(time)
|
259
|
-
"#{time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (time.usec/1000)}"
|
260
|
-
end
|
261
245
|
else
|
262
246
|
def self.thread_name
|
263
247
|
Thread.current.object_id
|
264
248
|
end
|
265
|
-
|
266
|
-
# Return the Time as a formatted string
|
267
|
-
# Ruby MRI supports micro seconds
|
268
|
-
def self.formatted_time(time)
|
269
|
-
"#{time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%06d" % (time.usec)}"
|
270
|
-
end
|
271
|
-
end
|
272
|
-
|
273
|
-
if RUBY_VERSION.to_f >= 1.9
|
274
|
-
# With Ruby 1.9 calling .to_s on a hash now returns { 'a' => 1 }
|
275
|
-
def self.inspect_payload(payload)
|
276
|
-
payload.to_s
|
277
|
-
end
|
278
|
-
else
|
279
|
-
def self.inspect_payload(payload)
|
280
|
-
payload.inspect
|
281
|
-
end
|
282
249
|
end
|
283
250
|
|
284
251
|
# Internal method to return the log level as an internal index
|
@@ -304,11 +271,5 @@ module SemanticLogger
|
|
304
271
|
index
|
305
272
|
end
|
306
273
|
|
307
|
-
# Appenders don't take a class name, so use this class name if an appender
|
308
|
-
# is logged to directly
|
309
|
-
def name
|
310
|
-
self.class.name
|
311
|
-
end
|
312
|
-
|
313
274
|
end
|
314
275
|
end
|
@@ -47,24 +47,6 @@ module SemanticLogger
|
|
47
47
|
ThreadSafe::Array.new
|
48
48
|
end
|
49
49
|
|
50
|
-
# Initial default Level for all new instances of SemanticLogger::Logger
|
51
|
-
@@default_level = :info
|
52
|
-
@@appender_thread = nil
|
53
|
-
|
54
|
-
# Allow for setting the global default log level
|
55
|
-
# This change only applies to _new_ loggers, existing logger levels
|
56
|
-
# will not be changed in any way
|
57
|
-
def self.default_level=(level)
|
58
|
-
@@default_level = level
|
59
|
-
end
|
60
|
-
|
61
|
-
# Returns the global default log level for new Logger instances
|
62
|
-
def self.default_level
|
63
|
-
@@default_level
|
64
|
-
end
|
65
|
-
|
66
|
-
attr_reader :name
|
67
|
-
|
68
50
|
# Returns a Logger instance
|
69
51
|
#
|
70
52
|
# Return the logger for a specific class, supports class specific log levels
|
@@ -93,15 +75,22 @@ module SemanticLogger
|
|
93
75
|
# able to write to the appenders fast enough. Either reduce the amount of
|
94
76
|
# logging, increase the log level, reduce the number of appenders, or
|
95
77
|
# look into speeding up the appenders themselves
|
96
|
-
def self.
|
78
|
+
def self.queue_size
|
97
79
|
queue.size
|
98
80
|
end
|
99
81
|
|
82
|
+
# DEPRECATED: Please use queue_size instead.
|
83
|
+
def self.cache_count
|
84
|
+
warn "[DEPRECATION] 'SemanticLogger::Logger.cache_count' is deprecated. Please use 'SemanticLogger::Logger.queue_size' instead."
|
85
|
+
queue_size
|
86
|
+
end
|
87
|
+
|
100
88
|
# Flush all queued log entries disk, database, etc.
|
101
89
|
# All queued log messages are written and then each appender is flushed in turn
|
102
90
|
def self.flush
|
103
91
|
return false unless started? && @@appender_thread && @@appender_thread.alive?
|
104
92
|
|
93
|
+
logger.debug "SemanticLogger::Logger Flushing appenders with #{queue_size} log messages on the queue"
|
105
94
|
reply_queue = Queue.new
|
106
95
|
queue << { :command => :flush, :reply_queue => reply_queue }
|
107
96
|
reply_queue.pop
|
@@ -140,6 +129,7 @@ module SemanticLogger
|
|
140
129
|
############################################################################
|
141
130
|
protected
|
142
131
|
|
132
|
+
@@appender_thread = nil
|
143
133
|
@@queue = Queue.new
|
144
134
|
|
145
135
|
# Queue to hold messages that need to be logged to the various appenders
|
@@ -190,7 +180,7 @@ module SemanticLogger
|
|
190
180
|
# Check every few log messages whether this appender thread is falling behind
|
191
181
|
if count > lag_check_interval
|
192
182
|
if (diff = Time.now - message.time) > lag_threshold_s
|
193
|
-
logger.warn "SemanticLogger::Logger Appender thread has fallen behind by #{diff} seconds with #{
|
183
|
+
logger.warn "SemanticLogger::Logger Appender thread has fallen behind by #{diff} seconds with #{queue_size} messages queued up. Consider reducing the log level or changing the appenders"
|
194
184
|
end
|
195
185
|
count = 0
|
196
186
|
end
|
@@ -226,11 +216,5 @@ module SemanticLogger
|
|
226
216
|
end
|
227
217
|
end
|
228
218
|
|
229
|
-
# Formatting does not occur within this thread, it is done by each appender
|
230
|
-
# in the appender thread
|
231
|
-
def default_formatter
|
232
|
-
nil
|
233
|
-
end
|
234
|
-
|
235
219
|
end
|
236
220
|
end
|
Binary file
|
@@ -30,7 +30,7 @@ class AppenderMongoDBTest < Test::Unit::TestCase
|
|
30
30
|
context "format logs into documents" do
|
31
31
|
|
32
32
|
should "handle nil name, message and hash" do
|
33
|
-
@appender.log SemanticLogger::
|
33
|
+
@appender.log SemanticLogger::Base::Log.new(:debug)
|
34
34
|
document = @appender.collection.find_one
|
35
35
|
assert_equal :debug, document['level']
|
36
36
|
assert_equal nil, document['message']
|
@@ -43,7 +43,7 @@ class AppenderMongoDBTest < Test::Unit::TestCase
|
|
43
43
|
end
|
44
44
|
|
45
45
|
should "handle nil message and payload" do
|
46
|
-
log = SemanticLogger::
|
46
|
+
log = SemanticLogger::Base::Log.new(:debug)
|
47
47
|
log.payload = @hash
|
48
48
|
@appender.log(log)
|
49
49
|
|
@@ -59,7 +59,7 @@ class AppenderMongoDBTest < Test::Unit::TestCase
|
|
59
59
|
end
|
60
60
|
|
61
61
|
should "handle message and payload" do
|
62
|
-
log = SemanticLogger::
|
62
|
+
log = SemanticLogger::Base::Log.new(:debug)
|
63
63
|
log.message = 'hello world'
|
64
64
|
log.payload = @hash
|
65
65
|
log.thread_name = 'thread'
|
@@ -78,7 +78,7 @@ class AppenderMongoDBTest < Test::Unit::TestCase
|
|
78
78
|
end
|
79
79
|
|
80
80
|
should "handle message without payload" do
|
81
|
-
log = SemanticLogger::
|
81
|
+
log = SemanticLogger::Base::Log.new(:debug)
|
82
82
|
log.message = 'hello world'
|
83
83
|
log.thread_name = 'thread'
|
84
84
|
log.time = @time
|
@@ -100,7 +100,7 @@ class AppenderMongoDBTest < Test::Unit::TestCase
|
|
100
100
|
# Ensure that any log level can be logged
|
101
101
|
SemanticLogger::LEVELS.each do |level|
|
102
102
|
should "log #{level} information" do
|
103
|
-
@appender.log SemanticLogger::
|
103
|
+
@appender.log SemanticLogger::Base::Log.new(level, 'thread', 'my_class', 'hello world -- Calculations', @hash, @time)
|
104
104
|
document = @appender.collection.find_one
|
105
105
|
assert_equal level, document['level']
|
106
106
|
assert_equal 'hello world -- Calculations', document['message']
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: semantic_logger
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.9.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-10-
|
12
|
+
date: 2012-10-24 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: sync_attr
|
@@ -72,6 +72,7 @@ files:
|
|
72
72
|
- Gemfile
|
73
73
|
- Gemfile.lock
|
74
74
|
- init.txt
|
75
|
+
- lib/semantic_logger/appender/base.rb
|
75
76
|
- lib/semantic_logger/appender/file.rb
|
76
77
|
- lib/semantic_logger/appender/mongodb.rb
|
77
78
|
- lib/semantic_logger/appender/wrapper.rb
|
@@ -92,6 +93,7 @@ files:
|
|
92
93
|
- semantic_logger-0.7.0.gem
|
93
94
|
- semantic_logger-0.7.1.gem
|
94
95
|
- semantic_logger-0.8.0.gem
|
96
|
+
- semantic_logger-0.8.1.gem
|
95
97
|
- test/appender_file_test.rb
|
96
98
|
- test/appender_mongodb_test.rb
|
97
99
|
- test/appender_wrapper_test.rb
|
@@ -111,7 +113,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
111
113
|
version: '0'
|
112
114
|
segments:
|
113
115
|
- 0
|
114
|
-
hash:
|
116
|
+
hash: 3745819161206359497
|
115
117
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
116
118
|
none: false
|
117
119
|
requirements:
|