semantic_logger 0.11.4 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README.md CHANGED
@@ -204,12 +204,12 @@ logger.info?
204
204
  The following logging methods are available
205
205
 
206
206
  ```ruby
207
- trace(message, payload=nil, &block)
208
- debug(message, payload=nil, &block)
209
- info(message, payload=nil, &block)
210
- warn(message, payload=nil, &block)
211
- error(message, payload=nil, &block)
212
- fatal(message, payload=nil, &block)
207
+ trace(message, payload=nil, exception=nil, &block)
208
+ debug(message, payload=nil, exception=nil, &block)
209
+ info(message, payload=nil, exception=nil, &block)
210
+ warn(message, payload=nil, exception=nil, &block)
211
+ error(message, payload=nil, exception=nil, &block)
212
+ fatal(message, payload=nil, exception=nil, &block)
213
213
  ```
214
214
 
215
215
  Parameters
@@ -217,6 +217,7 @@ Parameters
217
217
  - message: The text message to log.
218
218
  Mandatory only if no block is supplied
219
219
  - payload: Optional, either a Ruby Exception object or a Hash
220
+ - exception: Optional, Ruby Exception object. Allows both an exception and a payload to be logged
220
221
  - block: The optional block is executed only if the corresponding log level
221
222
  is active. Can be used to prevent unnecessary calculations of debug data in
222
223
  production.
@@ -311,7 +312,10 @@ Parameters
311
312
  Default: 0.0
312
313
 
313
314
  :payload
314
- Optional, either a Ruby Exception object or a Hash
315
+ Optional, Hash payload
316
+
317
+ :exception
318
+ Optional, Ruby Exception object to log along with the duration of the supplied block
315
319
  ```
316
320
 
317
321
  #### Logging levels
@@ -578,21 +582,15 @@ Example: Replace the Rails log formatter, in the environment configuration file:
578
582
  config.after_initialize do
579
583
  # Since the Rails logger is already initialized, replace its default formatter
580
584
  config.semantic_logger.appenders.first.formatter = Proc.new do |log|
581
- message = log.message.to_s
582
585
  tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
583
586
 
584
- if log.payload
585
- if log.payload.is_a?(Exception)
586
- exception = log.payload
587
- message << " -- " << "#{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
588
- else
589
- message << " -- " << log.payload.inspect
590
- end
591
- end
592
-
593
- str = "#{log.time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%06d" % log.time.usec} #{"%-05s" % log.level.to_s.upcase} [#{$$}:#{log.thread_name}] #{tags}#{log.name} -- #{message}"
594
- str << " (#{'%.1f' % log.duration}ms)" if log.duration
595
- str
587
+ message = log.message.to_s
588
+ message << " -- " << log.payload.inspect if log.payload
589
+ message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
590
+
591
+ duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
592
+
593
+ "#{SemanticLogger::Appender::Base.formatted_time(log.time)} #{log.level.to_s[0..0].upcase} [#{$$}:#{log.thread_name}] #{tags}#{duration_str}#{log.name} -- #{message}"
596
594
  end
597
595
  end
598
596
  ```
@@ -614,24 +612,18 @@ Example: Replace the MongoDB formatter, in the environment configuration file:
614
612
  :thread_name => log.thread_name,
615
613
  :name => log.name,
616
614
  :level => log.level,
615
+ :level_index => log.level_index,
617
616
  }
618
617
  document[:application] = 'MyApplication'
619
618
  document[:message] = SemanticLogger::Appender::MongoDB.strip_colorizing(log.message) if log.message
620
619
  document[:duration] = log.duration if log.duration
621
620
  document[:tags] = log.tags if log.tags && (log.tags.size > 0)
622
-
623
- if log.payload
624
- if log.payload.is_a?(Exception)
625
- exception = log.payload
626
- document[:payload] = {
627
- :exception => exception.class.name,
628
- :message => exception.message,
629
- :backtrace => exception.backtrace
630
- }
631
- else
632
- document[:payload] = log.payload
633
- end
634
- end
621
+ document[:payload] = log.payload if log.payload
622
+ document[:exception] = {
623
+ :name => log.exception.class.name,
624
+ :message => log.exception.message,
625
+ :stack_trace => log.exception.backtrace
626
+ } if log.exception
635
627
  document
636
628
  end
637
629
  config.semantic_logger.appenders << mongodb_appender
@@ -17,17 +17,11 @@ module SemanticLogger
17
17
  # 2011-07-19 14:36:15.660 D [1149:ScriptThreadProcess] Rails -- Hello World
18
18
  def default_formatter
