semantic_logger 4.1.1 → 4.2.0

Sign up to get free protection for your applications and to get access to all the features.
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