debug_logging 4.0.2 → 4.0.3

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.
data/RUBOCOP.md ADDED
@@ -0,0 +1,71 @@
1
+ # RuboCop Usage Guide
2
+
3
+ ## Overview
4
+
5
+ A tale of two RuboCop plugin gems.
6
+
7
+ ### RuboCop Gradual
8
+
9
+ This project uses `rubocop_gradual` instead of vanilla RuboCop for code style checking. The `rubocop_gradual` tool allows for gradual adoption of RuboCop rules by tracking violations in a lock file.
10
+
11
+ ### RuboCop LTS
12
+
13
+ This project uses `rubocop-lts` to ensure, on a best-effort basis, compatibility with Ruby >= 1.9.2.
14
+ RuboCop rules are meticulously configured by the `rubocop-lts` family of gems to ensure that a project is compatible with a specific version of Ruby. See: https://rubocop-lts.gitlab.io for more.
15
+
16
+ ## Checking RuboCop Violations
17
+
18
+ To check for RuboCop violations in this project, always use:
19
+
20
+ ```bash
21
+ bundle exec rake rubocop_gradual:check
22
+ ```
23
+
24
+ **Do not use** the standard RuboCop commands like:
25
+ - `bundle exec rubocop`
26
+ - `rubocop`
27
+
28
+ ## Understanding the Lock File
29
+
30
+ The `.rubocop_gradual.lock` file tracks all current RuboCop violations in the project. This allows the team to:
31
+
32
+ 1. Prevent new violations while gradually fixing existing ones
33
+ 2. Track progress on code style improvements
34
+ 3. Ensure CI builds don't fail due to pre-existing violations
35
+
36
+ ## Common Commands
37
+
38
+ - **Check violations**
39
+ - `bundle exec rake rubocop_gradual`
40
+ - `bundle exec rake rubocop_gradual:check`
41
+ - **(Safe) Autocorrect violations, and update lockfile if no new violations**
42
+ - `bundle exec rake rubocop_gradual:autocorrect`
43
+ - **Force update the lock file (w/o autocorrect) to match violations present in code**
44
+ - `bundle exec rake rubocop_gradual:force_update`
45
+
46
+ ## Workflow
47
+
48
+ 1. Before submitting a PR, run `bundle exec rake rubocop_gradual:autocorrect`
49
+ a. or just the default `bundle exec rake`, as autocorrection is a pre-requisite of the default task.
50
+ 2. If there are new violations, either:
51
+ - Fix them in your code
52
+ - Run `bundle exec rake rubocop_gradual:force_update` to update the lock file (only for violations you can't fix immediately)
53
+ 3. Commit the updated `.rubocop_gradual.lock` file along with your changes
54
+
55
+ ## Never add inline RuboCop disables
56
+
57
+ Do not add inline `rubocop:disable` / `rubocop:enable` comments anywhere in the codebase (including specs, except when following the few existing `rubocop:disable` patterns for a rule already being disabled elsewhere in the code). We handle exceptions in two supported ways:
58
+
59
+ - Permanent/structural exceptions: prefer adjusting the RuboCop configuration (e.g., in `.rubocop.yml`) to exclude a rule for a path or file pattern when it makes sense project-wide.
60
+ - Temporary exceptions while improving code: record the current violations in `.rubocop_gradual.lock` via the gradual workflow:
61
+ - `bundle exec rake rubocop_gradual:autocorrect` (preferred; will autocorrect what it can and update the lock only if no new violations were introduced)
62
+ - If needed, `bundle exec rake rubocop_gradual:force_update` (as a last resort when you cannot fix the newly reported violations immediately)
63
+
64
+ In general, treat the rules as guidance to follow; fix violations rather than ignore them. For example, RSpec conventions in this project expect `described_class` to be used in specs that target a specific class under test.
65
+
66
+ ## Benefits of rubocop_gradual
67
+
68
+ - Allows incremental adoption of code style rules
69
+ - Prevents CI failures due to pre-existing violations
70
+ - Provides a clear record of code style debt
71
+ - Enables focused efforts on improving code quality over time
data/SECURITY.md CHANGED
@@ -2,15 +2,20 @@
2
2
 
3
3
  ## Supported Versions
4
4
 
5
- | Version | Supported |
6
- |---------|-----------|
7
- | 4.x | ✅ |
8
- | 3.x | ❌ |
9
- | 2.x | ❌ |
10
- | 1.x | ❌ |
5
+ | Version | Supported |
6
+ |----------|-----------|
7
+ | 1.latest | ✅ |
11
8
 
12
- ## Reporting a Vulnerability
9
+ ## Security contact information
13
10
 
14
- Peter Boling is the primary maintainer of this gem. Please find a way
15
- to [contact him directly](https://railsbling.com/contact) to report the issue. Include as much relevant information as
16
- possible.
11
+ To report a security vulnerability, please use the
12
+ [Tidelift security contact](https://tidelift.com/security).
13
+ Tidelift will coordinate the fix and disclosure.
14
+
15
+ ## Additional Support
16
+
17
+ If you are interested in support for versions older than the latest release,
18
+ please consider sponsoring the project / maintainer @ https://liberapay.com/pboling/donate,
19
+ or find other sponsorship links in the [README].
20
+
21
+ [README]: README.md
data/certs/pboling.pem ADDED
@@ -0,0 +1,27 @@
1
+ -----BEGIN CERTIFICATE-----
2
+ MIIEgDCCAuigAwIBAgIBATANBgkqhkiG9w0BAQsFADBDMRUwEwYDVQQDDAxwZXRl
3
+ ci5ib2xpbmcxFTATBgoJkiaJk/IsZAEZFgVnbWFpbDETMBEGCgmSJomT8ixkARkW
4
+ A2NvbTAeFw0yNTA1MDQxNTMzMDlaFw00NTA0MjkxNTMzMDlaMEMxFTATBgNVBAMM
5
+ DHBldGVyLmJvbGluZzEVMBMGCgmSJomT8ixkARkWBWdtYWlsMRMwEQYKCZImiZPy
6
+ LGQBGRYDY29tMIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAruUoo0WA
7
+ uoNuq6puKWYeRYiZekz/nsDeK5x/0IEirzcCEvaHr3Bmz7rjo1I6On3gGKmiZs61
8
+ LRmQ3oxy77ydmkGTXBjruJB+pQEn7UfLSgQ0xa1/X3kdBZt6RmabFlBxnHkoaGY5
9
+ mZuZ5+Z7walmv6sFD9ajhzj+oIgwWfnEHkXYTR8I6VLN7MRRKGMPoZ/yvOmxb2DN
10
+ coEEHWKO9CvgYpW7asIihl/9GMpKiRkcYPm9dGQzZc6uTwom1COfW0+ZOFrDVBuV
11
+ FMQRPswZcY4Wlq0uEBLPU7hxnCL9nKK6Y9IhdDcz1mY6HZ91WImNslOSI0S8hRpj
12
+ yGOWxQIhBT3fqCBlRIqFQBudrnD9jSNpSGsFvbEijd5ns7Z9ZMehXkXDycpGAUj1
13
+ to/5cuTWWw1JqUWrKJYoifnVhtE1o1DZ+LkPtWxHtz5kjDG/zR3MG0Ula0UOavlD
14
+ qbnbcXPBnwXtTFeZ3C+yrWpE4pGnl3yGkZj9SMTlo9qnTMiPmuWKQDatAgMBAAGj
15
+ fzB9MAkGA1UdEwQCMAAwCwYDVR0PBAQDAgSwMB0GA1UdDgQWBBQE8uWvNbPVNRXZ
16
+ HlgPbc2PCzC4bjAhBgNVHREEGjAYgRZwZXRlci5ib2xpbmdAZ21haWwuY29tMCEG
17
+ A1UdEgQaMBiBFnBldGVyLmJvbGluZ0BnbWFpbC5jb20wDQYJKoZIhvcNAQELBQAD
18
+ ggGBAJbnUwfJQFPkBgH9cL7hoBfRtmWiCvdqdjeTmi04u8zVNCUox0A4gT982DE9
19
+ wmuN12LpdajxZONqbXuzZvc+nb0StFwmFYZG6iDwaf4BPywm2e/Vmq0YG45vZXGR
20
+ L8yMDSK1cQXjmA+ZBKOHKWavxP6Vp7lWvjAhz8RFwqF9GuNIdhv9NpnCAWcMZtpm
21
+ GUPyIWw/Cw/2wZp74QzZj6Npx+LdXoLTF1HMSJXZ7/pkxLCsB8m4EFVdb/IrW/0k
22
+ kNSfjtAfBHO8nLGuqQZVH9IBD1i9K6aSs7pT6TW8itXUIlkIUI2tg5YzW6OFfPzq
23
+ QekSkX3lZfY+HTSp/o+YvKkqWLUV7PQ7xh1ZYDtocpaHwgxe/j3bBqHE+CUPH2vA
24
+ 0V/FwdTRWcwsjVoOJTrYcff8pBZ8r2MvtAc54xfnnhGFzeRHfcltobgFxkAXdE6p
25
+ DVjBtqT23eugOqQ73umLcYDZkc36vnqGxUBSsXrzY9pzV5gGr2I8YUxMqf6ATrZt
26
+ L9nRqA==
27
+ -----END CERTIFICATE-----
@@ -8,7 +8,8 @@ module DebugLogging
8
8
  end
9
9
 
10
10
  def debug_invocation_id_to_s(args: nil, kwargs: nil, start_at: nil, config_proxy: nil)
11
- return "" unless (args || kwargs) && config_proxy
11
+ return "" unless config_proxy
12
+ return "" unless args || kwargs
12
13
 
13
14
  if config_proxy.debug_add_invocation_id
14
15
  time = start_at ? Util.debug_time(start_at) : Time.now
@@ -63,7 +64,8 @@ module DebugLogging
63
64
  end
64
65
 
65
66
  def debug_signature_to_s(args: nil, kwargs: nil, config_proxy: nil) # rubocop:disable Metrics/CyclomaticComplexity
66
- return "" unless (args || kwargs) && config_proxy
67
+ return "" unless config_proxy
68
+ return "" unless args || kwargs
67
69
 
68
70
  printed_args = ""
69
71
 
@@ -86,7 +88,7 @@ module DebugLogging
86
88
  )
87
89
  printed
88
90
  else
89
- other_args.map(&:inspect).join(", ").tap do |x|
91
+ debug_args_to_s(other_args).tap do |x|
90
92
  add_other_args_ellipsis = x.length > config_proxy.debug_args_max_length
91
93
  end[0..(config_proxy.debug_args_max_length)]
92
94
  end
@@ -120,7 +122,7 @@ module DebugLogging
120
122
  )
121
123
  printed
122
124
  else
123
- other_args.map(&:inspect).join(", ").tap do |x|
125
+ debug_args_to_s(other_args).tap do |x|
124
126
  add_other_args_ellipsis = x.length > config_proxy.debug_args_max_length
125
127
  end[0..(config_proxy.debug_args_max_length)]
126
128
  end
@@ -156,11 +158,11 @@ module DebugLogging
156
158
  printed
157
159
  elsif args.length == 1 && args[0].is_a?(Hash)
158
160
  # handle double splat
159
- "**#{args.map(&:inspect).join(", ").tap do |x|
161
+ "**#{debug_args_to_s(args).tap do |x|
160
162
  add_args_ellipsis = x.length > config_proxy.debug_args_max_length
161
163
  end }"[0..(config_proxy.debug_args_max_length)]
