semantic_logger 4.1.1 → 4.2.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.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/lib/semantic_logger.rb +6 -13
  3. data/lib/semantic_logger/ansi_colors.rb +10 -10
  4. data/lib/semantic_logger/appender.rb +42 -26
  5. data/lib/semantic_logger/appender/async.rb +179 -0
  6. data/lib/semantic_logger/appender/async_batch.rb +95 -0
  7. data/lib/semantic_logger/appender/bugsnag.rb +2 -1
  8. data/lib/semantic_logger/appender/elasticsearch.rb +113 -81
  9. data/lib/semantic_logger/appender/elasticsearch_http.rb +1 -3
  10. data/lib/semantic_logger/appender/file.rb +1 -3
  11. data/lib/semantic_logger/appender/graylog.rb +6 -5
  12. data/lib/semantic_logger/appender/honeybadger.rb +0 -2
  13. data/lib/semantic_logger/appender/http.rb +25 -10
  14. data/lib/semantic_logger/appender/kafka.rb +1 -3
  15. data/lib/semantic_logger/appender/mongodb.rb +1 -3
  16. data/lib/semantic_logger/appender/new_relic.rb +7 -3
  17. data/lib/semantic_logger/appender/sentry.rb +6 -7
  18. data/lib/semantic_logger/appender/splunk.rb +1 -2
  19. data/lib/semantic_logger/appender/splunk_http.rb +3 -4
  20. data/lib/semantic_logger/appender/syslog.rb +1 -3
  21. data/lib/semantic_logger/appender/tcp.rb +7 -9
  22. data/lib/semantic_logger/appender/udp.rb +0 -2
  23. data/lib/semantic_logger/appender/wrapper.rb +0 -2
  24. data/lib/semantic_logger/base.rb +76 -19
  25. data/lib/semantic_logger/formatters.rb +37 -0
  26. data/lib/semantic_logger/formatters/base.rb +10 -3
  27. data/lib/semantic_logger/formatters/json.rb +2 -6
  28. data/lib/semantic_logger/formatters/one_line.rb +18 -0
  29. data/lib/semantic_logger/formatters/raw.rb +8 -2
  30. data/lib/semantic_logger/formatters/signalfx.rb +169 -0
  31. data/lib/semantic_logger/log.rb +23 -14
  32. data/lib/semantic_logger/loggable.rb +88 -15
  33. data/lib/semantic_logger/logger.rb +0 -20
  34. data/lib/semantic_logger/metric/new_relic.rb +75 -0
  35. data/lib/semantic_logger/metric/signalfx.rb +123 -0
  36. data/lib/semantic_logger/{metrics → metric}/statsd.rb +20 -8
  37. data/lib/semantic_logger/processor.rb +67 -169
  38. data/lib/semantic_logger/semantic_logger.rb +7 -31
  39. data/lib/semantic_logger/subscriber.rb +32 -36
  40. data/lib/semantic_logger/utils.rb +47 -0
  41. data/lib/semantic_logger/version.rb +1 -1
  42. data/test/appender/async_batch_test.rb +61 -0
  43. data/test/appender/async_test.rb +45 -0
  44. data/test/appender/elasticsearch_http_test.rb +3 -3
  45. data/test/appender/elasticsearch_test.rb +211 -49
  46. data/test/appender/file_test.rb +9 -8
  47. data/test/appender/mongodb_test.rb +3 -3
  48. data/test/appender/newrelic_rpm.rb +6 -0
  49. data/test/appender/sentry_test.rb +3 -1
  50. data/test/appender/wrapper_test.rb +29 -0
  51. data/test/concerns/compatibility_test.rb +64 -60
  52. data/test/debug_as_trace_logger_test.rb +62 -77
  53. data/test/formatters/one_line_test.rb +61 -0
  54. data/test/formatters/signalfx_test.rb +200 -0
  55. data/test/formatters_test.rb +36 -0
  56. data/test/in_memory_appender.rb +9 -0
  57. data/test/in_memory_appender_helper.rb +43 -0
  58. data/test/in_memory_batch_appender.rb +9 -0
  59. data/test/in_memory_metrics_appender.rb +14 -0
  60. data/test/loggable_test.rb +15 -30
  61. data/test/logger_test.rb +181 -135
  62. data/test/measure_test.rb +212 -113
  63. data/test/metric/new_relic_test.rb +36 -0
  64. data/test/metric/signalfx_test.rb +78 -0
  65. data/test/semantic_logger_test.rb +58 -65
  66. data/test/test_helper.rb +19 -2
  67. metadata +33 -7
  68. data/lib/semantic_logger/metrics/new_relic.rb +0 -30
  69. data/lib/semantic_logger/metrics/udp.rb +0 -80
  70. data/test/mock_logger.rb +0 -29
@@ -7,14 +7,15 @@ module Appender
7
7
  class FileTest < Minitest::Test
8
8
  describe SemanticLogger::Appender::File do
9
9
  before do
10
- SemanticLogger.default_level = :trace
11
- @time = Time.new
12
- @io = StringIO.new
13
- @appender = SemanticLogger::Appender::File.new(io: @io)
14
- @hash = {session_id: 'HSSKLEU@JDK767', tracking_number: 12345}
15
- @hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
16
- @thread_name = Thread.current.name
17
- @file_name_reg_exp = RUBY_VERSION.to_f <= 2.0 ? ' (mock|file_test).rb:\d+' : ' file_test.rb:\d+'
10
+ SemanticLogger.default_level = :trace
11
+ SemanticLogger.backtrace_level = :error
12
+ @time = Time.new
13
+ @io = StringIO.new
14
+ @appender = SemanticLogger::Appender::File.new(io: @io)
15
+ @hash = {session_id: 'HSSKLEU@JDK767', tracking_number: 12345}
16
+ @hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
17
+ @thread_name = Thread.current.name
18
+ @file_name_reg_exp = RUBY_VERSION.to_f <= 2.0 ? ' (mock|file_test).rb:\d+' : ' file_test.rb:\d+'
18
19
  end
19
20
 
20
21
  describe 'format logs into text form' do
@@ -8,9 +8,9 @@ module Appender
8
8
  @appender = SemanticLogger::Appender::MongoDB.new(
9
9
  uri: 'mongodb://127.0.0.1:27017/test',
10
10
  collection_size: 10*1024**2, # 10MB
11
- host: 'test',
12
- application: 'test_application',
13
- level: :trace
11
+ host: 'test',
12
+ application: 'test_application',
13
+ level: :trace
14
14
  )
15
15
  @hash = {tracking_number: 12345, session_id: 'HSSKLEU@JDK767'}
16
16
  Thread.current.name = 'thread'
@@ -4,5 +4,11 @@ module NewRelic
4
4
  module Agent
5
5
  def self.notice_error(message, hash)
6
6
  end
7
+
8
+ def self.record_metric(name, secoonds)
9
+ end
10
+
11
+ def self.increment_metric(name, count=1)
12
+ end
7
13
  end
8
14
  end
@@ -37,7 +37,9 @@ module Appender
37
37
 
38
38
  assert_equal error.class.to_s, exception.class.to_s
39
39
  assert_equal error.message, exception.message
40
- assert_equal @message, hash[:message], hash
40
+ assert_equal true, hash.has_key?(:extra)
41
+ assert_equal @message, hash[:extra][:message], hash
42
+ assert_equal level, hash[:level]
41
43
  end
42
44
  end
43
45
 
@@ -4,6 +4,35 @@ require_relative '../test_helper'
4
4
  #
5
5
  module Appender
6
6
  class WrapperTest < Minitest::Test
7
+ # Looks like a standard Ruby Logger or Rails Logger
8
+ # Except that it stores the last logged entry in the instance variable: message
9
+ class MockLogger
10
+ attr_accessor :message
11
+
12
+ Logger::Severity.constants.each do |level|
13
+ class_eval <<-EOT, __FILE__, __LINE__
14
+ def #{level.downcase}(message = nil, progname = nil)
15
+ if message
16
+ self.message = message
17
+ elsif block_given?
18
+ self.message = yield
19
+ else
20
+ self.message = progname
21
+ end
22
+ self.message
23
+ end
24
+
25
+ def #{level}?
26
+ @true
27
+ end
28
+ EOT
29
+ end
30
+
31
+ def flush
32
+ true
33
+ end
34
+ end
35
+
7
36
  describe SemanticLogger::Appender::Wrapper do
