semantic_logger 0.2.0 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
data/FUTURE.rb
CHANGED
@@ -1,9 +1,4 @@
|
|
1
1
|
|
2
|
-
# Return the logger for a specific class, supports class specific log levels
|
3
|
-
# Clarity::Logger.logger(MyClass)
|
4
|
-
# # OR
|
5
|
-
# Clarity::Logger.logger('MyClass')
|
6
|
-
#
|
7
2
|
# # Switch to slf4j as the underlying implementation
|
8
3
|
# Clarity::Logger.impl = slf4j
|
9
4
|
#
|
@@ -14,13 +9,6 @@
|
|
14
9
|
#
|
15
10
|
#
|
16
11
|
#
|
17
|
-
# # Thread specific context information to be logged with every log entry
|
18
|
-
# #
|
19
|
-
# # Add metadata information within a block to all log calls on This Thread
|
20
|
-
# logger.with_metadata(:tracking_number=>12345) do
|
21
|
-
# # Any log entries within this block will have this metadata added to it
|
22
|
-
# logger.debug('Hello World', :result => 'blah')
|
23
|
-
# end
|
24
12
|
#
|
25
13
|
# # If a block cannot be used to set the scope of context
|
26
14
|
# # Set global metadata for every log entry on this machine
|
@@ -41,6 +41,8 @@ module SemanticLogger
|
|
41
41
|
def default_formatter
|
42
42
|
Proc.new do |log|
|
43
43
|
message = log.message.to_s
|
44
|
+
tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
|
45
|
+
|
44
46
|
if log.payload
|
45
47
|
if log.payload.is_a?(Exception)
|
46
48
|
exception = log.payload
|
@@ -50,8 +52,9 @@ module SemanticLogger
|
|
50
52
|
end
|
51
53
|
end
|
52
54
|
|
53
|
-
str = "#{log.time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (log.time.usec/1000)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{log.name} -- #{message}
|
55
|
+
str = "#{log.time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (log.time.usec/1000)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{log.name} -- #{message}"
|
54
56
|
str << " (#{'%.1f' % log.duration}ms)" if log.duration
|
57
|
+
str << "\n"
|
55
58
|
str
|
56
59
|
end
|
57
60
|
end
|
@@ -12,8 +12,8 @@ module SemanticLogger
|
|
12
12
|
# level : 'trace|debug|warn|info|error',
|
13
13
|
# message : "blah blah",
|
14
14
|
# duration : ms, # Set by Logger#benchmark
|
15
|
-
#
|
16
|
-
#
|
15
|
+
# tags : "Some tracking id" | ["id1", "id2"]
|
16
|
+
# payload : {
|
17
17
|
# Optional. Any user supplied data, including any thread specific context variables
|
18
18
|
# values supplied on a per log entry will override any thread context values
|
19
19
|
# }
|
@@ -53,7 +53,13 @@ module SemanticLogger
|
|
53
53
|
|
54
54
|
@@default_level = :info
|
55
55
|
|
56
|
-
#
|
56
|
+
# Returns a Logger instance
|
57
|
+
#
|
58
|
+
# Return the logger for a specific class, supports class specific log levels
|
59
|
+
# logger = SemanticLogger::Logger.new(self)
|
60
|
+
# OR
|
61
|
+
# logger = SemanticLogger::Logger.new('MyClass')
|
62
|
+
#
|
57
63
|
# Parameters:
|
58
64
|
# application: A class, module or a string with the application/class name
|
59
65
|
# to be used in the logger
|
@@ -94,10 +100,14 @@ module SemanticLogger
|
|
94
100
|
if result.is_a?(String)
|
95
101
|
message = message.nil? ? result : "\#{message} -- \#{result.to_s}"
|
96
102
|
else
|
97
|
-
payload = payload.nil? ?
|
103
|
+
payload = payload.nil? ? result : payload.merge(result)
|
98
104
|
end
|
99
105
|
end
|
100
|
-
|
106
|
+
# Add scoped payload
|
107
|
+
if self.payload
|
108
|
+
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
109
|
+
end
|
110
|
+
self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, payload, Time.now, nil, tags)
|
101
111
|
true
|
102
112
|
else
|
103
113
|
false
|
@@ -117,10 +127,15 @@ module SemanticLogger
|
|
117
127
|
start = Time.now
|
118
128
|
begin
|
119
129
|
result = yield
|
120
|
-
|
130
|
+
# Add scoped payload
|
131
|
+
if self.payload
|
132
|
+
payload = payload.nil? ? self.payload : self.payload.merge(payload)
|
133
|
+
end
|
134
|
+
self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, payload, start, Time.now - start, tags)
|
121
135
|
result
|
122
136
|
rescue Exception => exc
|
123
|
-
|
137
|
+
# TODO Need to be able to have both an exception and a Payload
|
138
|
+
self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, exc, start, Time.now - start, tags)
|
124
139
|
raise exc
|
125
140
|
end
|
126
141
|
else
|
@@ -130,6 +145,55 @@ module SemanticLogger
|
|
130
145
|
EOT
|
131
146
|
end
|
132
147
|
|
148
|
+
# Add the supplied tags to the list of tags to log for this thread whilst
|
149
|
+
# the supplied block is active
|
150
|
+
# Returns nil if no tags are currently set
|
151
|
+
def with_tags(*tags)
|
152
|
+
current_tags = self.tags
|
153
|
+
# Check for nil tags
|
154
|
+
if tags
|
155
|
+
Thread.current[:semantic_logger_tags] = current_tags ? current_tags + tags : tags
|
156
|
+
end
|
157
|
+
yield
|
158
|
+
ensure
|
159
|
+
Thread.current[:semantic_logger_tags] = current_tags
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns [Array] of [String] tags currently active for this thread
|
163
|
+
# Returns nil if no tags are set
|
164
|
+
def tags
|
165
|
+
Thread.current[:semantic_logger_tags]
|
166
|
+
end
|
167
|
+
|
168
|
+
# Thread specific context information to be logged with every log entry
|
169
|
+
#
|
170
|
+
# Add a payload to all log calls on This Thread within the supplied block
|
171
|
+
#
|
172
|
+
# logger.with_payload(:tracking_number=>12345) do
|
173
|
+
# logger.debug('Hello World')
|
174
|
+
# end
|
175
|
+
#
|
176
|
+
# If a log call already includes a pyload, this payload will be merged with
|
177
|
+
# the supplied payload, with the supplied payload taking precedence
|
178
|
+
#
|
179
|
+
# logger.with_payload(:tracking_number=>12345) do
|
180
|
+
# logger.debug('Hello World', :result => 'blah')
|
181
|
+
# end
|
182
|
+
def with_payload(payload)
|
183
|
+
current_payload = self.payload
|
184
|
+
Thread.current[:semantic_logger_payload] = current_payload ? current_payload.merge(payload) : payload
|
185
|
+
yield
|
186
|
+
ensure
|
187
|
+
Thread.current[:semantic_logger_payload] = current_payload
|
188
|
+
end
|
189
|
+
|
190
|
+
# Returns [Hash] payload to be added to every log entry in the current scope
|
191
|
+
# on this thread.
|
192
|
+
# Returns nil if no payload is currently set
|
193
|
+
def payload
|
194
|
+
Thread.current[:semantic_logger_payload]
|
195
|
+
end
|
196
|
+
|
133
197
|
# Semantic Logging does not support :unknown level since these
|
134
198
|
# are not understood by the majority of the logging providers
|
135
199
|
# Map it to :error
|
@@ -187,7 +251,7 @@ module SemanticLogger
|
|
187
251
|
Queue.new
|
188
252
|
end
|
189
253
|
|
190
|
-
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration)
|
254
|
+
Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags)
|
191
255
|
|
192
256
|
# For JRuby include the Thread name rather than its id
|
193
257
|
if defined? Java
|
@@ -23,15 +23,31 @@ module SemanticLogger #:nodoc:
|
|
23
23
|
#
|
24
24
|
# Loaded after Rails logging is initialized since SemanticLogger will continue
|
25
25
|
# to forward logging to the Rails Logger
|
26
|
-
initializer :initialize_semantic_logger, :
|
26
|
+
initializer :initialize_semantic_logger, :before => :initialize_logger do
|
27
27
|
config = Rails.application.config
|
28
28
|
|
29
|
-
|
29
|
+
logger = Rails.logger || config.logger || begin
|
30
|
+
path = config.paths.log.to_a.first
|
31
|
+
logger = ActiveSupport::BufferedLogger.new(path)
|
32
|
+
logger.level = ActiveSupport::BufferedLogger.const_get(config.log_level.to_s.upcase)
|
33
|
+
logger.auto_flushing = false if Rails.env.production?
|
34
|
+
logger
|
35
|
+
rescue StandardError => e
|
36
|
+
logger = ActiveSupport::BufferedLogger.new(STDERR)
|
37
|
+
logger.level = ActiveSupport::BufferedLogger::WARN
|
38
|
+
logger.warn(
|
39
|
+
"Rails Error: Unable to access log file. Please ensure that #{path} exists and is chmod 0666. " +
|
40
|
+
"The log level has been raised to WARN and the output directed to STDERR until the problem is fixed."
|
41
|
+
)
|
42
|
+
logger
|
43
|
+
end
|
44
|
+
|
45
|
+
# First set the internal logger to the default file one used by Rails in case something goes wrong
|
30
46
|
# with an appender
|
31
|
-
SemanticLogger::Logger.logger =
|
47
|
+
SemanticLogger::Logger.logger = logger
|
32
48
|
|
33
49
|
# Add the Rails Logger to the list of appenders
|
34
|
-
SemanticLogger::Logger.appenders << SemanticLogger::Appender::Logger.new(
|
50
|
+
SemanticLogger::Logger.appenders << SemanticLogger::Appender::Logger.new(logger)
|
35
51
|
|
36
52
|
# Set the default log level based on the Rails config
|
37
53
|
SemanticLogger::Logger.default_level = Rails.configuration.log_level
|
@@ -41,6 +57,10 @@ module SemanticLogger #:nodoc:
|
|
41
57
|
if defined?(ActiveRecord)
|
42
58
|
ActiveRecord::Base.logger = SemanticLogger::Logger.new(ActiveRecord)
|
43
59
|
end
|
60
|
+
if defined?(ActionController)
|
61
|
+
ActionController::Base.logger = SemanticLogger::Logger.new(ActionController)
|
62
|
+
end
|
63
|
+
SemanticLogger::Logger.logger.info "SemanticLogger initialized"
|
44
64
|
end
|
45
65
|
|
46
66
|
end
|
data/test/logger_test.rb
CHANGED
@@ -9,7 +9,6 @@ require 'semantic_logger'
|
|
9
9
|
require 'test/mock_logger'
|
10
10
|
|
11
11
|
# Unit Test for SemanticLogger::Logger
|
12
|
-
#
|
13
12
|
class LoggerTest < Test::Unit::TestCase
|
14
13
|
context SemanticLogger::Logger do
|
15
14
|
|
@@ -39,6 +38,36 @@ class LoggerTest < Test::Unit::TestCase
|
|
39
38
|
end
|
40
39
|
end
|
41
40
|
|
41
|
+
context "with_tags logging" do
|
42
|
+
should "add tags to log entries" do
|
43
|
+
@logger.with_tags('12345', 'DJHSFK') do
|
44
|
+
@logger.info('Hello world')
|
45
|
+
@logger.flush
|
46
|
+
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[12345\] \[DJHSFK\] LoggerTest -- Hello world\n/, @mock_logger.message
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
should "add embedded tags to log entries" do
|
51
|
+
@logger.with_tags('First Level', 'tags') do
|
52
|
+
@logger.with_tags('Second Level') do
|
53
|
+
@logger.info('Hello world')
|
54
|
+
@logger.flush
|
55
|
+
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[First Level\] \[tags\] \[Second Level\] LoggerTest -- Hello world\n/, @mock_logger.message
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
should "add payload to log entries" do
|
61
|
+
@logger.with_payload(:tracking_number => '123456') do
|
62
|
+
@logger.with_payload(:more => 'data', :even => 2) do
|
63
|
+
@logger.info('Hello world')
|
64
|
+
@logger.flush
|
65
|
+
assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- Hello world -- \{:more=>\"data\", :even=>2, :tracking_number=>\"123456\"\}\n/, @mock_logger.message
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
end
|
42
71
|
end
|
43
72
|
|
44
73
|
end
|
metadata
CHANGED
@@ -4,9 +4,9 @@ version: !ruby/object:Gem::Version
|
|
4
4
|
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 0
|
7
|
-
-
|
7
|
+
- 3
|
8
8
|
- 0
|
9
|
-
version: 0.
|
9
|
+
version: 0.3.0
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Reid Morrison
|
@@ -14,7 +14,7 @@ autorequire:
|
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
16
|
|
17
|
-
date: 2012-08-
|
17
|
+
date: 2012-08-21 00:00:00 -04:00
|
18
18
|
default_executable:
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|