debug_me 1.0.2 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 03f8c0541fab13dc5ea656fdd5ef697075132bb00a4662345d4d27f3f935bc99
4
+ data.tar.gz: 0d1d53bbedf84a6d9e17fcccb1565eaecd25ff0fa58ce09daeafb7386482999b
5
+ SHA512:
6
+ metadata.gz: 6531b542b0b28d5dd0d5b0dee66b3e15d316a0ee05b54be0dedfb1a38f7a78e1cf9ba366404dd2a5d8867e5bb35af7add5254b1a58187a5be610b0f750b1ad24
7
+ data.tar.gz: 36df84f99c1ab56ea168a7e693904244cf2b5c46660da6326e0649c5cdf5685190eb01155f1cbee548914babbbe02e9726ef6418de67e490a9a9f75d387c30fd
data/README.md CHANGED
@@ -1,13 +1,24 @@
1
1
  # DebugMe
2
2
 
3
- This thing is pretty old. There are much better
3
+ A tool to print the labeled value of variables.
4
+
5
+ This thing is pretty old; but, so am I. Even with the gray
6
+ in our hair we still do the job.
7
+
8
+ There are much more complex/comprehensive
4
9
  ways of debugging in a complex application. But,
5
10
  you know, I keep returning to this little method
6
11
  time after time. I guess that marks me as a geezer.
7
12
 
8
- A tool to print the labeled value of variables.
9
13
 
10
- Works with local, instance and class variables.
14
+ DebugMe::debug_me(){} works with local, instance and class variables.
15
+
16
+ ## Recent Changes
17
+
18
+ * 1.1.0 Changes the output formatting w/r/t the use of levels option; add :backtrace option for full backtrace
19
+ * 1.0.6 Added support for variable backtrack length via the :levels option
20
+ * 1.0.5 Added support for an instance of a Logger class.
21
+ * 1.0.4 Added :strftime to the options; changed the default format from decimal seconds since epic to something that is more easy comprehend on a clock.
11
22
 
12
23
  ## Installation
13
24
 
@@ -35,6 +46,11 @@ debug_me # Prints only the header banner consisting of tag, method name, file na
35
46
 
36
47
  debug_me('INFO') # Also prints only the header but with a different tag
37
48
 
49
+ debug_me(levels: 5) # Along with the header, show the call stack back this many levels
50
+ debug_me{:backtrace} # show the entire call stack
51
+ debug_me{[ :backtrace ]} will # show the entire call stack
52
+ debug_me(levels: 5){[ :backtrace ]} # will only show the first 5 levels of the backtrace - ie. the levels parameter supersedes :backtrace
53
+
38
54
  debug_me {} # prints the default header and __ALL__ variables
39
55
 
40
56
  debug_me {:just_this_variable} # prints the default header and the value of only one specific variable
@@ -45,9 +61,9 @@ debug_me { [:this_one, :that_one, :that_other_one] } # prints default header and
45
61
  # Each element of the array is 'eval'ed with the context binding of the caller
46
62
  debug_me(){[ :my_var, 'my_complex_var_or_method[my_var]' ]}
47
63
 
48
- debug_me(:header => false) {} # disables the printing of the header; prints all variables
64
+ debug_me(header: false) {} # disables the printing of the header; prints all variables
49
65
 
50
- debug_me(:tag => 'MyTag', :header => false) {} # disables header, sets different tag, prints all variables
66
+ debug_me(tag: 'MyTag', :header => false) {} # disables header, sets different tag, prints all variables
51
67
 
52
68
  debug_me('=== LOOK ===') {} # changes the tag and prints all variables with a header line
53
69
 
@@ -55,8 +71,140 @@ debug_me('=== LOOK ===') {:@foo} # changes the tag, prints a header line and a s
55
71
 
56
72
  debug_me('=== LOOK ===') {:@@foo} # changes the tag, prints a header line and a specific class variable
57
73
 