162
164
  else
163
- args.map(&:inspect).join(", ").tap do |x|
165
+ debug_args_to_s(args).tap do |x|
164
166
  add_args_ellipsis = x.length > config_proxy.debug_args_max_length
165
167
  end[0..(config_proxy.debug_args_max_length)]
166
168
  end
@@ -187,7 +189,7 @@ module DebugLogging
187
189
 
188
190
  case config_proxy.debug_add_payload
189
191
  when true
190
- payload.inspect
192
+ debug_value_to_s(payload)
191
193
  else
192
194
  printed_payload = ""
193
195
  printed, add_payload_ellipsis = debug_safe_proc(
@@ -204,6 +206,25 @@ module DebugLogging
204
206
 
205
207
  module_function
206
208
 
209
+ def debug_args_to_s(args)
210
+ args.map { |arg| debug_value_to_s(arg) }.join(", ")
211
+ end
212
+
213
+ def debug_value_to_s(value)
214
+ case value
215
+ when Hash
216
+ "{#{value.map { |key, inner_value| "#{debug_hash_key_to_s(key)}: #{debug_value_to_s(inner_value)}" }.join(", ")}}"
217
+ when Array
218
+ "[#{value.map { |inner_value| debug_value_to_s(inner_value) }.join(", ")}]"
219
+ else
220
+ value.inspect
221
+ end
222
+ end
223
+
224
+ def debug_hash_key_to_s(key)
225
+ key.is_a?(Symbol) ? key.to_s : key.inspect
226
+ end
227
+
207
228
  def debug_event_name_to_s(decorated_method: nil)
208
229
  "#{decorated_method}.log"
209
230
  end
@@ -0,0 +1,130 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DebugLogging
4
+ class ColorizedString < String
5
+ FOREGROUND_CODES = {
6
+ black: 30,
7
+ red: 31,
8
+ green: 32,
9
+ yellow: 33,
10
+ blue: 34,
11
+ magenta: 35,
12
+ cyan: 36,
13
+ white: 37,
14
+ light_black: 90,
15
+ light_red: 91,
16
+ light_green: 92,
17
+ light_yellow: 93,
18
+ light_blue: 94,
19
+ light_magenta: 95,
20
+ light_cyan: 96,
21
+ light_white: 97,
22
+ default: 39,
23
+ }.freeze
24
+ BACKGROUND_CODES = FOREGROUND_CODES.transform_values { |code| code + 10 }.merge(default: 49).freeze
25
+ FORMAT_CODES = {
26
+ bold: 1,
27
+ italic: 3,
28
+ underline: 4,
29
+ blink: 5,
30
+ reverse_color: 7,
31
+ conceal: 8,
32
+ hide: 8,
33
+ strikethrough: 9,
34
+ double_underline: 21,
35
+ }.freeze
36
+
37
+ class << self
38
+ def [](value)
39
+ new(value.to_s)
40
+ end
41
+ end
42
+
43
+ def initialize(value, foreground: nil, background: nil, formats: [])
44
+ @raw = value.to_s
45
+ @foreground = foreground
46
+ @background = background
47
+ @formats = formats.dup
48
+ super(render)
49
+ end
50
+
51
+ def colorize(color = nil, options = {})
52
+ options = color if color.is_a?(Hash)
53
+ foreground = options.fetch(:color, nil) || options.fetch("color", nil)
54
+ foreground ||= color unless color.is_a?(Hash)
55
+ background = options.fetch(:background, nil) || options.fetch("background", nil)
56
+ formats = Array(options[:mode]) + Array(options[:modes])
57
+
58
+ self.class.new(
59
+ @raw,
60
+ foreground: foreground ? normalized_color(foreground) : @foreground,
61
+ background: background ? normalized_color(background) : @background,
62
+ formats: merge_formats(formats),
63
+ )
64
+ end
65
+
66
+ def colorized?
67
+ @foreground || @background || @formats.any?
68
+ end
69
+
70
+ def uncolorize
71
+ @raw.dup
72
+ end
73
+
74
+ FOREGROUND_CODES.each_key do |color|
75
+ next if color == :default
76
+
77
+ define_method(color) do
78
+ colorize(color)
79
+ end
80
+
81
+ define_method(:"on_#{color}") do
82
+ colorize(background: color)
83
+ end
84
+ end
85
+ alias_method :on_gray, :on_light_black
86
+ alias_method :on_grey, :on_light_black
87
+
88
+ FORMAT_CODES.each_key do |format|
89
+ define_method(format) do
90
+ self.class.new(@raw, foreground: @foreground, background: @background, formats: merge_formats([format]))
91
+ end
92
+ end
93
+
94
+ private
95
+
96
+ def background_code
97
+ BACKGROUND_CODES.fetch(@background, 49)
98
+ end
99
+
100
+ def foreground_code
101
+ FOREGROUND_CODES.fetch(@foreground, 39)
102
+ end
103
+
104
+ def style_codes
105
+ format_codes = @formats.map { |format| FORMAT_CODES.fetch(format) }
106
+ format_codes = [0] if format_codes.empty?
107
+ [*format_codes, foreground_code, background_code]
108
+ end
109
+
110
+ def normalized_color(color)
111
+ color.to_s.tr(" ", "_").downcase.to_sym
112
+ end
113
+
114
+ def merge_formats(formats)
115
+ normalized_formats = formats.filter_map do |format|
116
+ normalized = format.to_sym
117
+ normalized if FORMAT_CODES.key?(normalized)
118
+ end
119
+ @formats | normalized_formats
120
+ end
121
+
122
+ def render
123
+ return @raw.dup unless colorized?
124
+
125
+ "\e[#{style_codes.join(";")}m#{@raw}\e[0m"
126
+ end
127
+ end
128
+ end
129
+
130
+ ColorizedString = DebugLogging::ColorizedString unless Object.const_defined?(:ColorizedString)
@@ -1,6 +1,7 @@
1
1
  module DebugLogging
2
2
  class Configuration
3
3
  include Constants
4
+
4
5
  # For reference, log levels as integers mapped to symbols:
5
6
  # LEVELS = { 0 => :debug, 1 => :info, 2 => :warn, 3 => :error, 4 => :fatal, 5 => :unknown }
6
7
  attr_accessor(*CONFIG_ATTRS)
@@ -2,15 +2,17 @@
2
2
  # License: https://creativecommons.org/licenses/by-sa/4.0/
3
3
  module DebugLogging
4
4
  module Finalize
5
- def self.extended(obj)
6
- TracePoint.trace(:end) do |t|
7
- if obj == t.self
8
- if obj.respond_to?(:debug_finalize)
9
- obj.debug_finalize
10
- else
11
- warn("#{obj} does not define a debug_finalize")
5
+ class << self
6
+ def extended(obj)
7
+ TracePoint.trace(:end) do |t|
8
+ if obj == t.self
9
+ if obj.respond_to?(:debug_finalize)
10
+ obj.debug_finalize
11
+ else
12
+ warn("#{obj} does not define a debug_finalize")
13
+ end
14
+ t.disable
12
15
  end
13
- t.disable
14
16
  end
15
17
  end
16
18
  end
@@ -7,36 +7,43 @@ module DebugLogging
7
7
  extend DebugLogging::ArgumentPrinter
8
8
 
9
9
  class << self
10
- attr_accessor :event
11
- end
12
- attach_to :log
10
+ def event
11
+ @@event
12
+ end
13
13
 
14
- EVENT_FORMAT_STRING = "%<name>s (%<duration>.3f secs) start=%<time>s end=%<end>s args=%<args>s payload=%<payload>s"
14
+ def event=(value)
15
+ @@event = value
16
+ end
15
17
 
16
- def self.log_event(event)
17
- @event = event
18
- if event.payload && event.payload[:exception_object]
19
- exception = event.payload[:exception_object]
20
- "#{event.name} [ERROR] : \n#{exception.class} : #{exception.message}\n" + exception.backtrace.join("\n")
21
- else
22
- format(EVENT_FORMAT_STRING, event_to_format_options(event))
18
+ def log_event(event)
19
+ self.event = event
20
+ if event.payload && event.payload[:exception_object]
21
+ exception = event.payload[:exception_object]
22
+ "#{event.name} [ERROR] : \n#{exception.class} : #{exception.message}\n" + exception.backtrace.join("\n")
23
+ else
24
+ format(EVENT_FORMAT_STRING, event_to_format_options(event))
25
+ end
23
26
  end
24
- end
25
27
 
26
- # @param [ActiveSupport::Notifications::Event]
27
- # @return [Hash]
28
- def self.event_to_format_options(event)
29
- args = event.payload[:debug_args]
30
- config_proxy = event.payload[:config_proxy]
31
- payload = event.payload.reject { |k, _| EXCLUDE_FROM_PAYLOAD.include?(k) }
32
- {
33
- name: event.name,
34
- duration: Rational(event.duration, 1000).to_f,
35
- time: debug_event_time_to_s(event.time),
36
- end: debug_event_time_to_s(event.end),
37
- args: debug_signature_to_s(args: args, config_proxy: config_proxy),
38
- payload: debug_payload_to_s(payload: payload, config_proxy: config_proxy),
39
- }
28
+ # @param [ActiveSupport::Notifications::Event]
29
+ # @return [Hash]
30
+ def event_to_format_options(event)
31
+ args = event.payload[:debug_args]
32
+ config_proxy = event.payload[:config_proxy]
33
+ payload = event.payload.reject { |k, _| EXCLUDE_FROM_PAYLOAD.include?(k) }
34
+ {
35
+ name: event.name,
36
+ duration: Rational(event.duration, 1000).to_f,
37
+ time: debug_event_time_to_s(event.time),
38
+ end: debug_event_time_to_s(event.end),
39
+ args: debug_signature_to_s(args: args, config_proxy: config_proxy),
40
+ payload: debug_payload_to_s(payload: payload, config_proxy: config_proxy),
41
+ }
42
+ end
40
43
  end
44
+
45
+ attach_to :log
46
+
47
+ EVENT_FORMAT_STRING = "%<name>s (%<duration>.3f secs) start=%<time>s end=%<end>s args=%<args>s payload=%<payload>s"
41
48
  end
42
49
  end
@@ -1,5 +1,8 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module DebugLogging
2
4
  module Version
3
- VERSION = "4.0.2"
5
+ VERSION = "4.0.3"
4
6
  end
7
+ VERSION = Version::VERSION # Traditional Constant Location
5
8
  end
data/lib/debug_logging.rb CHANGED
@@ -1,10 +1,14 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Std Lib
2
4
  require "logger"
3
5
  require "digest"
4
6
 
5
7
  # External gems
6
8
  require "version_gem"
7
- require "colorized_string"
9
+ require_relative "debug_logging/version"
10
+
11
+ require "debug_logging/colorized_string"
8
12
 
9
13
  # This gem
10
14
  require "debug_logging/constants"
@@ -116,7 +120,13 @@ module DebugLogging
116
120
 
117
121
  #### CONFIG ####
118
122
  class << self
119
- attr_accessor :debug_logging_configuration
123
+ def debug_logging_configuration
124
+ @@debug_logging_configuration
125
+ end
126
+
127
+ def debug_logging_configuration=(config)
128
+ @@debug_logging_configuration = config
129
+ end
120
130
  end
121
131
 
122
132
  module ConfigClassMethods
@@ -0,0 +1,6 @@
1
+ module DebugLogging
2
+ module Version
3
+ VERSION: String
4
+ end
5
+ VERSION: String
6
+ end
data.tar.gz.sig CHANGED
Binary file