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}\n"
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
- # tracking_number : "Some tracking id"
16
- # metadata : {
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
- # Create a Logger instance
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? ? sresult : payload.merge(result)
103
+ payload = payload.nil? ? result : payload.merge(result)
98
104
  end
99
105
  end
100
- self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, payload, Time.now)
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
- self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, payload, start, Time.now - start)
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
- self.class.queue << Log.new(:#{level}, self.class.thread_name, name, message, exc, start, Time.now - start)
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, :after => :initialize_logger do
26
+ initializer :initialize_semantic_logger, :before => :initialize_logger do
27
27
  config = Rails.application.config
28
28
 
29
- # First set the internal logger to the one used by Rails in case something goes wrong
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 = Rails.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(Rails.logger)
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
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger #:nodoc
2
- VERSION = "0.2.0"
2
+ VERSION = "0.3.0"
3
3
  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
- - 2
7
+ - 3
8
8
  - 0
9
- version: 0.2.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-20 00:00:00 -04:00
17
+ date: 2012-08-21 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency