lorekeeper 2.3.1 → 2.4.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 92b989dbf8ed93f0ef8a14a4c38c96942e34fdfb11c09048bbbe4077c4c0e493
4
- data.tar.gz: 994f2c997387e2bf60e991b858a7683de6e0e53f21a7868b42844606e2d93a30
3
+ metadata.gz: 8099634bb3a3f3d4d348737b0c9634a3a70743c1d868ebec42c194865df7a13c
4
+ data.tar.gz: c216efb9f7f6c2e06c357aee59d1f0ad8299445c5becc0d8fc4f2d444e5193ec
5
5
  SHA512:
6
- metadata.gz: 2626986445dd5884ed83d2853e8654be86eced615ab9b82aab90bae74c3e9e6a2e081acb5c8a3afe27143213cc588f331cd35fb5356c0bab5c196c15d2d19052
7
- data.tar.gz: 28e4416df69d092dffe46ed3317c33ef0e4d893c3484425d45cf7a4ae8bcfa0768f540dbee6969bc92836008ce71c51d029a3f8ee6fab297228d9fa16a74ffdf
6
+ metadata.gz: 93af9f7d3142bdc8166a14e2324b71fe3e51c3f150ea2fccee8557fc2d17b92517b3d6214e8021ed86bdbf632bed836b12027bf438f4bba0099ef1bbaed32e63
7
+ data.tar.gz: d81128b6905c1f70e7946bf7be63bf35923d40056d9c9ab7274397b7ff8726da582109f83c0c2905768c0c694ac48c2fa8574dd894f10a0b60d6c3b0ac28dfbb
@@ -14,7 +14,7 @@ jobs:
14
14
  runs-on: ubuntu-latest
15
15
  strategy:
16
16
  matrix:
17
- ruby-version: ['2.7', '3.0', '3.1']
17
+ ruby-version: ['2.7', '3.0', '3.1', '3.2']
18
18
 
19
19
  steps:
20
20
  - uses: actions/checkout@v2
@@ -23,6 +23,8 @@ jobs:
23
23
  with:
24
24
  ruby-version: ${{ matrix.ruby-version }}
25
25
  bundler-cache: true # runs 'bundle install' and caches installed gems automatically
26
+ - name: Run rubocop
27
+ run: bundle exec rubocop
26
28
  - name: Run tests
27
29
  run: bundle exec rspec
28
30
  - name: Run benchmark
data/.rubocop.yml CHANGED
@@ -1,6 +1,42 @@
1
- Metrics/LineLength:
2
- Max: 120
3
- # https://github.com/rubocop/rubocop/blob/20990ed3831589c0d9f202107b1b580ead8ef2c5/lib/rubocop/cop/style/single_line_methods.rb#L11
1
+ require:
2
+ - rubocop-performance
3
+
4
+ inherit_gem:
5
+ rubocop-mdsol: rubocop.yml
6
+
7
+ AllCops:
8
+ Exclude:
9
+ - '*gemspec'
10
+ # NOTE: Excludes vendor from linting. Needed by GitHub Actions.
11
+ # - https://github.com/rubocop/rubocop/issues/9832#issuecomment-873398952
12
+ #
13
+ - 'vendor/bundle/**/*'
14
+
15
+ Lint/ConstantDefinitionInBlock:
16
+ Exclude:
17
+ - 'spec/**/*'
18
+
19
+ Layout/ArgumentAlignment:
20
+ EnforcedStyle: with_fixed_indentation
21
+
22
+ Layout/FirstHashElementIndentation:
23
+ EnforcedStyle: consistent
24
+
25
+ Metrics/ParameterLists:
26
+ CountKeywordArgs: false
27
+
4
28
  # TODO: add "EnforcedStyle: allow_single_line" once all rubys are > 3.0 to autocorrect all single-line methods to endless
29
+ # https://github.com/rubocop/rubocop/blob/20990ed3831589c0d9f202107b1b580ead8ef2c5/lib/rubocop/cop/style/single_line_methods.rb#L11
30
+ #
5
31
  Style/SingleLineMethods:
6
32
  Enabled: false
33
+
34
+ Style/MissingRespondToMissing:
35
+ Enabled: false
36
+
37
+ Style/FrozenStringLiteralComment:
38
+ Enabled: true
39
+
40
+ Style/StringLiterals:
41
+ Enabled: true
42
+ EnforcedStyle: single_quotes
data/CHANGELOG.md CHANGED
@@ -1,3 +1,13 @@
1
+ # 2.4.0
2
+ * Add `#with_level` method support added to the stdlib's Logger in [#85](https://github.com/ruby/logger/issues/85)
3
+ * Support symbol log level setting
4
+
5
+ # 2.3.2
6
+ * Ensure additional fields are reset after logging
7
+ * Let Oj fallback to :object mode for non-representable data
8
+ * Fix SimpleLogger to handle non-String log messages
9
+ * Run RuboCop checks on build and fix RuboCop offenses
10
+
1
11
  # 2.3.1