19
19
  Proc.new do |log|
20
- message = log.message.to_s
21
20
  tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
22
21
 
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
22
+ message = log.message.to_s
23
+ message << " -- " << log.payload.inspect if log.payload
24
+ message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
31
25
 
32
26
  duration_str = log.duration ? "(#{'%.1f' % log.duration}ms) " : ''
33
27
 
@@ -67,17 +61,6 @@ module SemanticLogger
67
61
  end
68
62
  end
69
63
 
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
64
  end
82
65
  end
83
66
  end
@@ -144,19 +144,12 @@ module SemanticLogger
144
144
  document[:message] = self.class.strip_colorizing(log.message) if log.message
145
145
  document[:duration] = log.duration if log.duration
146
146
  document[:tags] = log.tags if log.tags && (log.tags.size > 0)
147
-
148
- if log.payload
149
- if log.payload.is_a?(Exception)
150
- exception = log.payload
151
- document[:exception] = {
152
- :name => exception.class.name,
153
- :message => exception.message,
154
- :stack_trace => exception.backtrace
155
- }
156
- else
157
- document[:payload] = log.payload
158
- end
159
- end
147
+ document[:payload] = log.payload if log.payload
148
+ document[:exception] = {
149
+ :name => log.exception.class.name,
150
+ :message => log.exception.message,
151
+ :stack_trace => log.exception.backtrace
152
+ } if log.exception
160
153
  document
161
154
  end
162
155
  end
@@ -31,7 +31,23 @@ module SemanticLogger
31
31
  # Implement the log level query
32
32
  # logger.debug?
33
33
  #
34
- # Example:
34
+ # Parameters:
35
+ # message
36
+ # [String] text message to be logged
37
+ # Should always be supplied unless the result of the supplied block returns
38
+ # a string in which case it will become the logged message
39
+ # Default: nil
40
+ #
41
+ # payload
42
+ # [Hash|Exception] Optional hash payload or an exception to be logged
43
+ # Default: nil
44
+ #
45
+ # exception
46
+ # [Exception] Optional exception to be logged
47
+ # Allows both an exception and a payload to be logged
48
+ # Default: nil
49
+ #
50
+ # Examples:
35
51
  # require 'semantic_logger'
36
52
  #
37
53
  # # Enable trace level logging
@@ -54,20 +70,28 @@ module SemanticLogger
54
70
  #
55
71
  SemanticLogger::LEVELS.each_with_index do |level, index|
56
72
  class_eval <<-EOT, __FILE__, __LINE__
57
- def #{level}(message = nil, payload = nil)
73
+ def #{level}(message=nil, payload=nil, exception=nil)
58
74
  if @level_index <= #{index}
75
+ if exception.nil? && payload && payload.is_a?(Exception)
76
+ exception = payload
77
+ payload = nil
78
+ end
79
+
59
80
  if block_given? && (result = yield)
60
81
  if result.is_a?(String)
61
- message = message.nil? ? result : "\#{message} -- \#{result.to_s}"
82
+ message = message.nil? ? result : "\#{message} -- \#{result}"
83
+ elsif payload && payload.respond_to?(:merge)
84
+ payload.merge(result)
62
85
  else
63
- payload = payload.nil? ? result : payload.merge(result)
86
+ payload = result
64
87
  end
65
88
  end
89
+
66
90
  # Add scoped payload
67
91
  if self.payload
68
92
  payload = payload.nil? ? self.payload : self.payload.merge(payload)
69
93
  end