58
- debug_me(:ivar => false, :cvar => false) {} # print only the local variables with the default tag and a header line
74
+ debug_me(ivar: false, cvar: false) {} # print only the local variables with the default tag and a header line
75
+
76
+ ```
77
+
78
+ Most of the examples above use symbols to designate the variables that you want
79
+ to be shown with their name as a label. You can also use strings. With strings
80
+ you are not limited to just variables. Consider these examples:
81
+
82
+ ```ruby
83
+ debug_me {[ 'some_array.size', 'SomeDatabaseModel.count' ]}
84
+
85
+ # What a backtrace with your variables?
86
+
87
+ debug_me {[
88
+ :my_variable,
89
+ 'some_hash.keys.reject{|k| k.to_s.start_with?('A')}',
90
+ 'caller' ]} # yes, caller is a kernel method that will give a backtrace
91
+
92
+ # You can also get into trouble so be careful. The symbols and strings
93
+ # are evaluated in the context of the caller. Within the string any
94
+ # command or line of code can be given. SO DO NOT try to use
95
+ # something silly like debug_me{ 'system("rm -fr /")'}
96
+
97
+ ```
98
+
99
+ ## Default Options
100
+
101
+ The default options is a global constant `DebugMeDefaultOptions` that is outside of the `DebugMe` name space. I did that so that if you do `include DebugMe` to make access to the method easier you could still have the constant with a function specific name that would be outside of anything that you may have already coded in you program.
102
+
103
+ Notice that this constant is outside of the DebugMe's module namespace.
59
104
 
105
+ ```ruby
106
+ DebugMeDefaultOptions = {
107
+ tag: 'DEBUG', # A tag to prepend to each output line
108
+ time: true, # Include a time-stamp in front of the tag
109
+ strftime: '%Y-%m-%d %H:%M:%S.%6N', # timestamp format
110
+ header: true, # Print a header string before printing the variables
111
+ levels: 0, # Number of additional backtrack entries to display
112
+ skip1: false, # skip 1 blank line in front of a new output block
113
+ skip2: false, # skip 2 blank lines in front of a new output block
114
+ lvar: true, # Include local variables
115
+ ivar: true, # Include instance variables in the output
116
+ cvar: true, # Include class variables in the output
117
+ cconst: true, # Include class constants
118
+ logger: nil, # Pass in a logger class instance like Rails.logger
119
+ file: $stdout # The output file
120
+ }
121
+ ```
122
+
123
+ If you want the output of the method to always go to STDERR then do this:
124
+
125
+ ```ruby
126
+ require 'debug_me'
127
+ DebugMeDefaultOptions[:file] = $stderr # or STDERR
128
+ ```
129
+ If you want the `debug_me` output to go to a real file:
130
+
131
+ ```ruby
132
+ DebugMeDefaultOptions[:file] = File.open('debug_me.log', 'w')
133
+
134
+ ```
135
+
136
+ ## Using a Logger class instance
137
+
138
+ If you are working in Rails and want all the `debug_me` output to go to the Rails.logger its as easy as:
139
+ ```ruby
140
+ DebugMeDefaultOptions[:logger] = Rails.logger
141
+
142
+ ```
143
+
144
+ Or while working in rails you only want to add a marker to the Rails.logger do this:
145
+ ```ruby
146
+ debug_me(logger: Rails.logger, tag: 'Hello World')
147
+ ```
148
+
149
+ If you are working in Rails and want to use both the standard `debug_me` functions and occassionally put stuff into the Rails.logger but do not want to always remember the option settings then do something line this in a `config/initializers/aaaaa_debug_me.rb` file:
150
+
151
+ ```ruby
152
+ # config/initializers/aaaaa_debug_me.rb
153
+
154
+ require 'debug_me'
155
+
156
+ module DebugMe
157
+ def log_me(message, options={}, &block)
158
+ options = {logger: Rails.logger, time: false, header: false, tag: message}
159
+ block_given? ? debug_me(options, block) : debug_me(options)
160
+ end
161
+ end
162
+
163
+ include DebugMe
164
+
165
+ # Just setup the base name. The parent path will be added below ...
166
+ debug_me_file_name = 'debug_me'
167
+
168
+ # NOTE: you could add a timestamp to the filename
169
+ # debug_me_file_name += '_' + Time.now.strftime('%Y%m%d%H%M%S')
170
+
171
+ debug_me_file_name += '_' + Process.argv0.gsub('/',' ').split(' ').last
172
+ # NOTE: by using the Process.argv0 ... you get multiple log files for
173
+ # rails, rake, sidekiq etc.
174
+
175
+ debug_me_file_name += '.log'
176
+
177
+ debug_me_filepath = Rails.root + 'log' + debug_me_file_name
178
+
179
+ debug_me_file = File.open(debug_me_filepath, 'w')
180
+
181
+ debug_me_file.puts <<~RULER
182
+
183
+ ==================== Starting New Test Run --------->>>>>>
184
+
185
+ RULER
186
+
187
+ # Set application wide options in the DebugMeDefaultOptions hash
188
+ DebugMeDefaultOptions[:file] = debug_me_file
189
+
190
+ debug_me{['ENV']}
191
+
192
+ ```
193
+
194
+ What that does for your Rails application is dump all of your system environment variables and their values to a debug_me log file in the log directory of the application.
195
+
196
+ It also adds a new method `log_me` which you can use to send stuff to the `Rails.logger` instance. The method used by `debug_me` for the `logger` instance is always the `debug` method.
197
+
198
+ ## Conclusion
199
+
200
+ The rest of the default options are obvious.
201
+
202
+ You can always over-ride the default options on a case by case basis like this:
203
+
204
+ ```
205
+ debug_me {...}
206
+ ...
207
+ debug_me(header: false){...}
60
208
  ```
61
209
 
62
210
  ## Contributing
data/debug_me.gemspec CHANGED
@@ -5,7 +5,7 @@ require 'debug_me/version'
5
5
 
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = 'debug_me'
8
- spec.version = DebugMe::VERSION
8
+ spec.version = DebugMe::DEBUG_ME_VERSION
9
9
  spec.authors = ['Dewayne VanHoozer']
10
10
  spec.email = ['dvanhoozer@gmail.com']
11
11
  spec.summary = 'A tool to print the labeled value of variables.'
@@ -21,6 +21,6 @@ time after time. I guess that marks me as a geezer.'
21
21
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
22
22
  spec.require_paths = ['lib']
23
23
 
24
- spec.add_development_dependency 'bundler', '~> 1.7'
25
- spec.add_development_dependency 'rake', '~> 10.0'
24
+ spec.add_development_dependency 'bundler'
25
+ spec.add_development_dependency 'rake'
26
26
  end
data/lib/debug_me.rb CHANGED
@@ -1,43 +1,66 @@
1
1
  require 'pp'
2
2
  require_relative 'debug_me/version'
3
3
 
4
+ DebugMeDefaultOptions = {
5
+ tag: 'DEBUG', # A tag to prepend to each output line
6
+ time: true, # Include a time-stamp in front of the tag
7
+ strftime: '%Y-%m-%d %H:%M:%S.%6N', # timestamp format
8
+ header: true, # Print a header string before printing the variables
9
+ levels: 0, # Number of additional backtrack entries to display
10
+ skip1: false, # skip 1 lines between different outputs
11
+ skip2: false, # skip 2 lines between different outputs
12
+ lvar: true, # Include local variables
13
+ ivar: true, # Include instance variables in the output
14
+ cvar: true, # Include class variables in the output
15
+ cconst: true, # Include class constants
16
+ logger: nil, # Pass in an instance of logger class like Rails.logger
17
+ # must respond_to? :debug
18
+ file: $stdout # The output file
19
+ }
20
+
4
21
  module DebugMe
5
22
  def debug_me(options = {}, &block)
6
- default_options = {
7
- tag: 'DEBUG:', # A tag to prepend to each output line
8
- time: true, # Include a time-stamp in front of the tag
9
- header: true, # Print a header string before printing the variables
10
- lvar: true, # Include local variables
11
- ivar: true, # Include instance variables in the output
12
- cvar: true, # Include class variables in the output
13
- cconst: true, # Include class constants
14
- file: $stdout # The output file
15
- }
16
-
17
23
 
18
24
  if 'Hash' == options.class.to_s
19
- options = default_options.merge(options)
25
+ options = DebugMeDefaultOptions.merge(options)
20
26
  else
21
- options = default_options.merge(tag: options)
27
+ options = DebugMeDefaultOptions.merge(tag: options)
22
28
  end
23
29
 
24
- out_string = ''
30
+ skip = ''
31
+ skip = "\n" if options[:skip1]
32
+ skip = "\n\n" if options[:skip2]
33
+ out_string = ''
25
34
 
26
35
  f = options[:file]
36
+ l = options[:logger]
27
37
  s = ''
28
- s += "#{sprintf('%010.6f', Time.now.to_f)} " if options[:time]
29
- s += " #{options[:tag]}"
30
- wf = caller # where_from under 1.8.6 its a stack trace array under 1.8.7 is a string
31
- wf = wf[0] if 'Array' == wf.class.to_s
32
-
33
- out_string = sprintf("%s Source: %s\n",s,wf) if options[:header]
38
+ s += Time.now.strftime(options[:strftime])+' ' if options[:time]
39
+ s += "#{options[:tag]}"
40
+ bt = caller # where_from under 1.8.6 its a stack trace array under 1.8.7+ as a string
41
+ bt_out = []
34
42
 
35
- if block_given?
43
+ if options[:header]
44
+ cf = bt.is_a?(Array) ? bt[0] : bt
45
+ out_string = sprintf("%s Source: %s\n", skip+s, cf)
46
+ if options[:levels] > 0
47
+ levels = options[:levels].to_i
48
+ bt[1..levels].each_with_index do |cff, level |
49
+ bt_out << [level, cff]
50
+ end
51
+ end
52
+ end
36
53
 
37
- block_value = [block.call].flatten.compact
54
+ if block_given? || bt_out.size > 0
55
+ block_value = []
56
+ block_value << 'backtrace' if bt_out.size > 0
57
+ if block_given?
58
+ [block.call].flatten.compact.each do |v|
59
+ block_value << v
60
+ end
61
+ end
38
62
 
39
63
  if block_value.empty?
40
- block_value = []
41
64
  block_value += [eval('local_variables', block.binding)] if options[:lvar]
42
65
  block_value += [eval('instance_variables', block.binding)] if options[:ivar]
43
66
  block_value += [self.class.send('class_variables')] if options[:cvar]
@@ -48,7 +71,12 @@ module DebugMe
48
71
  block_value.map!(&:to_s)
49
72
 
50
73
  block_value.each do |v|
51
- ev = eval("defined?(#{v})",block.binding).nil? ? '<undefined>' : eval(v, block.binding)
74
+
75
+ ev = if 'backtrace' == v
76
+ bt_out.size > 0 ? bt_out : bt[1..10000]
77
+ else
78
+ eval("defined?(#{v})",block.binding).nil? ? '<undefined>' : eval(v, block.binding)
79
+ end
52
80
  out_string += sprintf( "%s %s -=> %s", s,v,ev.pretty_inspect)
53
81
  end
54
82
 
@@ -59,10 +87,14 @@ module DebugMe
59
87
  f.flush
60
88
  end
61
89
 
90
+ unless l.nil?
91
+ l.debug(out_string) if l.respond_to? :debug
92
+ end
93
+
62
94
  return out_string
63
95
  end ## def debug_me( options={}, &block )
64
96
 
65
97
  # def log_me(msg, opts={})
66
- # debug_me({:tag => msg, :header => false}.merge(opts))
98
+ # debug_me({tag: msg, header: false}.merge(opts))
67
99
  # end
68
100
  end # module DebugMe
@@ -1,3 +1,8 @@
1
1
  module DebugMe
2
- VERSION = '1.0.2'
2
+ # I know. Its weird to duplicate the name space; but,
3
+ # doing this allows you to include DebugMe in your code
4
+ # to get direct access to the debug_me method without
5
+ # poluting your code with an object name that is so
6
+ # common.
7
+ DEBUG_ME_VERSION = '1.1.0'
3
8
  end
@@ -1,5 +1,9 @@
1
1
  #!/usr/bin/env ruby
2
2
 
3
+ require 'amazing_print'
4
+ require 'logger'
5
+ require 'pathname'
6
+
3
7
  require_relative '../lib/debug_me'
4
8
  include DebugMe
5
9
 
@@ -34,6 +38,27 @@ describe DebugMe do
34
38
 
35
39
  end # describe "source header included" do
36
40
 
41
+
42
+
43
+ describe "Add more from the call stack" do
44
+
45
+ before do
46
+ @my_world_view = WorldView.new
47
+ end
48
+
49
+ it 'supports multiple levels from the call stack' do
50
+ result = @my_world_view.one
51
+ # debug_me returns everything as one big long string
52
+ # with embedded new lines. In the WorldView class
53
+ # method six is called from five, which is called from four, three, two, one.
54
+ # The ":levels" options is set to 5 so expect the
55
+ # normal source header followed by 5 additional
56
+ # entries from the call stack.
57
+ assert_equal(result.split("\n").size, 6)
58
+ end
59
+ end
60
+
61
+
37
62
  describe "source header excluded" do
38
63
 
39
64
  before do
@@ -224,6 +249,45 @@ describe DebugMe do
224
249
 
225
250
  end # describe "works with class CONSTANTS" do
226
251
 
252
+ describe "works with a Logger class" do
253
+
254
+ it 'default logger class is nil' do
255
+ DebugMeDefaultOptions[:logger].must_equal nil
256
+ end
257
+
258
+ it 'works with standard ruby Logger class' do
259
+ logger_output_path = Pathname.pwd + 'logger_class_output.txt'
260
+ logger_output_path.exist?.must_equal false
261
+
262
+ logger = Logger.new(logger_output_path)
263
+ logger.level = Logger::DEBUG
264
+
265
+ out_string = debug_me(
266
+ logger: logger, # Use instance of Ruby's Logger
267
+ time: false, # turn off debug_me's timestamp
268
+ file: nil, # don't write to STDOUT the default
269
+ tag: 'Hello World' # say hello
270
+ )
271
+ # Generates an entry like this:
272
+ =begin
273
+ # Logfile created on 2020-04-27 16:16:38 -0500 by logger.rb/v1.4.2
274
+ D, [2020-04-27T16:16:38.580889 #54662] DEBUG -- : Hello World Source: debug_me_test.rb:244:in `block (3 levels) in <main>'
275
+ =end
276
+
277
+ lines = logger_output_path.read.split("\n")
278
+
279
+ lines.size.must_equal 2
280
+
281
+ lines[0].start_with?('# Logfile created on').must_equal true
282
+ lines[1].start_with?('D, [').must_equal true
283
+ lines[1].include?('DEBUG').must_equal true
284
+ lines[1].include?('Hello World').must_equal true
285
+ lines[1].include?('debug_me_test.rb').must_equal true
286
+ lines[1].include?(out_string.chomp).must_equal true
287
+
288
+ logger_output_path.delete
289
+ end
227
290
 