2
12
  * Fix MultiLogger to not raise ArgumentError
3
13
 
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in lorekeeper.gemspec
data/Rakefile CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'benchmark'
2
4
  require 'tempfile'
3
5
  require 'securerandom'
@@ -5,7 +7,7 @@ require 'benchmark/ips'
5
7
  require 'byebug'
6
8
  require 'rbtrace'
7
9
 
8
- $LOAD_PATH.unshift(File.expand_path('../lib', __FILE__))
10
+ $LOAD_PATH.unshift(File.expand_path('lib', __dir__))
9
11
  $LOAD_PATH.uniq!
10
12
 
11
13
  require 'lorekeeper'
@@ -26,7 +28,7 @@ end
26
28
 
27
29
  def create_simple_logger
28
30
  logfile = Tempfile.new('my_test_log.log')
29
- ::Logger.new(logfile.path)
31
+ Logger.new(logfile.path)
30
32
  end
31
33
 
32
34
  # This task is used to help development of Lorekeeper. Use together with rbtrace
data/bin/console CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'bundler/setup'
4
5
  require 'lorekeeper'
data/bin/setup CHANGED
File without changes
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'logger'
4
+ require 'fiber'
4
5
 
5
6
  module Lorekeeper
6
7
  # Very simple, very fast logger
7
8
  class FastLogger
8
- include ::Logger::Severity # contains the levels constants: DEBUG, ERROR, etc.
9
- attr_accessor :level # Current level, default: DEBUG
10
- attr_accessor :formatter # Just for compatibility with Logger, not used
9
+ include ::Logger::Severity # contains the levels constants: DEBUG, ERROR, etc.
10
+ attr_accessor :formatter # Just for compatibility with Logger, not used
11
11
 
12
12
  def debug?; level <= DEBUG; end
13
13
  def info?; level <= INFO; end
@@ -19,14 +19,37 @@ module Lorekeeper
19
19
  @level = DEBUG
20
20
  @iodevice = LogDevice.new(file)
21
21
  @file = file # We only keep this so we can inspect where we are sending the logs
22
+ @level_override = {}
22
23
  end
23
24
 