8
37
  before do
9
38
  SemanticLogger.default_level = :trace
@@ -1,113 +1,117 @@
1
1
  require_relative '../test_helper'
2
2
 
3
- # Unit Test for SemanticLogger::Logger
4
- class CompatibilityTest < Minitest::Test
3
+ class TestLogger < Minitest::Test
5
4
  describe SemanticLogger::Logger do
6
- before do
7
- # Use a mock logger that just keeps the last logged entry in an instance
8
- # variable
9
- SemanticLogger.default_level = :trace
10
- SemanticLogger.backtrace_level = nil
11
- @mock_logger = MockLogger.new
12
- @appender = SemanticLogger.add_appender(logger: @mock_logger)
13
-
14
- # Use this test's class name as the application name in the log output
15
- @logger = SemanticLogger[CompatibilityTest]
16
- @thread_name = Thread.current.name
17
- end
18
-
19
- after do
20
- SemanticLogger.remove_appender(@appender)
21
- end
5
+ include InMemoryAppenderHelper
22
6
 
23
7
  it '#add' do
24
- @logger.add(Logger::INFO, 'hello world', 'progname') { 'Data' }
25
- SemanticLogger.flush
26
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ I \[\d+:#{@thread_name}\] CompatibilityTest -- hello world -- Data -- \"progname\"/, @mock_logger.message)
8
+ logger.add(Logger::INFO, 'hello world', 'progname') { 'Data' }
9
+
10
+ assert log = log_message
11
+ assert_equal 'hello world -- progname -- Data', log.message
12
+ assert_equal :info, log.level
27
13
  end
28
14
 
29
15
  it '#log' do
30
- @logger.log(Logger::FATAL, 'hello world', 'progname') { 'Data' }
31
- SemanticLogger.flush
32
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ F \[\d+:#{@thread_name}\] CompatibilityTest -- hello world -- Data -- \"progname\"/, @mock_logger.message)
16
+ logger.log(Logger::FATAL, 'hello world', 'progname') { 'Data' }
17
+
18
+ assert log = log_message
19
+ assert_equal 'hello world -- progname -- Data', log.message
20
+ assert_equal :fatal, log.level
33
21
  end
34
22
 
35
23
  it '#unknown' do
36
- @logger.unknown('hello world') { 'Data' }
37
- SemanticLogger.flush
38
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ E \[\d+:#{@thread_name}\] CompatibilityTest -- hello world -- Data/, @mock_logger.message)
24
+ logger.unknown('hello world') { 'Data' }
25
+
26
+ assert log = log_message
27
+ assert_equal 'hello world -- Data', log.message
28
+ assert_equal :error, log.level
29
+ assert_equal 'TestLogger', log.name
39
30
  end
40
31
 
41
32
  it '#unknown? as error?' do
42
33
  SemanticLogger.default_level = :error
43
- assert @logger.unknown?
34
+ assert logger.unknown?
35
+ logger.log(Logger::UNKNOWN, 'hello world', 'progname') { 'Data' }
36
+
37
+ assert log = log_message
38
+ assert_equal 'hello world -- progname -- Data', log.message
39
+ assert_equal :error, log.level
44
40
  end
45
41
 
46
42
  it '#unknown? as error? when false' do
47
43
  SemanticLogger.default_level = :fatal
48
- refute @logger.unknown?
44
+ refute logger.unknown?
45
+ logger.log(Logger::UNKNOWN, 'hello world', 'progname') { 'Data' }
46
+
47
+ refute log_message
49
48
  end
50
49
 
51
50
  it '#silence_logger' do
52
- @logger.silence_logger do
53
- @logger.info 'hello world'
51
+ logger.silence_logger do
52
+ logger.info 'hello world'
54
53
  end
55
- SemanticLogger.flush
56
- refute @mock_logger.message
54
+ refute log_message
57
55
  end
58
56
 
59
57
  it '#<< as info' do
60
- @logger << 'hello world'
61
- SemanticLogger.flush
62
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ I \[\d+:#{@thread_name}\] CompatibilityTest -- hello world/, @mock_logger.message)
58
+ logger << 'hello world'
59
+
60
+ assert log = log_message
61
+ assert_equal 'hello world', log.message
62
+ assert_equal :info, log.level
63
63
  end
64
64
 
65
65
  it '#progname= as #name=' do
66
- assert_equal 'CompatibilityTest', @logger.name
67
- @logger.progname = 'NewTest'
68
- assert_equal 'NewTest', @logger.name
66
+ assert_equal 'TestLogger', logger.name
67
+ logger.progname = 'NewTest'
68
+ assert_equal 'NewTest', logger.name
69
69
  end
70
70
 
71
71
  it '#progname as #name' do
72
- assert_equal 'CompatibilityTest', @logger.name
73
- assert_equal 'CompatibilityTest', @logger.progname
72
+ assert_equal 'TestLogger', logger.name
73
+ assert_equal 'TestLogger', logger.progname
74
74
  end
75
75
 
76
76
  it '#sev_threshold= as #level=' do
77
- assert_equal :trace, @logger.level
78
- @logger.sev_threshold = Logger::DEBUG
79
- assert_equal :debug, @logger.level
77
+ assert_equal :trace, logger.level
78
+ logger.sev_threshold = Logger::DEBUG
79
+ assert_equal :debug, logger.level
80
80
  end
81
81
 
82
82
  it '#sev_threshold as #level' do
83
- assert_equal :trace, @logger.level
84
- assert_equal :trace, @logger.sev_threshold
83
+ assert_equal :trace, logger.level
84
+ assert_equal :trace, logger.sev_threshold
85
85
  end
86
86
 
87
87
  it '#formatter NOOP' do
88
- assert_nil @logger.formatter
89
- @logger.formatter = 'blah'
90
- assert_equal 'blah', @logger.formatter
88
+ assert_nil logger.formatter
89
+ logger.formatter = 'blah'
90
+ assert_equal 'blah', logger.formatter
91
91
  end
92
92
 
93
93
  it '#datetime_format NOOP' do
94
- assert_nil @logger.datetime_format
95
- @logger.datetime_format = 'blah'
96
- assert_equal 'blah', @logger.datetime_format
94
+ assert_nil logger.datetime_format
95
+ logger.datetime_format = 'blah'
96
+ assert_equal 'blah', logger.datetime_format
97
97
  end
98
98
 
99
99
  it '#close NOOP' do
100
- @logger.close
101
- @logger.info('hello world') { 'Data' }
102
- SemanticLogger.flush
103
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ I \[\d+:#{@thread_name}\] CompatibilityTest -- hello world -- Data/, @mock_logger.message)
100
+ logger.close
101
+ logger.info('hello world')
102
+
103
+ assert log = log_message
104
+ assert_equal 'hello world', log.message
105
+ assert_equal :info, log.level
104
106
  end
105
107
 
106
108
  it '#reopen NOOP' do
107
- @logger.reopen
108
- @logger.info('hello world') { 'Data' }
109
- SemanticLogger.flush
110
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ I \[\d+:#{@thread_name}\] CompatibilityTest -- hello world -- Data/, @mock_logger.message)
109
+ logger.reopen
110
+ logger.info('hello world')
111
+
112
+ assert log = log_message
113
+ assert_equal 'hello world', log.message
114
+ assert_equal :info, log.level
111
115
  end
112
116
 
113
117
  end
@@ -1,95 +1,80 @@
1
1
  require_relative 'test_helper'
2
2
 
3
- # Unit Test for SemanticLogger::Logger
4
3
  class DebugAsTraceLoggerTest < Minitest::Test
5
4
  describe SemanticLogger::Logger do
6
- # Test each filter
7
- [nil, /\ADebugAsTraceLoggerTest/, Proc.new { |l| (/\AExclude/ =~ l.message).nil? }].each do |filter|
8
- describe "filter: #{filter.class.name}" do
9
- before do
10
- # Use a mock logger that just keeps the last logged entry in an instance
11
- # variable
12
- SemanticLogger.default_level = :trace
13
- @mock_logger = MockLogger.new
14
- appender = SemanticLogger.add_appender(logger: @mock_logger)
15
- appender.filter = filter
5
+ describe '.level?' do
6
+ let :logger do
7
+ SemanticLogger::DebugAsTraceLogger.new('TestLogger')
8
+ end
16
9
 
17
- # Use this test's class name as the application name in the log output
18
- @logger = SemanticLogger::DebugAsTraceLogger.new(DebugAsTraceLoggerTest)
19
- @hash = {session_id: 'HSSKLEU@JDK767', tracking_number: 12345}
20
- @hash_str = @hash.inspect.sub("{", "\\{").sub("}", "\\}")
21
- assert_equal [], @logger.tags
22
- end
10
+ it 'return true for debug? with :trace level' do
11
+ SemanticLogger.default_level = :trace
12
+ assert_equal :trace, logger.level
13
+ assert_equal true, logger.debug?
14
+ assert_equal true, logger.trace?
15
+ end
23
16
 
24
- after do
25
- # Remove all appenders
26
- SemanticLogger.appenders.each { |appender| SemanticLogger.remove_appender(appender) }
27
- end
17
+ it 'return false for debug? with global :debug level' do
18
+ SemanticLogger.default_level = :debug
19
+ assert_equal :debug, logger.level, logger
20
+ assert logger.info?, logger.inspect
21
+ refute logger.debug?, logger.inspect
22
+ refute logger.trace?, logger.inspect
23
+ end
28
24
 
29
- describe '.level?' do
30
- it 'return true for debug? with :trace level' do
31
- SemanticLogger.default_level = :trace
32
- assert_equal :trace, @logger.level
33
- assert_equal true, @logger.debug?
34
- assert_equal true, @logger.trace?
35
- end
25
+ it 'return true for debug? with global :info level' do
26
+ SemanticLogger.default_level = :info
27
+ assert_equal :info, logger.level, logger.inspect
28
+ refute logger.debug?, logger.inspect
29
+ refute logger.trace?, logger.inspect
30
+ end
36
31
 
37
- it 'return false for debug? with global :debug level' do
38
- SemanticLogger.default_level = :debug
39
- assert_equal :debug, @logger.level, @logger.inspect
40
- assert_equal false, @logger.debug?, @logger.inspect
41
- assert_equal false, @logger.trace?, @logger.inspect
42
- end
32
+ it 'return false for debug? with instance :debug level' do
33
+ logger.level = :debug
34
+ assert_equal :debug, logger.level, logger.inspect
35
+ refute logger.debug?, logger.inspect
36
+ refute logger.trace?, logger.inspect
37
+ end
43
38
 
44
- it 'return true for debug? with global :info level' do
45
- SemanticLogger.default_level = :info
46
- assert_equal :info, @logger.level, @logger.inspect
47
- assert_equal false, @logger.debug?, @logger.inspect
48
- assert_equal false, @logger.trace?, @logger.inspect
49
- end
39
+ it 'return true for debug? with instance :info level' do
40
+ logger.level = :info
41
+ assert_equal :info, logger.level, logger.inspect
42
+ refute logger.debug?, logger.inspect
43
+ refute logger.trace?, logger.inspect
44
+ end
45
+ end
50
46
 
51
- it 'return false for debug? with instance :debug level' do
52
- @logger.level = :debug
53
- assert_equal :debug, @logger.level, @logger.inspect
54
- assert_equal false, @logger.debug?, @logger.inspect
55
- assert_equal false, @logger.trace?, @logger.inspect
56
- end
47
+ describe 'log' do
48
+ include InMemoryAppenderHelper
57
49
 
58
- it 'return true for debug? with instance :info level' do
59
- @logger.level = :info
60
- assert_equal :info, @logger.level, @logger.inspect
61
- assert_equal false, @logger.debug?, @logger.inspect
62
- assert_equal false, @logger.trace?, @logger.inspect
63
- end
64
- end
50
+ let :logger do
51
+ SemanticLogger::DebugAsTraceLogger.new('TestLogger')
52
+ end
65
53
 
66
- it 'not log trace when level is debug' do
67
- @logger.level = :debug
68
- @logger.trace('hello world', @hash) { 'Calculations' }
69
- SemanticLogger.flush
70
- assert_nil @mock_logger.message
71
- end
54
+ it 'not log trace when level is debug' do
55
+ logger.level = :debug
56
+ logger.trace('hello world', payload) { 'Calculations' }
57
+ refute log_message
58
+ end
72
59
 
73
- it 'not log debug when level is debug' do
74
- @logger.level = :debug
75
- @logger.debug('hello world', @hash) { 'Calculations' }
76
- SemanticLogger.flush
77
- assert_nil @mock_logger.message
78
- end
60
+ it 'not log debug when level is debug' do
61
+ logger.level = :debug
62
+ logger.debug('hello world', payload) { 'Calculations' }
63
+ refute log_message
64
+ end
79
65
 
80
- it 'map trace to debug' do
81
- @logger.level = :trace
82
- @logger.debug('hello world', @hash) { 'Calculations' }
83
- SemanticLogger.flush
84
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ T \[\d+:.+\] DebugAsTraceLoggerTest -- hello world -- Calculations -- #{@hash_str}/, @mock_logger.message)
85
- end
66
+ it 'map debug to trace' do
67
+ logger.level = :trace
68
+ logger.debug('hello world')
69
+ assert log = log_message
70
+ assert_equal :trace, log.level
71
+ end
86
72
 
87
- it 'log trace as trace' do
88
- @logger.level = :trace
89
- @logger.trace('hello world', @hash) { 'Calculations' }
90
- SemanticLogger.flush
91
- assert_match(/\d+-\d+-\d+ \d+:\d+:\d+.\d+ T \[\d+:.+\] DebugAsTraceLoggerTest -- hello world -- Calculations -- #{@hash_str}/, @mock_logger.message)
92
- end
73
+ it 'log trace as trace' do
74
+ logger.level = :trace
75
+ logger.trace('hello world', payload) { 'Calculations' }
76
+ assert log = log_message
77
+ assert_equal :trace, log.level
93
78
  end
94
79
  end
95
80
 
@@ -0,0 +1,61 @@
1
+ require_relative '../test_helper'
2
+
3
+ module SemanticLogger
4
+ module Formatters
5
+ class DefaultTest < Minitest::Test
6
+ describe Default do
7
+ let(:log_time) do
8
+ Time.utc(2017, 1, 14, 8, 32, 5.375276)
9
+ end
10
+
11
+ let(:level) do
12
+ :debug
13
+ end
14
+
15
+ let(:log) do
16
+ log = SemanticLogger::Log.new('DefaultTest', level)
17
+ log.time = log_time
18
+ log
19
+ end
20
+
21
+ let(:set_exception) do
22
+ begin
23
+ raise 'Oh no'
24
+ rescue Exception => exc
25
+ log.exception = exc
26
+ end
27
+ end
28
+
29
+ let(:formatter) do
30
+ formatter = SemanticLogger::Formatters::OneLine.new
31
+ # Does not use the logger instance for formatting purposes
32
+ formatter.call(log, nil)
33
+ formatter
34
+ end
35
+
36
+ describe 'message' do
37
+ it 'logs message' do
38
+ log.message = "Hello \nWorld\n"
39
+ assert_equal "-- Hello World", formatter.message
40
+ end
41
+
42
+ it 'skips empty message' do
43
+ refute formatter.message
44
+ end
45
+ end
46
+
47
+ describe 'exception' do
48
+ it 'logs exception' do
49
+ set_exception
50
+ assert_equal '-- Exception: RuntimeError: Oh no', formatter.exception
51
+ end
52
+
53
+ it 'skips nil exception' do
54
+ refute formatter.exception
55
+ end
56
+ end
57
+
58
+ end
59
+ end
60
+ end
61
+ end