291
+ end
228
292
 
229
293
  end # describe DebugMe do
data/tests/world_view.rb CHANGED
@@ -3,20 +3,23 @@ class WorldView
3
3
  A = 1
4
4
  B = 2
5
5
  C = 3
6
+
6
7
  def initialize
7
- @a,@b,@c = 1,2,3
8
- @@d, @@e, @@f = 4,5,6
8
+ @a,@b,@c = 1,2,3
9
+ @@d, @@e, @@f = 4,5,6
9
10
  end
11
+
10
12
  def everything
11
13
  debug_me(
12
- file:nil,
13
- header:true,
14
- lvar: true,
15
- ivar: true,
16
- cvar: true,
14
+ file: nil,
15
+ header: true,
16
+ lvar: true,
17
+ ivar: true,
18
+ cvar: true,
17
19
  cconst: true
18
20
  ){}
19
21
  end
22
+
20
23
  def my_constants
21
24
  debug_me(
22
25
  file:nil,
@@ -26,6 +29,15 @@ class WorldView
26
29
  cvar: false,
27
30
  cconst: true
28
31
  ){}
32
+ end
33
+
34
+ def one; two; end
35
+ def two; three; end
36
+ def three; four; end
37
+ def four; five; end
38
+ def five; six; end
29
39
 