70
- log Log.new(:#{level}, self.class.thread_name, name, message, payload, Time.now, nil, tags, #{index})
94
+ log Log.new(:#{level}, self.class.thread_name, name, message, payload, Time.now, nil, tags, #{index}, exception)
71
95
  true
72
96
  else
73
97
  false
@@ -80,13 +104,17 @@ module SemanticLogger
80
104
 
81
105
  def benchmark_#{level}(message, params = nil)
82
106
  raise "Mandatory block missing" unless block_given?
83
- log_exception = params.nil? ? :full : params[:log_exception]
84
- min_duration = params.nil? ? 0.0 : (params[:min_duration] || 0.0)
85
- payload = params.nil? ? nil : params[:payload]
86
107
  if @level_index <= #{index}
87
- start = Time.now
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[:exception]
112
+ start = Time.now
88
113
  begin
89
- result = yield
114
+ yield
115
+ rescue Exception => exc
116
+ exception = exc
117
+ ensure
90
118
  end_time = Time.now
91
119
  duration = 1000.0 * (end_time - start)
92
120
 
@@ -96,16 +124,18 @@ module SemanticLogger
96
124
  if self.payload
97
125
  payload = payload.nil? ? self.payload : self.payload.merge(payload)
98
126
  end
99
- log Log.new(:#{level}, self.class.thread_name, name, message, payload, end_time, duration, tags, #{index})
100
- end
101
- result
102
- rescue Exception => exc
103
- if log_exception == :full
104
- log Log.new(:#{level}, self.class.thread_name, name, message, exc, Time.now, 1000.0 * (Time.now - start), tags, #{index})
105
- elsif log_exception == :partial
106
- log Log.new(:#{level}, self.class.thread_name, name, "\#{message} -- \#{exception.class}: \#{exception.message}", payload, end_time, 1000.0 * (end_time - start), tags, #{index})
127
+ if exception
128
+ case log_exception
129
+ when :full
130
+ log Log.new(:#{level}, self.class.thread_name, name, message, payload, end_time, duration, tags, #{index}, exception)
131
+ when :partial
132
+ log Log.new(:#{level}, self.class.thread_name, name, "\#{message} -- Exception: \#{exception.class}: \#{exception.message}", payload, end_time, duration, tags, #{index}, nil)
133
+ end
134
+ raise exception
135
+ else
136
+ log Log.new(:#{level}, self.class.thread_name, name, message, payload, end_time, duration, tags, #{index}, nil)
137
+ end
107
138
  end
108
- raise exc
109
139
  end
110
140
  else
111
141
  yield
@@ -234,7 +264,7 @@ module SemanticLogger
234
264
  #
235
265
  # level_index
236
266
  # Internal index of the log level
237
- Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index)
267
+ Log = Struct.new(:level, :thread_name, :name, :message, :payload, :time, :duration, :tags, :level_index, :exception)
238
268
 
239
269
  # For JRuby include the Thread name rather than its id
240
270
  if defined? Java
@@ -1,3 +1,3 @@
1
1
  module SemanticLogger #:nodoc
2
- VERSION = "0.11.4"
2
+ VERSION = "1.0.0"
3
3
  end
@@ -36,6 +36,11 @@ class AppenderFileTest < Test::Unit::TestCase
36
36
  @appender.debug 'hello world', @hash
37
37
  assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ D \[\d+:#{@thread_name}\] SemanticLogger::Appender::File -- hello world -- #{@hash_str}\n/, @io.string
38
38
  end
39
+
40
+ should "handle message, payload, and exception" do
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
43
+ end
39
44
  end
40
45
 
41
46
  context "for each log level" do
@@ -51,21 +56,15 @@ class AppenderFileTest < Test::Unit::TestCase
51
56
  context "custom formatter" do
52
57
  setup do
53
58
  @appender = SemanticLogger::Appender::File.new(@io) do |log|
54
- message = log.message.to_s
55
59
  tags = log.tags.collect { |tag| "[#{tag}]" }.join(" ") + " " if log.tags && (log.tags.size > 0)
56
60
 
57
- if log.payload
58
- if log.payload.is_a?(Exception)
59
- exception = log.payload
60
- message << " -- " << "#{exception.class}: #{exception.message}\n#{(exception.backtrace || []).join("\n")}"
61
- else
62
- message << " -- " << log.payload.inspect
63
- end
64
- end
61
+ message = log.message.to_s
62
+ message << " -- " << log.payload.inspect if log.payload
63
+ message << " -- " << "#{log.exception.class}: #{log.exception.message}\n#{(log.exception.backtrace || []).join("\n")}" if log.exception
64
+
65
+ duration_str = log.duration ? " (#{'%.1f' % log.duration}ms)" : ''
65
66
 
66
- str = "#{log.time.strftime("%Y-%m-%d %H:%M:%S")}.#{"%03d" % (log.time.usec/1000)} #{log.level.to_s.upcase} [#{$$}:#{log.thread_name}] #{tags}#{log.name} -- #{message}"
67
- str << " (#{'%.1f' % log.duration}ms)" if log.duration
68
- str
67
+ "#{SemanticLogger::Appender::Base.formatted_time(log.time)} #{log.level.to_s.upcase} [#{$$}:#{log.thread_name}] #{tags}#{log.name} -- #{message}#{duration_str}"
69
68
  end
70
69
  end
71
70
 
data/test/logger_test.rb CHANGED
@@ -10,104 +10,130 @@ require 'semantic_logger'
10
10
  # Unit Test for SemanticLogger::Logger
11
11
  class LoggerTest < Test::Unit::TestCase
12
12
  context SemanticLogger::Logger do
13
+ setup do
14
+ # Use a mock logger that just keeps the last logged entry in an instance
15
+ # variable
16
+ @mock_logger = MockLogger.new
17
+ @appender = SemanticLogger::Appender::Wrapper.new(@mock_logger)
18
+ SemanticLogger::Logger.appenders << @appender
19
+
20
+ # 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("}", "\\}")
24
+ end
13
25
 
14
- context "log to Ruby and Rails logger" do
15
- setup do
16
- # Use a mock logger that just keeps the last logged entry in an instance variable
17
- @mock_logger = MockLogger.new
18
- @appender = SemanticLogger::Appender::Wrapper.new(@mock_logger)
19
- SemanticLogger::Logger.appenders << @appender
20
-
21
- # Use this test's class name as the application name in the log output
22
- @logger = SemanticLogger::Logger.new('LoggerTest', :trace)
23
-
24
- @hash = { :session_id => 'HSSKLEU@JDK767', :tracking_number => 12345 }
25
- @hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
26
- end
26
+ teardown do
27
+ SemanticLogger::Logger.appenders.delete(@appender)
28
+ end
27
29
 
28
- teardown do
29
- SemanticLogger::Logger.appenders.delete(@appender)
30
+ # Ensure that any log level can be logged
31
+ SemanticLogger::LEVELS.each do |level|
32
+ should "log #{level} info" do
33
+ @logger.send(level, 'hello world', @hash) { "Calculations" }
34
+ SemanticLogger::Logger.flush
35
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- hello world -- Calculations -- #{@hash_str}/, @mock_logger.message
30
36
  end
37
+ end
31
38
 
32
- # Ensure that any log level can be logged
33
- SemanticLogger::LEVELS.each do |level|
34
- should "log #{level} info" do
35
- @logger.send(level, 'hello world', @hash) { "Calculations" }
39
+ context "with_tags logging" do
40
+ should "add tags to log entries" do
41
+ @logger.with_tags('12345', 'DJHSFK') do
42
+ @logger.info('Hello world')
36
43
  SemanticLogger::Logger.flush
37
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- hello world -- Calculations -- #{@hash_str}/, @mock_logger.message
44
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[12345\] \[DJHSFK\] LoggerTest -- Hello world/, @mock_logger.message
38
45
  end
39
46
  end
40
47
 
41
- context "with_tags logging" do
42
- should "add tags to log entries" do
43
- @logger.with_tags('12345', 'DJHSFK') do
48
+ should "add embedded tags to log entries" do
49
+ @logger.with_tags('First Level', 'tags') do
50
+ @logger.with_tags('Second Level') do
44
51
  @logger.info('Hello world')
45
52
  SemanticLogger::Logger.flush
46
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[12345\] \[DJHSFK\] LoggerTest -- Hello world/, @mock_logger.message
53
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[First Level\] \[tags\] \[Second Level\] LoggerTest -- Hello world/, @mock_logger.message
47
54
  end
48
55
  end
56
+ end
49
57
 
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
- SemanticLogger::Logger.flush
55
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \[First Level\] \[tags\] \[Second Level\] LoggerTest -- Hello world/, @mock_logger.message
56
- end
58
+ should "add payload to log entries" do
59
+ hash = {:tracking_number=>"123456", :even=>2, :more=>"data"}
60
+ hash_str = hash.inspect.sub("{", "\\{").sub("}", "\\}")
61
+ @logger.with_payload(:tracking_number => '123456') do
62
+ @logger.with_payload(:even => 2, :more => 'data') do
63
+ @logger.info('Hello world')
64
+ SemanticLogger::Logger.flush
65
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- Hello world -- #{hash_str}/, @mock_logger.message
57
66
  end
58
67
  end
68
+ end
59
69
 
60
- should "add payload to log entries" do
61
- hash = {:tracking_number=>"123456", :even=>2, :more=>"data"}
62
- hash_str = hash.inspect.sub("{", "\\{").sub("}", "\\}")
63
- @logger.with_payload(:tracking_number => '123456') do
64
- @logger.with_payload(:even => 2, :more => 'data') do
65
- @logger.info('Hello world')
66
- SemanticLogger::Logger.flush
67
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] LoggerTest -- Hello world -- #{hash_str}/, @mock_logger.message
70
+ context "Ruby Logger" do
71
+ # Ensure that any log level can be logged
72
+ Logger::Severity.constants.each do |level|
73
+ should "log Ruby logger #{level} info" do
74
+ @logger.level = Logger::Severity.const_get(level)
75
+ if level.to_s == 'UNKNOWN'
76
+ assert_equal Logger::Severity.const_get('ERROR')+1, @logger.send(:level_index)
77
+ else
78
+ assert_equal Logger::Severity.const_get(level)+1, @logger.send(:level_index)
68
79
  end
69
80
  end
70
81
  end
82
+ end
71
83
 
72
- context "Ruby Logger" do
73
- # Ensure that any log level can be logged
74
- Logger::Severity.constants.each do |level|
75
- should "log Ruby logger #{level} info" do
76
- @logger.level = Logger::Severity.const_get(level)
77
- if level.to_s == 'UNKNOWN'
78
- assert_equal Logger::Severity.const_get('ERROR')+1, @logger.send(:level_index)
79
- else
80
- assert_equal Logger::Severity.const_get(level)+1, @logger.send(:level_index)
81
- end
82
- end
84
+ context "benchmark" do
85
+ # Ensure that any log level can be benchmarked and logged
86
+ SemanticLogger::LEVELS.each do |level|
87
+ should "log #{level} info" do
88
+ assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world') { "result" } # Measure duration of the supplied block
89
+ SemanticLogger::Logger.flush
90
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world/, @mock_logger.message
83
91
  end
84
- end
85
92
 
86
- context "benchmark" do
87
- # Ensure that any log level can be benchmarked and logged
88
- SemanticLogger::LEVELS.each do |level|
89
- should "log #{level} info" do
90
- assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world') { "result" }
91
- SemanticLogger::Logger.flush
92
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world/, @mock_logger.message
93
- end
93
+ should "log #{level} info with payload" do
94
+ assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', :payload => @hash) { "result" } # Measure duration of the supplied block
95
+ SemanticLogger::Logger.flush
96
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- #{@hash_str}/, @mock_logger.message
97
+ end
94
98
 
95
- should "log #{level} info with payload" do
96
- assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', :payload => @hash) { "result" }
97
- SemanticLogger::Logger.flush
98
- assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- #{@hash_str}/, @mock_logger.message
99
- end
99
+ should "not log #{level} info when block is faster than :min_duration" do
100
+ assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', :min_duration => 0.5) { "result" } # Measure duration of the supplied block
101
+ SemanticLogger::Logger.flush
102
+ assert_nil @mock_logger.message
103
+ end
104
+
105
+ should "log #{level} info when block duration exceeds :min_duration" do
106
+ assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', :min_duration => 0.2, :payload => @hash) { sleep 0.5; "result" } # Measure duration of the supplied block
107
+ SemanticLogger::Logger.flush
108
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- #{@hash_str}/, @mock_logger.message
109
+ end
100
110
 
101
- should "not log #{level} info when block is faster than :min_duration" do
102
- assert_equal "result", @logger.send("benchmark_#{level}".to_sym, 'hello world', :min_duration => 0.5) { "result" }
103
- SemanticLogger::Logger.flush
104
- assert_nil @mock_logger.message
111
+ should "log #{level} info with an exception" do
112
+ assert_raise RuntimeError do
113
+ @logger.send("benchmark_#{level}", 'hello world', :payload => @hash) { raise RuntimeError.new("Test") } # Measure duration of the supplied block
105
114
  end
115
+ SemanticLogger::Logger.flush
116
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- Exception: RuntimeError: Test -- #{@hash_str}/, @mock_logger.message
106
117
  end
107
118
  end
108
119
 
120
+ should "log when the block performs a return" do
121
+ assert_equal "Good", function_with_return(@logger)
122
+ SemanticLogger::Logger.flush
123
+ assert_match /\d+-\d+-\d+ \d+:\d+:\d+.\d+ \w \[\d+:.+\] \(\d+\.\dms\) LoggerTest -- hello world -- #{@hash_str}/, @mock_logger.message
124
+ end
109
125
  end
126
+
110
127
  end
128
+ end
111
129
 
130
+ # Make sure that benchmark still logs when a block uses return to return from
131
+ # a function
132
+ def function_with_return(logger)
133
+ logger.benchmark_info('hello world', :payload => @hash) do
134
+ return "Good"
135
+ end
136
+ "Bad"
112
137
  end
138
+
113
139
  end
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.11.4
4
+ version: 1.0.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-11-02 00:00:00.000000000 Z
12
+ date: 2012-12-06 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: sync_attr
@@ -108,7 +108,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
108
108
  version: '0'
109
109
  segments:
110
110
  - 0
111
- hash: 3605629782528849560
111
+ hash: -2573404344883398043
112
112
  required_rubygems_version: !ruby/object:Gem::Requirement
113
113
  none: false
114
114
  requirements: