semantic_logger 4.18.0 → 5.0.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 (65) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -81
  3. data/Rakefile +10 -3
  4. data/lib/semantic_logger/appender/async.rb +86 -173
  5. data/lib/semantic_logger/appender/cloudwatch_logs.rb +4 -4
  6. data/lib/semantic_logger/appender/elasticsearch.rb +6 -182
  7. data/lib/semantic_logger/appender/elasticsearch_base.rb +212 -0
  8. data/lib/semantic_logger/appender/elasticsearch_http.rb +2 -2
  9. data/lib/semantic_logger/appender/file.rb +20 -4
  10. data/lib/semantic_logger/appender/graylog.rb +2 -2
  11. data/lib/semantic_logger/appender/http.rb +27 -2
  12. data/lib/semantic_logger/appender/io.rb +8 -4
  13. data/lib/semantic_logger/appender/kafka.rb +2 -2
  14. data/lib/semantic_logger/appender/loki.rb +2 -4
  15. data/lib/semantic_logger/appender/mongodb.rb +3 -6
  16. data/lib/semantic_logger/appender/new_relic_logs.rb +2 -2
  17. data/lib/semantic_logger/appender/open_telemetry.rb +8 -6
  18. data/lib/semantic_logger/appender/opensearch.rb +35 -0
  19. data/lib/semantic_logger/appender/rabbitmq.rb +3 -3
  20. data/lib/semantic_logger/appender/sentry_ruby.rb +2 -2
  21. data/lib/semantic_logger/appender/splunk.rb +2 -2
  22. data/lib/semantic_logger/appender/splunk_http.rb +3 -3
  23. data/lib/semantic_logger/appender/syslog.rb +5 -4
  24. data/lib/semantic_logger/appender/tcp.rb +2 -2
  25. data/lib/semantic_logger/appender/udp.rb +2 -2
  26. data/lib/semantic_logger/appender/wrapper.rb +4 -4
  27. data/lib/semantic_logger/appender.rb +30 -19
  28. data/lib/semantic_logger/appenders.rb +26 -5
  29. data/lib/semantic_logger/base.rb +100 -21
  30. data/lib/semantic_logger/concerns/compatibility.rb +2 -2
  31. data/lib/semantic_logger/core_ext/process.rb +34 -0
  32. data/lib/semantic_logger/formatters/base.rb +46 -7
  33. data/lib/semantic_logger/formatters/color.rb +6 -3
  34. data/lib/semantic_logger/formatters/default.rb +6 -4
  35. data/lib/semantic_logger/formatters/ecs.rb +151 -0
  36. data/lib/semantic_logger/formatters/fluentd.rb +15 -4
  37. data/lib/semantic_logger/formatters/json.rb +6 -1
  38. data/lib/semantic_logger/formatters/logfmt.rb +2 -2
  39. data/lib/semantic_logger/formatters/loki.rb +4 -4
  40. data/lib/semantic_logger/formatters/open_telemetry.rb +15 -5
  41. data/lib/semantic_logger/formatters/pattern.rb +235 -0
  42. data/lib/semantic_logger/formatters/raw.rb +2 -2
  43. data/lib/semantic_logger/formatters/signalfx.rb +2 -2
  44. data/lib/semantic_logger/formatters/syslog.rb +14 -3
  45. data/lib/semantic_logger/formatters/syslog_cee.rb +1 -1
  46. data/lib/semantic_logger/formatters.rb +2 -0
  47. data/lib/semantic_logger/log.rb +18 -4
  48. data/lib/semantic_logger/logger.rb +2 -2
  49. data/lib/semantic_logger/metric/new_relic.rb +2 -2
  50. data/lib/semantic_logger/metric/signalfx.rb +2 -2
  51. data/lib/semantic_logger/metric/statsd.rb +2 -2
  52. data/lib/semantic_logger/processor.rb +21 -0
  53. data/lib/semantic_logger/queue_processor.rb +369 -0
  54. data/lib/semantic_logger/reporters/minitest.rb +4 -4
  55. data/lib/semantic_logger/semantic_logger.rb +103 -11
  56. data/lib/semantic_logger/subscriber.rb +15 -2
  57. data/lib/semantic_logger/sync_processor.rb +25 -3
  58. data/lib/semantic_logger/test/capture_log_events.rb +2 -2
  59. data/lib/semantic_logger/test/minitest.rb +8 -4
  60. data/lib/semantic_logger/test/rspec.rb +249 -0
  61. data/lib/semantic_logger/utils.rb +83 -4
  62. data/lib/semantic_logger/version.rb +1 -1
  63. data/lib/semantic_logger.rb +9 -0
  64. metadata +17 -8
  65. data/lib/semantic_logger/appender/async_batch.rb +0 -93
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 98c3a3e01f125e81eb58559ca0f7931c55bb787102d89d0c10dd9c9a7ea2e221
4
- data.tar.gz: 8d82c20b77fe2c98773b72ab2483bdfb2d1267c65f9b8102cb2ffba00c141ee9
3
+ metadata.gz: ff43a3438164b6bf70367a7b2806350e65da8762fc6fb4e333a769cdf200e95b
4
+ data.tar.gz: 3d12647aaed6e22b7abc7a4c377c0d0470f00ffee3401d2db6043aece3ce09c1
5
5
  SHA512:
6
- metadata.gz: c014af737549553d82d1d65ac1f46fbb09cefae9cb5aca3d5c39a4bbc180587fea4a65fa6756cad87eb031af52806693ddf11b9c2a4564bb140b1b1261b216c7
7
- data.tar.gz: f0c050cb59d1a3022fbf2b5ca180b644493c8630103e09498e7a9097bbda97df3cb3a28b84f125331196819123cad128f85a142c7952918d9df376acfd1dff69
6
+ metadata.gz: 2893b8e69a4d246c1346e5fc6b20ca6a8fcdc3a29e78a44e4e1c8dae5466971298d9cfcabd736080beef17c2eb68914cb90ddef844bf6afd3ede388850232a90
7
+ data.tar.gz: 944f2cbf7232a4cae3ecee1f67d770d4b6a9306fae810b6045710c6920cc5876a5d56246d0a2605c7e066722df4abba1d8dccc29b43964c677a1bd33296dac73
data/README.md CHANGED
@@ -1,13 +1,41 @@
1
1
  # Semantic Logger
2
2
  [![Gem Version](https://img.shields.io/gem/v/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![Build Status](https://github.com/reidmorrison/semantic_logger/workflows/build/badge.svg)](https://github.com/reidmorrison/semantic_logger/actions?query=workflow%3Abuild) [![Downloads](https://img.shields.io/gem/dt/semantic_logger.svg)](https://rubygems.org/gems/semantic_logger) [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](http://opensource.org/licenses/Apache-2.0) ![](https://img.shields.io/badge/status-Production%20Ready-blue.svg)
3
3
 
4
- Semantic Logger is a feature rich logging framework, and replacement for existing Ruby & Rails loggers.
4
+ Semantic Logger is a high-performance, asynchronous structured logging framework for Ruby
5
+ and Rails.
5
6
 
6
- * https://logger.rocketjob.io/
7
+ It differs from ordinary loggers in two important ways:
8
+
9
+ 1. **It logs structured data, not just strings.** Along with the text message, each log entry can
10
+ carry a payload (any Hash), an exception, a duration, metrics, and tags. That data is preserved
11
+ all the way to the destination, so it stays searchable instead of being flattened into text.
12
+ 2. **It logs asynchronously.** Log events are pushed onto an in-memory queue and written to their
13
+ destinations by a separate background thread, so your application is not blocked while logs are
14
+ written. Semantic Logger can log thousands of lines per second without slowing the application
15
+ down.
16
+
17
+ ```ruby
18
+ require "semantic_logger"
19
+
20
+ SemanticLogger.default_level = :info
21
+ SemanticLogger.add_appender(io: $stdout, formatter: :color)
22
+
23
+ logger = SemanticLogger["MyApp"]
24
+
25
+ # A plain message, plus structured data that stays searchable
26
+ logger.info("Queried users table", duration: 54, result: :ok, table: "users")
27
+ ```
28
+
29
+ When running Rails, use
30
+ [rails_semantic_logger](https://github.com/reidmorrison/rails_semantic_logger) instead, since it
31
+ replaces the Rails default logger with Semantic Logger automatically.
7
32
 
8
33
  ## Documentation
9
34
 
10
- [Semantic Logger Guide](https://logger.rocketjob.io/)
35
+ Start with the [Introduction](https://logger.rocketjob.io/), then the
36
+ [Programmer's Guide](https://logger.rocketjob.io/api.html).
37
+
38
+ * Full guide: [https://logger.rocketjob.io/](https://logger.rocketjob.io/)
11
39
 
12
40
  ## Logging Destinations
13
41
 
@@ -28,6 +56,7 @@ Logging to the following destinations are all supported "out-of-the-box":
28
56
  * UDP
29
57
  * Syslog
30
58
  * CloudWatch Logs
59
+ * OpenTelemetry
31
60
  * Add any existing Ruby logger as another destination.
32
61
  * Roll-your-own
33
62
 
@@ -63,89 +92,16 @@ and are therefore not automatically included by this gem:
63
92
  - Syslog Appender to a remote syslogng server over TCP or UDP: gem 'net_tcp_client'
64
93
  - Splunk Appender: gem 'splunk-sdk-ruby'
65
94
  - Elasticsearch Appender: gem 'elasticsearch'
95
+ - OpenSearch Appender: gem 'opensearch-ruby'
66
96
  - Kafka Appender: gem 'ruby-kafka'
67
97
  - Legacy Sentry Appender: gem 'sentry-raven' (deprecated)
68
98
  - Sentry Appender: gem 'sentry-ruby'
99
+ - OpenTelemetry Appender: gem 'opentelemetry-logs-sdk' (plus an exporter, e.g. 'opentelemetry-exporter-otlp-logs')
69
100
 
70
- ## Upgrading to Semantic Logger v4.9
101
+ ## Upgrading
71
102
 
72
- These changes should not be noticeable by the majority of users of Semantic Logger, since
73
- they are to the internal API. It is possible that advanced users may be using these internal
74
- API's directly.
75
-
76
- This does not affect any calls to the public api `SemanticLogger.add_appender`.
77
-
78
- File and IO are now separate appenders. When creating the File appender explicitly, its arguments
79
- have changed. For example, when requesting an IO stream, it needs to be changed from:
80
-
81
- ~~~ruby
82
- SemanticLogger::Appender::File.new(io: $stderr)
83
- ~~~
84
- to:
85
- ~~~ruby
86
- SemanticLogger::Appender::IO.new($stderr)
87
- ~~~
88
-
89
- Additionally, this needs to be changed from:
90
- ~~~ruby
91
- SemanticLogger::Appender::File.new(file_name: "file.log")
92
- ~~~
93
- to:
94
- ~~~ruby
95
- SemanticLogger::Appender::File.new("file.log")
96
- ~~~
97
-
98
- Rails Semantic Logger, if used, needs to be upgraded to v4.9 when upgrading to Semantic Logger v4.9.
99
-
100
- ## Upgrading to Semantic Logger v4.4
101
-
102
- With some forking frameworks it is necessary to call `reopen` after the fork. With v4.4 the
103
- workaround for Ruby 2.5 crashes is no longer needed.
104
- I.e. Please remove the following line if being called anywhere:
105
-
106
- ~~~ruby
107
- SemanticLogger::Processor.instance.instance_variable_set(:@queue, Queue.new)
108
- ~~~
109
-
110
- ## Upgrading to Semantic Logger v4.0
111
-
112
- The following changes need to be made when upgrading to V4:
113
- - Ruby V2.3 / JRuby V9.1 is now the minimum runtime version.
114
- - Replace calls to Logger#with_payload with SemanticLogger.named_tagged.
115
- - Replace calls to Logger#payload with SemanticLogger.named_tags.
116
- - MongoDB Appender requires Mongo Ruby Client V2 or greater.
117
- - Appenders now write payload data in a seperate :payload tag instead of mixing them
118
- directly into the root elements to avoid name clashes.
119
-
120
- As a result any calls like the following:
121
-
122
- ~~~ruby
123
- logger.debug foo: 'foo', bar: 'bar'
124
- ~~~
125
-
126
- Must be replaced with the following in v4:
127
-
128
- ~~~ruby
129
- logger.debug payload: {foo: 'foo', bar: 'bar'}
130
- ~~~
131
-
132
- Similarly, for measure blocks:
133
-
134
- ~~~ruby
135
- logger.measure_info('How long is the sleep', foo: 'foo', bar: 'bar') { sleep 1 }
136
- ~~~
137
-
138
- Must be replaced with the following in v4:
139
-
140
- ~~~ruby
141
- logger.measure_info('How long is the sleep', payload: {foo: 'foo', bar: 'bar'}) { sleep 1 }
142
- ~~~
143
-
144
- The common log call has not changed, and the payload is still logged directly:
145
-
146
- ~~~ruby
147
- logger.debug('log this', foo: 'foo', bar: 'bar')
148
- ~~~
103
+ See the [Upgrading Guide](https://logger.rocketjob.io/upgrading.html) for instructions on
104
+ upgrading between major versions.
149
105
 
150
106
  ## Install
151
107
 
@@ -165,6 +121,11 @@ SemanticLogger.add_appender(file_name: 'development.log', formatter: :color)
165
121
 
166
122
  If running rails, see: [Semantic Logger Rails](https://logger.rocketjob.io/rails.html)
167
123
 
124
+ ## Contributing
125
+
126
+ Contributions are welcome. See [CONTRIBUTING.md](CONTRIBUTING.md) for how to set up the project, run the
127
+ tests, and an overview of the architecture, including a class diagram.
128
+
168
129
  ## Author
169
130
 
170
131
  [Reid Morrison](https://github.com/reidmorrison)
data/Rakefile CHANGED
@@ -9,8 +9,8 @@ task :gem do
9
9
  end
10
10
 
11
11
  task publish: :gem do
12
- # system "git tag -a v#{SemanticLogger::VERSION} -m 'Tagging #{SemanticLogger::VERSION}'"
13
- # system "git push --tags"
12
+ system "git tag -a v#{SemanticLogger::VERSION} -m 'Tagging #{SemanticLogger::VERSION}'"
13
+ system "git push --tags"
14
14
  system "gem push semantic_logger-#{SemanticLogger::VERSION}.gem"
15
15
  system "rm semantic_logger-#{SemanticLogger::VERSION}.gem"
16
16
  end
@@ -21,4 +21,11 @@ Rake::TestTask.new(:test) do |t|
21
21
  t.warning = false
22
22
  end
23
23
 
24
- task default: :test
24
+ begin
25
+ require "rspec/core/rake_task"
26
+ RSpec::Core::RakeTask.new(:spec)
27
+ rescue LoadError
28
+ # RSpec is only available in the test/development environment.
29
+ end
30
+
31
+ task default: %i[test spec]
@@ -2,28 +2,39 @@ require "forwardable"
2
2
 
3
3
  module SemanticLogger
4
4
  module Appender
5
- # Allow any appender to run asynchronously in a separate thread.
5
+ # Proxy that allows any appender to run asynchronously in a separate thread.
6
+ #
7
+ # The worker thread and the in-memory queue are owned by an internal
8
+ # SemanticLogger::QueueProcessor. This proxy forwards log/flush/close/reopen on to the
9
+ # processor, and forwards the remaining appender methods (name, level, ...) directly to
10
+ # the wrapped appender so they keep executing on the caller's thread.
6
11
  class Async
7
12
  extend Forwardable
8
13
 
9
- attr_accessor :lag_check_interval, :lag_threshold_s
10
- attr_reader :queue, :appender, :max_queue_size
14
+ attr_reader :appender, :processor
11
15
 
12
- # Forward methods that can be called directly
13
- def_delegator :@appender, :name
14
- def_delegator :@appender, :should_log?
15
- def_delegator :@appender, :filter
16
- def_delegator :@appender, :host
17
- def_delegator :@appender, :application
18
- def_delegator :@appender, :environment
19
- def_delegator :@appender, :level
20
- def_delegator :@appender, :level=
21
- def_delegator :@appender, :logger
22
- def_delegator :@appender, :logger=
16
+ # Methods forwarded directly to the wrapped appender (run on the caller's thread).
17
+ def_delegators :@appender,
18
+ :name, :should_log?, :filter, :host, :application, :environment,
19
+ :level, :level=, :logger, :logger=, :console_stream, :console_output?
20
+
21
+ # Methods forwarded to the queue processor that owns the thread and queue.
22
+ # Tuning options (max_queue_size, batch_size, non_blocking, ...) are set once at
23
+ # construction via SemanticLogger.add_appender, so only the values that callers actually
24
+ # read back are re-exposed here. lag_* backs the public SemanticLogger.lag_* API.
25
+ def_delegators :@processor,
26
+ :log, :flush, :close, :thread, :active?, :queue, :max_queue_size,
27
+ :capped?, :non_blocking?, :batch?,
28
+ :lag_check_interval, :lag_check_interval=,
29
+ :lag_threshold_s, :lag_threshold_s=,
30
+ :processed_count, :dropped_count
23
31
 
24
32
  # Appender proxy to allow an existing appender to run asynchronously in a separate thread.
25
33
  #
26
34
  # Parameters:
35
+ # appender: [SemanticLogger::Subscriber]
36
+ # The appender to log to in a separate thread.
37
+ #
27
38
  # max_queue_size: [Integer]
28
39
  # The maximum number of log messages to hold on the queue before blocking attempts to add to the queue.
29
40
  # -1: The queue size is uncapped and will never block no matter how long the queue is.
@@ -36,172 +47,74 @@ module SemanticLogger
36
47
  # lag_check_interval: [Integer]
37
48
  # Number of messages to process before checking for slow logging.
38
49
  # Default: 1,000
39
- def initialize(appender:,
40
- max_queue_size: 10_000,
41
- lag_check_interval: 1_000,
42
- lag_threshold_s: 30)
43
- @appender = appender
44
- @lag_check_interval = lag_check_interval
45
- @lag_threshold_s = lag_threshold_s
46
- @thread = nil
47
- @max_queue_size = max_queue_size
48
- create_queue
49
- thread
50
+ # Note: Not applicable when batch: true.
51
+ #
52
+ # batch: [true|false]
53
+ # Process log messages in batches via the appender's #batch method, instead of one at a time.
54
+ # The appender must implement #batch.
55
+ # Default: false
56
+ #
57
+ # batch_size: [Integer]
58
+ # Maximum number of messages to batch up before sending.
59
+ # Default: 300
60
+ # Note: Only applicable when batch: true.
61
+ #
62
+ # batch_seconds: [Integer]
63
+ # Maximum number of seconds between sending batches.
64
+ # Default: 5
65
+ # Note: Only applicable when batch: true.
66
+ #
67
+ # non_blocking: [true|false]
68
+ # Whether to drop log messages instead of blocking the calling thread when the queue is full.
69
+ # When true and the queue is capped, attempts to add to a full queue return immediately and
70
+ # the message is dropped. The number of dropped messages is logged to the internal logger
71
+ # periodically (see dropped_message_report_seconds). Only applies to a capped queue.
72
+ # Default: false
73
+ #
74
+ # dropped_message_report_seconds: [Integer]
75
+ # When non_blocking is enabled, log the count of dropped messages to the internal logger
76
+ # at most once every this number of seconds.
77
+ # Default: 30
78
+ #
79
+ # async_max_retries: [Integer]
80
+ # Maximum number of consecutive times to restart the worker thread (with a back-off)
81
+ # after it raises an exception while processing messages, before giving up and stopping
82
+ # the thread. The counter resets after any message is processed successfully.
83
+ # -1: Retry indefinitely and never stop the thread (the pre-v5 behaviour).
84
+ # Default: 100
85
+ def initialize(appender:, **args)
86
+ @appender = appender
87
+ @processor = QueueProcessor.start(appender: appender, **args)
50
88
  end
51
89
 
52
- # Re-open appender after a fork
90
+ # Re-open appender after a fork.
53
91
  def reopen
54
- # Workaround CRuby crash on fork by recreating queue on reopen
55
- # https://github.com/reidmorrison/semantic_logger/issues/103
56
- @queue&.close
57
- create_queue
58
-
59
92
  appender.reopen if appender.respond_to?(:reopen)
60
-
61
- @thread&.kill if @thread&.alive?
62
- @thread = Thread.new { process }
63
- end
64
-
65
- # Returns [true|false] if the queue has a capped size.
66
- def capped?
67
- @capped
93
+ processor.reopen
68
94
  end
69
95
 
70
- # Returns [Thread] the worker thread.
96
+ # Returns [Hash] operational statistics for this appender.
71
97
  #
72
- # Starts the worker thread if not running.
73
- def thread
74
- return @thread if @thread&.alive?
75
-
76
- @thread = Thread.new { process }
77
- end
78
-
79
- # Returns true if the worker thread is active
80
- def active?
81
- @thread&.alive?
82
- end
83
-
84
- # Add log message for processing.
85
- def log(log)
86
- queue << log
87
- end
88
-
89
- # Flush all queued log entries disk, database, etc.
90
- # All queued log messages are written and then each appender is flushed in turn.
91
- def flush
92
- submit_request(:flush)
93
- end
94
-
95
- # Close all appenders and flush any outstanding messages.
96
- def close
97
- # TODO: Prevent new close requests once this appender has been closed.
98
- submit_request(:close)
99
- end
100
-
101
- private
102
-
103
- def create_queue
104
- if max_queue_size == -1
105
- @queue = Queue.new
106
- @capped = false
107
- else
108
- @queue = SizedQueue.new(max_queue_size)
109
- @capped = true
110
- end
111
- end
112
-
113
- # Separate thread for batching up log messages before writing.
114
- def process
115
- # This thread is designed to never go down unless the main thread terminates
116
- # or the appender is closed.
117
- Thread.current.name = logger.name
118
- logger.trace "Async: Appender thread active"
119
- begin
120
- process_messages
121
- rescue StandardError => e
122
- # This block may be called after the file handles have been released by Ruby
123
- begin
124
- logger.error("Async: Restarting due to exception", e)
125
- rescue StandardError
126
- nil
127
- end
128
- retry
129
- rescue Exception => e
130
- # This block may be called after the file handles have been released by Ruby
131
- begin
132
- logger.error("Async: Stopping due to fatal exception", e)
133
- rescue StandardError
134
- nil
135
- end
136
- ensure
137
- @thread = nil
138
- # This block may be called after the file handles have been released by Ruby
139
- begin
140
- logger.trace("Async: Thread has stopped")
141
- rescue StandardError
142
- nil
143
- end
144
- end
145
- end
146
-
147
- def process_messages
148
- count = 0
149
- while (message = queue.pop)
150
- if message.is_a?(Log)
151
- appender.log(message)
152
- count += 1
153
- # Check every few log messages whether this appender thread is falling behind
154
- if count > lag_check_interval
155
- check_lag(message)
156
- count = 0
157
- end
158
- else
159
- break unless process_message(message)
160
- end
161
- end
162
- logger.trace "Async: Queue Closed"
163
- end
164
-
165
- # Returns false when message processing should be stopped
166
- def process_message(message)
167
- case message[:command]
168
- when :flush
169
- appender.flush
170
- message[:reply_queue] << true if message[:reply_queue]
171
- when :close
172
- appender.close
173
- message[:reply_queue] << true if message[:reply_queue]
174
- return false
175
- else
176
- logger.warn "Async: Appender thread: Ignoring unknown command: #{message[:command]}"
177
- end
178
- true
179
- end
180
-
181
- def check_lag(log)
182
- diff = Time.now - log.time
183
- return unless diff > lag_threshold_s
184
-
185
- logger.warn "Async: Appender thread has fallen behind by #{diff} seconds with #{queue.size} messages queued up. Consider reducing the log level or changing the appenders"
186
- end
187
-
188
- # Submit command and wait for reply
189
- def submit_request(command)
190
- return false unless active?
191
-
192
- queue_size = queue.size
193
- msg = "Async: Queued log messages: #{queue_size}, running command: #{command}"
194
- if queue_size > 1_000
195
- logger.warn msg
196
- elsif queue_size > 100
197
- logger.info msg
198
- elsif queue_size.positive?
199
- logger.trace msg
200
- end
201
-
202
- reply_queue = Queue.new
203
- queue << {command: command, reply_queue: reply_queue}
204
- reply_queue.pop
98
+ # name: [String] Name of the wrapped appender.
99
+ # async: [true] This appender logs asynchronously via a separate thread.
100
+ # thread_active: [Boolean] Whether the worker thread is currently running.
101
+ # queue_size: [Integer] Number of log messages currently waiting to be written.
102
+ # capped: [Boolean] Whether the queue has a maximum size.
103
+ # max_queue_size: [Integer] Maximum queue size, or nil when uncapped.
104
+ # processed: [Integer] Cumulative number of log messages written since startup.
105
+ # dropped: [Integer] Cumulative number of log messages dropped because the queue
106
+ # was full (only possible when non_blocking is enabled).
107
+ def stats
108
+ {
109
+ name: name,
110
+ async: true,
111
+ thread_active: active? || false,
112
+ queue_size: queue.size,
113
+ capped: capped?,
114
+ max_queue_size: capped? ? max_queue_size : nil,
115
+ processed: processed_count,
116
+ dropped: dropped_count
117
+ }
205
118
  end
206
119
  end
207
120
  end
@@ -54,7 +54,7 @@ module SemanticLogger
54
54
  # Note that currently CloudWatch Logs has 10000 hard limit.
55
55
  # Default: 4000
56
56
  def initialize(
57
- *args,
57
+ *,
58
58
  group:,
59
59
  client_kwargs: {},
60
60
  stream: nil,
@@ -62,8 +62,8 @@ module SemanticLogger
62
62
  create_stream: true,
63
63
  force_flush_interval_seconds: 5,
64
64
  max_buffered_events: 4_000,
65
- **kwargs,
66
- &block
65
+ **,
66
+ &
67
67
  )
68
68
  @group = group
69
69
  @client_kwargs = client_kwargs
@@ -73,7 +73,7 @@ module SemanticLogger
73
73
  @force_flush_interval_seconds = force_flush_interval_seconds
74
74
  @max_buffered_events = max_buffered_events
75
75
 
76
- super(*args, **kwargs, &block)
76
+ super(*, **, &)
77
77
  reopen
78
78
  end
79
79