40
+ def six
41
+ debug_me(tag:'How did I get here?', levels: 5)
30
42
  end
31
43
  end # class WorldView
metadata CHANGED
@@ -1,63 +1,56 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: debug_me
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.2
5
- prerelease:
4
+ version: 1.1.0
6
5
  platform: ruby
7
6
  authors:
8
7
  - Dewayne VanHoozer
9
- autorequire:
8
+ autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2015-01-19 00:00:00.000000000 Z
11
+ date: 2021-04-23 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: bundler
16
15
  requirement: !ruby/object:Gem::Requirement
17
- none: false
18
16
  requirements:
19
- - - ~>
17
+ - - ">="
20
18
  - !ruby/object:Gem::Version
21
- version: '1.7'
19
+ version: '0'
22
20
  type: :development
23
21
  prerelease: false
24
22
  version_requirements: !ruby/object:Gem::Requirement
25
- none: false
26
23
  requirements:
27
- - - ~>
24
+ - - ">="
28
25
  - !ruby/object:Gem::Version
29
- version: '1.7'
26
+ version: '0'
30
27
  - !ruby/object:Gem::Dependency
31
28
  name: rake
32
29
  requirement: !ruby/object:Gem::Requirement
33
- none: false
34
30
  requirements:
35
- - - ~>
31
+ - - ">="
36
32
  - !ruby/object:Gem::Version
