semantic_logger 4.2.0 → 4.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (88) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +3 -3
  3. data/Rakefile +1 -1
  4. data/lib/semantic_logger/ansi_colors.rb +11 -12
  5. data/lib/semantic_logger/appender.rb +4 -5
  6. data/lib/semantic_logger/appender/async.rb +24 -16
  7. data/lib/semantic_logger/appender/async_batch.rb +1 -4
  8. data/lib/semantic_logger/appender/bugsnag.rb +67 -63
  9. data/lib/semantic_logger/appender/elasticsearch.rb +154 -157
  10. data/lib/semantic_logger/appender/elasticsearch_http.rb +59 -55
  11. data/lib/semantic_logger/appender/file.rb +1 -3
  12. data/lib/semantic_logger/appender/graylog.rb +114 -110
  13. data/lib/semantic_logger/appender/honeybadger.rb +54 -51
  14. data/lib/semantic_logger/appender/http.rb +194 -190
  15. data/lib/semantic_logger/appender/kafka.rb +152 -149
  16. data/lib/semantic_logger/appender/mongodb.rb +3 -3
  17. data/lib/semantic_logger/appender/new_relic.rb +52 -49
  18. data/lib/semantic_logger/appender/sentry.rb +59 -54
  19. data/lib/semantic_logger/appender/splunk.rb +108 -103
  20. data/lib/semantic_logger/appender/splunk_http.rb +82 -79
  21. data/lib/semantic_logger/appender/syslog.rb +4 -5
  22. data/lib/semantic_logger/appender/tcp.rb +8 -29
  23. data/lib/semantic_logger/appender/udp.rb +2 -3
  24. data/lib/semantic_logger/appender/wrapper.rb +2 -2
  25. data/lib/semantic_logger/base.rb +18 -16
  26. data/lib/semantic_logger/concerns/compatibility.rb +0 -1
  27. data/lib/semantic_logger/core_ext/thread.rb +0 -1
  28. data/lib/semantic_logger/formatters.rb +3 -5
  29. data/lib/semantic_logger/formatters/base.rb +2 -3
  30. data/lib/semantic_logger/formatters/color.rb +29 -12
  31. data/lib/semantic_logger/formatters/default.rb +10 -10
  32. data/lib/semantic_logger/formatters/json.rb +0 -2
  33. data/lib/semantic_logger/formatters/one_line.rb +2 -2
  34. data/lib/semantic_logger/formatters/raw.rb +7 -10
  35. data/lib/semantic_logger/formatters/signalfx.rb +3 -5
  36. data/lib/semantic_logger/formatters/syslog.rb +2 -3
  37. data/lib/semantic_logger/formatters/syslog_cee.rb +2 -3
  38. data/lib/semantic_logger/jruby/garbage_collection_logger.rb +8 -5
  39. data/lib/semantic_logger/log.rb +17 -17
  40. data/lib/semantic_logger/loggable.rb +6 -9
  41. data/lib/semantic_logger/logger.rb +0 -1
  42. data/lib/semantic_logger/metric/new_relic.rb +58 -55
  43. data/lib/semantic_logger/metric/signalfx.rb +108 -106
  44. data/lib/semantic_logger/metric/statsd.rb +2 -3
  45. data/lib/semantic_logger/processor.rb +9 -9
  46. data/lib/semantic_logger/semantic_logger.rb +50 -30
  47. data/lib/semantic_logger/subscriber.rb +0 -1
  48. data/lib/semantic_logger/utils.rb +37 -37
  49. data/lib/semantic_logger/version.rb +2 -2
  50. data/test/appender/async_batch_test.rb +0 -1
  51. data/test/appender/async_test.rb +0 -1
  52. data/test/appender/bugsnag_test.rb +7 -8
  53. data/test/appender/elasticsearch_http_test.rb +5 -6
  54. data/test/appender/elasticsearch_test.rb +14 -10
  55. data/test/appender/file_test.rb +5 -6
  56. data/test/appender/graylog_test.rb +8 -8
  57. data/test/appender/honeybadger_test.rb +6 -7
  58. data/test/appender/http_test.rb +4 -5
  59. data/test/appender/kafka_test.rb +5 -6
  60. data/test/appender/mongodb_test.rb +11 -13
  61. data/test/appender/new_relic_test.rb +8 -9
  62. data/test/appender/newrelic_rpm.rb +1 -1
  63. data/test/appender/sentry_test.rb +7 -8
  64. data/test/appender/splunk_http_test.rb +4 -4
  65. data/test/appender/splunk_test.rb +1 -3
  66. data/test/appender/syslog_test.rb +3 -5
  67. data/test/appender/tcp_test.rb +4 -5
  68. data/test/appender/udp_test.rb +4 -5
  69. data/test/appender/wrapper_test.rb +2 -3
  70. data/test/concerns/compatibility_test.rb +0 -1
  71. data/test/debug_as_trace_logger_test.rb +0 -1
  72. data/test/formatters/color_test.rb +5 -6
  73. data/test/formatters/default_test.rb +16 -17
  74. data/test/formatters/one_line_test.rb +1 -2
  75. data/test/formatters/signalfx_test.rb +8 -11
  76. data/test/formatters_test.rb +3 -3
  77. data/test/in_memory_appender.rb +0 -1
  78. data/test/in_memory_appender_helper.rb +1 -1
  79. data/test/in_memory_batch_appender.rb +0 -1
  80. data/test/in_memory_metrics_appender.rb +0 -1
  81. data/test/loggable_test.rb +2 -3
  82. data/test/logger_test.rb +11 -14
  83. data/test/measure_test.rb +13 -15
  84. data/test/metric/new_relic_test.rb +2 -3
  85. data/test/metric/signalfx_test.rb +4 -5
  86. data/test/semantic_logger_test.rb +28 -3
  87. data/test/test_helper.rb +6 -7
  88. metadata +34 -34
@@ -30,7 +30,6 @@
30
30
  # ExternalSupplier.prepend SemanticLogger::Loggable
31
31
  module SemanticLogger
32
32
  module Loggable
33
-
34
33
  def self.included(base)
35
34
  base.extend ClassMethods
36
35
  base.class_eval do
@@ -85,14 +84,14 @@ module SemanticLogger
85
84
 
86
85
  index = SemanticLogger.level_to_index(level)
87
86
 
88
- logger_measure_module.module_eval(<<-EOT, __FILE__, __LINE__ + 1)
87
+ logger_measure_module.module_eval(<<~MEASURE_METHOD, __FILE__, __LINE__ + 1)
89
88
  def #{method_name}(*args, &block)
90
89
  if logger.send(:level_index) <= #{index}
91
90
  logger.send(
92
91
  :measure_method,
93
- index: #{index},
94
- level: #{level.inspect},
95
- message: #{message.inspect},
92
+ index: #{index},
93
+ level: #{level.inspect},
94
+ message: #{message.inspect},
96
95
  min_duration: #{min_duration},
97
96
  metric: #{metric.inspect},
98
97
  log_exception: #{log_exception.inspect},
@@ -104,8 +103,8 @@ module SemanticLogger
104
103
  super(*args, &block)
105
104
  end
106
105
  end
107
- EOT
108
- #{"#{visibility} :#{method_name}" unless visibility == :public}
106
+ MEASURE_METHOD
107
+ # {"#{visibility} :#{method_name}" unless visibility == :public}
109
108
  true
110
109
  end
111
110
 
@@ -121,8 +120,6 @@ module SemanticLogger
121
120
  mod
122
121
  end
123
122
  end
124
-
125
123
  end
126
-
127
124
  end
128
125
  end
@@ -37,6 +37,5 @@ module SemanticLogger
37
37
  return add(log, message, progname, &block) unless log.is_a?(SemanticLogger::Log)
38
38
  Processor << log
39
39
  end
40
-
41
40
  end
42
41
  end
@@ -11,65 +11,68 @@ end
11
11
  #
12
12
  # Example:
13
13
  # SemanticLogger.add_appender(metric: :new_relic)
14
- class SemanticLogger::Metric::NewRelic < SemanticLogger::Subscriber
15
- attr_accessor :prefix
14
+ module SemanticLogger
15
+ module Metric
16
+ class NewRelic < SemanticLogger::Subscriber
17
+ attr_accessor :prefix
16
18
 
17
- # Create Appender
18
- #
19
- # Parameters
20
- # :prefix [String]
21
- # Prefix to add to every metric before forwarding to NewRelic.
22
- # Default: 'Custom'
23
- #
24
- # level: [:trace | :debug | :info | :warn | :error | :fatal]
25
- # Override the log level for this appender.
26
- # Default: :error
27
- #
28
- # formatter: [Object|Proc]
29
- # An instance of a class that implements #call, or a Proc to be used to format
30
- # the output from this appender
31
- # Default: Use the built-in formatter (See: #call)
32
- #
33
- # filter: [Regexp|Proc]
34
- # RegExp: Only include log messages where the class name matches the supplied.
35
- # regular expression. All other messages will be ignored.
36
- # Proc: Only include log messages where the supplied Proc returns true
37
- # The Proc must return true or false.
38
- def initialize(prefix: 'Custom',
39
- level: nil,
40
- formatter: nil,
41
- filter: nil,
42
- application: nil,
43
- host: nil,
44
- &block)
19
+ # Create Appender
20
+ #
21
+ # Parameters
22
+ # :prefix [String]
23
+ # Prefix to add to every metric before forwarding to NewRelic.
24
+ # Default: 'Custom'
25
+ #
26
+ # level: [:trace | :debug | :info | :warn | :error | :fatal]
27
+ # Override the log level for this appender.
28
+ # Default: :error
29
+ #
30
+ # formatter: [Object|Proc]
31
+ # An instance of a class that implements #call, or a Proc to be used to format
32
+ # the output from this appender
33
+ # Default: Use the built-in formatter (See: #call)
34
+ #
35
+ # filter: [Regexp|Proc]
36
+ # RegExp: Only include log messages where the class name matches the supplied.
37
+ # regular expression. All other messages will be ignored.
38
+ # Proc: Only include log messages where the supplied Proc returns true
39
+ # The Proc must return true or false.
40
+ def initialize(prefix: 'Custom',
41
+ level: nil,
42
+ formatter: nil,
43
+ filter: nil,
44
+ application: nil,
45
+ host: nil,
46
+ &block)
45
47
 
46
- @prefix = prefix
47
- super(level: level, formatter: formatter, filter: filter, application: application, host: host, &block)
48
- end
48
+ @prefix = prefix
49
+ super(level: level, formatter: formatter, filter: filter, application: application, host: host, &block)
50
+ end
49
51
 
50
- # Returns metric name to use.
51
- def call(log, _logger)
52
- metric = log.metric
53
- # Add prefix for NewRelic
54
- metric = "#{prefix}/#{metric}" unless metric.start_with?(prefix)
55
- metric
56
- end
52
+ # Returns metric name to use.
53
+ def call(log, _logger)
54
+ metric = log.metric
55
+ # Add prefix for NewRelic
56
+ metric = "#{prefix}/#{metric}" unless metric.start_with?(prefix)
57
+ metric
58
+ end
57
59
 
58
- def log(log)
59
- name = formatter.call(log, self)
60
- if duration = log.duration
61
- # Convert duration to seconds
62
- ::NewRelic::Agent.record_metric(name, duration / 1000.0)
63
- else
64
- ::NewRelic::Agent.increment_metric(name, log.metric_amount || 1)
65
- end
66
- true
67
- end
60
+ def log(log)
61
+ name = formatter.call(log, self)
62
+ if (duration = log.duration)
63
+ # Convert duration to seconds
64
+ ::NewRelic::Agent.record_metric(name, duration / 1000.0)
65
+ else
66
+ ::NewRelic::Agent.increment_metric(name, log.metric_amount || 1)
67
+ end
68
+ true
69
+ end
68
70
 
69
- # Only forward log entries that contain metrics.
70
- def should_log?(log)
71
- # Does not support metrics with dimensions.
72
- log.metric && !log.dimensions && meets_log_level?(log) && !filtered?(log)
71
+ # Only forward log entries that contain metrics.
72
+ def should_log?(log)
73
+ # Does not support metrics with dimensions.
74
+ log.metric && !log.dimensions && meets_log_level?(log) && !filtered?(log)
75
+ end
76
+ end
73
77
  end
74
-
75
78
  end
@@ -5,119 +5,121 @@
5
5
  # metric: :signalfx,
6
6
  # token: 'SIGNALFX_ORG_ACCESS_TOKEN'
7
7
  # )
8
- class SemanticLogger::Metric::Signalfx < SemanticLogger::Appender::Http
9
- attr_reader :full_url
8
+ module SemanticLogger
9
+ module Metric
10
+ class Signalfx < SemanticLogger::Appender::Http
11
+ attr_reader :full_url
10
12
 
11
- END_POINT = 'v2/datapoint'
13
+ END_POINT = 'v2/datapoint'.freeze
12
14
 
13
- # Create SignalFx metrics appender.
14
- #
15
- # Parameters:
16
- # token: [String]
17
- # Access Token to use for sending metrics.
18
- # Obtain the Signalfx token via the Signalfx Web UI under `Organization` -> `Access Tokens`.
19
- #
20
- # dimensions: [Array<String>]
21
- # Dimensions to forward to signalfx when they are present in the named tags of any log message.
22
- # By default `application` and `host` are always included as dimensions in all forwarded metrics.
23
- # Example: [:user_id, :state]
24
- #
25
- # filter: [Regexp|Proc]
26
- # RegExp: Only include log messages where the class name matches the supplied
27
- # regular expression. All other messages will be ignored.
28
- # Proc: Only include log messages where the supplied Proc returns true.
29
- # The Proc must return true or false.
30
- #
31
- # host: [String]
32
- # Name of this host to send as a dimension.
33
- # Default: SemanticLogger.host
34
- #
35
- # application: [String]
36
- # Name of this application to send as a dimension.
37
- # Default: SemanticLogger.application
38
- #
39
- # url: [String]
40
- # Override the SignalFx service url.
41
- # For historical data use: https://backfill.signalfx.com/v1/backfill
42
- # Default: https://ingest.signalfx.com
43
- #
44
- # Notes:
45
- #
46
- # When sending a metric to Signalfx, it is necessary to send both a `gauge` and a `counter` when a
47
- # duration is included in the metric, otherwise it is not possible to chart counts of the metric.
48
- # Unfortunately this doubles the number of metrics, but it is the way Signalfx works.
49
- # Using a `count` of a `gauge` in a chart will significantly under-count the number of occurrences.
50
- #
51
- # If dimensions are added to the metric, then the metric will be sent as-is and
52
- # the above logic will _not_ be applied.
53
- #
54
- # Example, Gauge metric, supplying the duration in `metric_amount`:
55
- # logger.info(metric: 'Filters.average', metric_amount: 1.2, dimensions: {user: 'jbloggs'})
56
- #
57
- # Example, Counter metric:
58
- # logger.info(metric: 'Filters.count', dimensions: {user: 'jbloggs'})
59
- #
60
- # Example, Counter metric with a count other than 1:
61
- # logger.info(metric: 'Filters.count', metric_amount: 23, dimensions: {user: 'jbloggs'})
62
- #
63
- # When a duration is supplied and no dimensions are supplied:
64
- # logger.info(metric: 'Common/User/authorize', duration: 1.4)
65
- #
66
- # Then it is translated into the following 2 log entries under the covers:
67
- # logger.info(metric: 'Application.average', metric_amount: 1.4, dimensions: {class: 'Common::User', action: 'authorize'})
68
- # logger.info(metric: 'Application.counter', metric_amount: 1, dimensions: {class: 'Common::User', action: 'authorize'})
69
- #
70
- # Similarly with a measure block which automatically supplies the duration:
71
- # logger.measure_info(metric: 'Common/User/authorize') do
72
- # sleep 1
73
- # end
74
- def initialize(token:,
75
- dimensions: nil,
76
- url: 'https://ingest.signalfx.com',
77
- open_timeout: 2.0,
78
- read_timeout: 1.0,
79
- continue_timeout: 1.0,
80
- filter: nil,
81
- application: nil,
82
- host: nil,
83
- formatter: nil,
84
- &block)
15
+ # Create SignalFx metrics appender.
16
+ #
17
+ # Parameters:
18
+ # token: [String]
19
+ # Access Token to use for sending metrics.
20
+ # Obtain the Signalfx token via the Signalfx Web UI under `Organization` -> `Access Tokens`.
21
+ #
22
+ # dimensions: [Array<String>]
23
+ # Dimensions to forward to signalfx when they are present in the named tags of any log message.
24
+ # By default `application` and `host` are always included as dimensions in all forwarded metrics.
25
+ # Example: [:user_id, :state]
26
+ #
27
+ # filter: [Regexp|Proc]
28
+ # RegExp: Only include log messages where the class name matches the supplied
29
+ # regular expression. All other messages will be ignored.
30
+ # Proc: Only include log messages where the supplied Proc returns true.
31
+ # The Proc must return true or false.
32
+ #
33
+ # host: [String]
34
+ # Name of this host to send as a dimension.
35
+ # Default: SemanticLogger.host
36
+ #
37
+ # application: [String]
38
+ # Name of this application to send as a dimension.
39
+ # Default: SemanticLogger.application
40
+ #
41
+ # url: [String]
42
+ # Override the SignalFx service url.
43
+ # For historical data use: https://backfill.signalfx.com/v1/backfill
44
+ # Default: https://ingest.signalfx.com
45
+ #
46
+ # Notes:
47
+ #
48
+ # When sending a metric to Signalfx, it is necessary to send both a `gauge` and a `counter` when a
49
+ # duration is included in the metric, otherwise it is not possible to chart counts of the metric.
50
+ # Unfortunately this doubles the number of metrics, but it is the way Signalfx works.
51
+ # Using a `count` of a `gauge` in a chart will significantly under-count the number of occurrences.
52
+ #
53
+ # If dimensions are added to the metric, then the metric will be sent as-is and
54
+ # the above logic will _not_ be applied.
55
+ #
56
+ # Example, Gauge metric, supplying the duration in `metric_amount`:
57
+ # logger.info(metric: 'Filters.average', metric_amount: 1.2, dimensions: {user: 'jbloggs'})
58
+ #
59
+ # Example, Counter metric:
60
+ # logger.info(metric: 'Filters.count', dimensions: {user: 'jbloggs'})
61
+ #
62
+ # Example, Counter metric with a count other than 1:
63
+ # logger.info(metric: 'Filters.count', metric_amount: 23, dimensions: {user: 'jbloggs'})
64
+ #
65
+ # When a duration is supplied and no dimensions are supplied:
66
+ # logger.info(metric: 'Common/User/authorize', duration: 1.4)
67
+ #
68
+ # Then it is translated into the following 2 log entries under the covers:
69
+ # logger.info(metric: 'Application.average', metric_amount: 1.4, dimensions: {class: 'Common::User', action: 'authorize'})
70
+ # logger.info(metric: 'Application.counter', metric_amount: 1, dimensions: {class: 'Common::User', action: 'authorize'})
71
+ #
72
+ # Similarly with a measure block which automatically supplies the duration:
73
+ # logger.measure_info(metric: 'Common/User/authorize') do
74
+ # sleep 1
75
+ # end
76
+ def initialize(token:,
77
+ dimensions: nil,
78
+ url: 'https://ingest.signalfx.com',
79
+ open_timeout: 2.0,
80
+ read_timeout: 1.0,
81
+ continue_timeout: 1.0,
82
+ filter: nil,
83
+ application: nil,
84
+ host: nil,
85
+ formatter: nil,
86
+ &block)
85
87
 
86
- formatter ||= SemanticLogger::Formatters::Signalfx.new(token: token, dimensions: dimensions)
88
+ formatter ||= SemanticLogger::Formatters::Signalfx.new(token: token, dimensions: dimensions)
87
89
 
88
- super(
89
- url: url,
90
- read_timeout: read_timeout,
91
- open_timeout: open_timeout,
92
- continue_timeout: continue_timeout,
93
- filter: filter,
94
- application: application,
95
- host: host,
96
- formatter: formatter,
97
- &block
98
- )
90
+ super(
91
+ url: url,
92
+ read_timeout: read_timeout,
93
+ open_timeout: open_timeout,
94
+ continue_timeout: continue_timeout,
95
+ filter: filter,
96
+ application: application,
97
+ host: host,
98
+ formatter: formatter,
99
+ &block
100
+ )
99
101
 
100
- @header['X-SF-TOKEN'] = token
101
- @full_url = "#{url}/#{END_POINT}"
102
- end
102
+ @header['X-SF-TOKEN'] = token
103
+ @full_url = "#{url}/#{END_POINT}"
104
+ end
103
105
 
104
- def log(log)
105
- message = formatter.call(log, self)
106
- logger.trace(message)
107
- post(message, full_url)
108
- end
106
+ def log(log)
107
+ message = formatter.call(log, self)
108
+ logger.trace(message)
109
+ post(message, full_url)
110
+ end
109
111
 
110
- # Logs in batches
111
- def batch(logs)
112
- message = formatter.batch(logs, self)
113
- logger.trace(message)
114
- post(message, full_url)
115
- end
112
+ # Logs in batches
113
+ def batch(logs)
114
+ message = formatter.batch(logs, self)
115
+ logger.trace(message)
116
+ post(message, full_url)
117
+ end
116
118
 
117
- # Only forward log entries that contain metrics.
118
- def should_log?(log)
119
- log.metric && meets_log_level?(log) && !filtered?(log)
119
+ # Only forward log entries that contain metrics.
120
+ def should_log?(log)
121
+ log.metric && meets_log_level?(log) && !filtered?(log)
122
+ end
123
+ end
120
124
  end
121
-
122
125
  end
123
-
@@ -41,11 +41,11 @@ module SemanticLogger
41
41
 
42
42
  def log(log)
43
43
  metric = log.metric
44
- if duration = log.duration
44
+ if (duration = log.duration)
45
45
  @statsd.timing(metric, duration)
46
46
  else
47
47
  amount = (log.metric_amount || 1).round
48
- if amount < 0
48
+ if amount.negative?
49
49
  amount.times { @statsd.decrement(metric) }
50
50
  else
51
51
  amount.times { @statsd.increment(metric) }
@@ -58,7 +58,6 @@ module SemanticLogger
58
58
  # Does not support metrics with dimensions.
59
59
  log.metric && !log.dimensions && meets_log_level?(log) && !filtered?(log)
60
60
  end
61
-
62
61
  end
63
62
  end
64
63
  end
@@ -60,8 +60,8 @@ module SemanticLogger
60
60
  # Can be replaced with another Ruby logger or Rails logger, but never to
61
61
  # SemanticLogger::Logger itself since it is for reporting problems
62
62
  # while trying to log to the various appenders
63
- def self.logger=(logger)
64
- @logger = logger
63
+ class << self
64
+ attr_writer :logger
65
65
  end
66
66
 
67
67
  # Internal logger for SemanticLogger
@@ -86,7 +86,10 @@ module SemanticLogger
86
86
  def on_log(object = nil, &block)
87
87
  subscriber = block || object
88
88
 
89
- raise('When supplying an on_log subscriber, it must support the #call method') unless subscriber.is_a?(Proc) || subscriber.respond_to?(:call)
89
+ unless subscriber.is_a?(Proc) || subscriber.respond_to?(:call)
90
+ raise('When supplying an on_log subscriber, it must support the #call method')
91
+ end
92
+
90
93
  subscribers = (@log_subscribers ||= Concurrent::Array.new)
91
94
  subscribers << subscriber unless subscribers.include?(subscriber)
92
95
  end
@@ -130,13 +133,11 @@ module SemanticLogger
130
133
  private
131
134
 
132
135
  def self.create_instance
133
- SemanticLogger::Appender::Async.new(
134
- name: 'SemanticLogger::Processor',
135
- appender: new,
136
- max_queue_size: -1
137
- )
136
+ SemanticLogger::Appender::Async.new(appender: new, max_queue_size: -1)
138
137
  end
139
138
 
139
+ private_class_method :create_instance
140
+
140
141
  @processor = create_instance
141
142
 
142
143
  # Call on_log subscribers
@@ -152,6 +153,5 @@ module SemanticLogger
152
153
  end
153
154
  end
154
155
  end
155
-
156
156
  end
157
157
  end