24
- LOGGING_METHODS = [
25
- :debug,
26
- :info,
27
- :warn,
28
- :error,
29
- :fatal
25
+ def level
26
+ @level_override[Fiber.current] || @level
27
+ end
28
+
29
+ def level=(severity)
30
+ @level = coerce(severity)
31
+ end
32
+
33
+ def with_level(severity)
34
+ prev = level
35
+ @level_override[Fiber.current] = coerce(severity)
36
+ begin
37
+ yield
38
+ ensure
39
+ if prev
40
+ @level_override[Fiber.current] = prev
41
+ else
42
+ @level_override.delete(Fiber.current)
43
+ end
44
+ end
45
+ end
46
+
47
+ LOGGING_METHODS = %i[
48
+ debug
49
+ info
50
+ warn
51
+ error
52
+ fatal
30
53
  ].freeze
31
54
 
32
55
  METHOD_SEVERITY_MAP = {
@@ -55,8 +78,9 @@ module Lorekeeper
55
78
 
56
79
  # This is part of the standard Logger API, we need this to be compatible
57
80
  def add(severity, message_param = nil, progname = nil, &block)
58
- return true if severity < @level
59
- message = (block && block.call) || message_param || progname
81
+ return true if severity < level
82
+
83
+ message = block&.call || message_param || progname
60
84
  log_data(severity, message.freeze)
61
85
  end
62
86
 
@@ -65,12 +89,12 @@ module Lorekeeper
65
89
  # To avoid needing to monkey-patch Lorekeeper just to get this method, we are adding a simple
66
90
  # non-functional version here.
67
91
  def silence_logger(&block)
68
- yield if block_given?
92
+ yield if block
69
93
  end
70
94
 
71
95
  # activerecord-session_store v2 is now simply calling silence instead of silence_logger
72
96
  def silence(&block)
73
- yield if block_given?
97
+ yield if block
74
98
  end
75
99
 
76
100
  # inherited classes probably want to reimplement this
@@ -82,7 +106,11 @@ module Lorekeeper
82
106
  @iodevice.write(message)
83
107
  end
84
108
 
85
- private
109
+ def coerce(severity)
110
+ return severity if severity.is_a?(Integer)
111
+
112
+ METHOD_SEVERITY_MAP[severity] || raise(ArgumentError, "invalid log level: #{severity}")
113
+ end
86
114
 
87
115
  require 'monitor'
88
116
  # Mutex to avoid broken lines when multiple threads access the log file
@@ -110,11 +138,12 @@ module Lorekeeper
110
138
  def to_iodevice(file)
111
139
  return nil unless file
112
140
 
113
- iodevice = if file.respond_to?(:write) && file.respond_to?(:close)
114
- file
115
- else
116
- open_logfile(file)
117
- end
141
+ iodevice =
142
+ if file.respond_to?(:write) && file.respond_to?(:close)
143
+ file
144
+ else
145
+ open_logfile(file)
146
+ end
118
147
 
119
148
  iodevice.sync = true if iodevice.respond_to?(:sync=)
120
149
  iodevice
@@ -132,5 +161,7 @@ module Lorekeeper
132
161
  open_logfile(filename)
133
162
  end
134
163
  end
164
+
165
+ private_constant :LogDeviceMutex, :LogDevice
135
166
  end
136
167
  end
@@ -28,13 +28,14 @@ module Lorekeeper
28
28
  # Delegates methods to the existing Logger instance
29
29
  # We are extending the logger API with methods error_with_data, etc
30
30
  LOGGING_METHODS.each do |method_name|
31
- define_method "#{method_name}_with_data", ->(message_param = nil, data = {}, &block) do
31
+ define_method "#{method_name}_with_data", ->(message_param = nil, data = {}, &block) {
32
32
  return true if METHOD_SEVERITY_MAP[method_name] < @level
33
+
33
34
  extra_fields = { DATA => (data || {}) }
34
- with_extra_fields(extra_fields) { # Using do/end here only valid on Ruby>= 2.3
35
+ with_extra_fields(extra_fields) do
35
36
  add(METHOD_SEVERITY_MAP[method_name], message_param, nil, &block)
36
- }
37
- end
37
+ end
38
+ }
38
39
  end
39
40
 
40
41
  def add_thread_unsafe_fields(fields)
@@ -65,7 +66,7 @@ module Lorekeeper
65
66
  # By default message comes from exception.message
66
67
  # Optional and named parameters to overwrite message, level and add data
67
68
  def exception(exception, custom_message = nil, custom_data = nil, custom_level = :error,
68
- message: nil, data: nil, level: nil) # Backwards compatible named params
69
+ message: nil, data: nil, level: nil) # Backwards compatible named params
69
70
 
70
71
  param_level = level || custom_level
71
72
  param_data = data || custom_data
@@ -95,11 +96,21 @@ module Lorekeeper
95
96
  end
96
97
 
97
98
  def write(message)
98
- super(Oj.dump(message, mode: :compat, cache_keys: true, cache_str: 5) << "\n")
99
+ super(json_message(message) << "\n")
99
100
  end
100
101
 
101
102
  private
102
103
 
104
+ def json_message(message)
105
+ Oj.dump(message, mode: :compat, cache_keys: true, cache_str: 5)
106
+ rescue JSON::GeneratorError
107
+ begin
108
+ Oj.dump(message)
109
+ rescue => e
110
+ Oj.dump(MESSAGE => e.message)
111
+ end
112
+ end
113
+
103
114
  # Some instrumentation libraries pollute the stacktrace and create a large output which may
104
115
  # cause problems with certain logging backends.
105
116
  # Hardcording newrelic, active_support/callbacks and zipkin-tracer now here.
@@ -130,12 +141,13 @@ module Lorekeeper
130
141
  def with_extra_fields(fields)
131
142
  state[:extra_fields] = fields
132
143
  yield
144
+ ensure
133
145
  state[:extra_fields] = {}
134
146
  end
135
147
 
136
148
  def remove_invalid_fields(fields)
137
149
  fields.delete_if do |_, v|
138
- v.nil? || v.respond_to?(:empty?) && v.empty?
150
+ v.nil? || (v.respond_to?(:empty?) && v.empty?)
139
151
  end
140
152
  end
141
153
 
@@ -143,10 +155,10 @@ module Lorekeeper
143
155
  current_state = state # Accessing state is slow. Do it only once per call.
144
156
  # merging is slow, we do not want to merge with empty hash if possible
145
157
  fields_to_log = if current_state[:extra_fields].empty?
146
- current_state[:base_fields]
147
- else
148
- current_state[:base_fields].merge(current_state[:extra_fields])
149
- end
158
+ current_state[:base_fields]
159
+ else
160
+ current_state[:base_fields].merge(current_state[:extra_fields])
161
+ end
150
162
 
151
163
  fields_to_log[MESSAGE] = message
152
164
  fields_to_log[TIMESTAMP] = Time.now.utc.strftime(DATE_FORMAT)
@@ -28,6 +28,7 @@ module Lorekeeper
28
28
  # \e[colorm sets a color \e[0m resets all properties
29
29
  def log_data(severity, message)
30
30
  color = SEVERITY_TO_COLOR_MAP[severity]
31
+ message = message.to_s
31
32
  write("\e[#{color}m#{message.gsub('\n', "\n").gsub('\t', "\t")}\e[0m\n")
32
33
  end
33
34
 
@@ -37,22 +38,28 @@ module Lorekeeper
37
38
 
38
39
  # Extending the logger API with methods error_with_data, etc
39
40
  LOGGING_METHODS.each do |method_name|
40
- define_method "#{method_name}_with_data", ->(message_param = nil, data = {}, &block) do
41
+ define_method "#{method_name}_with_data", ->(message_param = nil, data = {}) {
41
42
  return true if METHOD_SEVERITY_MAP[method_name] < @level
43
+
42
44
  log_data(METHOD_SEVERITY_MAP[method_name], "#{message_param}, data: #{data}")
43
- end
45
+ }
44
46
  end
45
47
 
46
48
  # To not raise NoMethodError for the methods defined in JSONLogger
47
49
  def current_fields(*); end
50
+
48
51
  def state(*); end
52
+
49
53
  def add_thread_unsafe_fields(*); end
54
+
50
55
  def remove_thread_unsafe_fields(*); end
56
+
51
57
  def add_fields(*); end
58
+
52
59
  def remove_fields(*); end
53
60
 
54
61
  def exception(exception, custom_message = nil, custom_data = nil, custom_level = :error,
55
- message: nil, data: nil, level: nil)
62
+ message: nil, data: nil, level: nil)
56
63
 
57
64
  param_level = level || custom_level
58
65
  param_data = data || custom_data
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Lorekeeper
4
- VERSION = '2.3.1'
4
+ VERSION = '2.4.0'
5
5
  end
data/lorekeeper.gemspec CHANGED
@@ -34,4 +34,6 @@ Gem::Specification.new do |spec|
34
34
  spec.add_development_dependency 'rbtrace', '~> 0.4'
35
35
  spec.add_development_dependency 'simplecov', '~> 0.16'
36
36
  spec.add_development_dependency 'mutant-rspec', '~> 0.8'
37
+ spec.add_development_dependency 'rubocop-mdsol', '~> 0.3'
38
+ spec.add_development_dependency 'rubocop-performance', '~> 1.14'
37
39
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: lorekeeper
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.3.1
4
+ version: 2.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jordi Polo
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-08-18 00:00:00.000000000 Z
11
+ date: 2023-04-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: oj
@@ -176,6 +176,34 @@ dependencies:
176
176
  - - "~>"
177
177
  - !ruby/object:Gem::Version
178
178
  version: '0.8'
179
+ - !ruby/object:Gem::Dependency
180
+ name: rubocop-mdsol
181
+ requirement: !ruby/object:Gem::Requirement
182
+ requirements:
183
+ - - "~>"
184
+ - !ruby/object:Gem::Version
185
+ version: '0.3'
186
+ type: :development
187
+ prerelease: false
188
+ version_requirements: !ruby/object:Gem::Requirement
189
+ requirements:
190
+ - - "~>"
191
+ - !ruby/object:Gem::Version
192
+ version: '0.3'
193
+ - !ruby/object:Gem::Dependency
194
+ name: rubocop-performance
195
+ requirement: !ruby/object:Gem::Requirement
196
+ requirements:
197
+ - - "~>"
198
+ - !ruby/object:Gem::Version
199
+ version: '1.14'
200
+ type: :development
201
+ prerelease: false
202
+ version_requirements: !ruby/object:Gem::Requirement
203
+ requirements:
204
+ - - "~>"
205
+ - !ruby/object:Gem::Version
206
+ version: '1.14'
179
207
  description: Opinionated logger which outputs messages in JSON format
180
208
  email:
181
209
  - mumismo@gmail.com
@@ -205,7 +233,7 @@ homepage: https://github.com/JordiPolo/lorekeeper
205
233
  licenses:
206
234
  - MIT
207
235
  metadata: {}
208
- post_install_message:
236
+ post_install_message:
209
237
  rdoc_options: []
210
238
  require_paths:
211
239
  - lib
@@ -220,8 +248,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
220
248
  - !ruby/object:Gem::Version
221
249
  version: '0'
222
250
  requirements: []
223
- rubygems_version: 3.2.15
224
- signing_key:
251
+ rubygems_version: 3.0.3.1
252
+ signing_key:
225
253
  specification_version: 4
226
254
  summary: Very fast JSON logger
227
255
  test_files: []