37
- version: '10.0'
33
+ version: '0'
38
34
  type: :development
39
35
  prerelease: false
40
36
  version_requirements: !ruby/object:Gem::Requirement
41
- none: false
42
37
  requirements:
43
- - - ~>
38
+ - - ">="
44
39
  - !ruby/object:Gem::Version
45
- version: '10.0'
46
- description: ! 'This thing is pretty old. There are much better
47
-
40
+ version: '0'
41
+ description: |-
42
+ This thing is pretty old. There are much better
48
43
  ways of debugging in a complex application. But,
49
-
50
44
  you know, I keep returning to this little method
51
-
52
- time after time. I guess that marks me as a geezer.'
45
+ time after time. I guess that marks me as a geezer.
53
46
  email:
54
47
  - dvanhoozer@gmail.com
55
48
  executables: []
56
49
  extensions: []
57
50
  extra_rdoc_files: []
58
51
  files:
59
- - .gitignore
60
- - .rultor.yml
52
+ - ".gitignore"
53
+ - ".rultor.yml"
61
54
  - Gemfile
62
55
  - LICENSE.txt
63
56
  - README.md
@@ -71,26 +64,24 @@ files:
71
64
  homepage: http://github.com/MadBomber/debug_me
72
65
  licenses:
73
66
  - You want it, its yours
74
- post_install_message:
67
+ metadata: {}
68
+ post_install_message:
75
69
  rdoc_options: []
76
70
  require_paths:
77
71
  - lib
78
72
  required_ruby_version: !ruby/object:Gem::Requirement
79
- none: false
80
73
  requirements:
81
- - - ! '>='
74
+ - - ">="
82
75
  - !ruby/object:Gem::Version
83
76
  version: '0'
84
77
  required_rubygems_version: !ruby/object:Gem::Requirement
85
- none: false
86
78
  requirements:
87
- - - ! '>='
79
+ - - ">="
88
80
  - !ruby/object:Gem::Version
89
81
  version: '0'
90
82
  requirements: []
91
- rubyforge_project:
92
- rubygems_version: 1.8.23
93
- signing_key:
94
- specification_version: 3
83
+ rubygems_version: 3.2.15
84
+ signing_key:
85
+ specification_version: 4
95
86
  summary: A tool to print the labeled value of variables.
96
87
  test_files: []