dbg_tags 1.0.1 → 1.1.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 +4 -4
- data/lib/dbg_tags.rb +149 -119
- data/spec/01_tag_spec.rb +45 -0
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aaad620ad2b1c43ee4fad44431ff99f22d5fe07f66dbb68eb11247246d99083e
|
4
|
+
data.tar.gz: e33c27bb2b870e18bd4a910ef0918db018174f89eb3aaf95c2619bca74e0dee6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 660f4307b55f0c7b0ff5e029916b436f000346c31cca80e1956eaada5a71599a2e1e21f654bc0d8cd6dfb086e0489445a4f4385394ec4f558e8f8284a9aaee59
|
7
|
+
data.tar.gz: 5be152c20aa033ba1372d132b7f514a0ddbd5fe5da459148e9790f120ad5c342564e24402c344cfb61aee4e437aa16238380b13f9a86520fe624242f1c4ec00b
|
data/lib/dbg_tags.rb
CHANGED
@@ -3,45 +3,41 @@
|
|
3
3
|
#
|
4
4
|
# # enabling
|
5
5
|
# # -----------
|
6
|
-
#
|
6
|
+
# require 'dbg_tags'
|
7
7
|
#
|
8
|
-
#
|
9
|
-
#
|
10
|
-
#
|
11
|
-
#
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
15
|
-
#
|
16
|
-
#
|
17
|
-
#
|
18
|
-
#
|
19
|
-
#
|
20
|
-
#
|
21
|
-
#
|
22
|
-
#
|
8
|
+
# Tag.enable :feature1, :feature2..., featureN: :log, featureO: :val, ...
|
9
|
+
# Tag.enable feature1: :trc, feature2: :val
|
10
|
+
# Tag.enable feature: Tag::TRC
|
11
|
+
# Tag.enable :dtl # enables ALL logging for :generic
|
12
|
+
# Tag.enable :val # enables val+trc+log+err for :generic only
|
13
|
+
# Tag.enable :trc # enables trc+log+err for :generic only
|
14
|
+
# Tag.enable :log # enables log+err tags for :generic
|
15
|
+
# Tag.enable :err # enables err tags for :generic
|
16
|
+
# Tag.enable # sets :generic to :trc
|
17
|
+
# Tag.enable(...) do ... end
|
18
|
+
# Tag.enable feature: nil
|
19
|
+
# Tag.enable feature: :nil
|
20
|
+
# Tag.enable all: :err # :all is a default for ALL systems, including :generic
|
21
|
+
# Tag.enable test: :err # switch on paranoia checking
|
22
|
+
# Tag.enable feature: '>=trc' # make sure at least level trc
|
23
23
|
#
|
24
24
|
# # logging
|
25
25
|
# # -----------
|
26
|
-
#
|
26
|
+
# Tag.err 'text', short for Tag.err(:generic) 'text'
|
27
27
|
# # :err should be used for fail states and paranoia stuff
|
28
|
-
#
|
29
|
-
#
|
30
|
-
#
|
31
|
-
#
|
32
|
-
#
|
33
|
-
#
|
34
|
-
#
|
35
|
-
#
|
36
|
-
#
|
37
|
-
#
|
38
|
-
#
|
28
|
+
# Tag.log 'text' # prints very important messages only
|
29
|
+
# Tag.trc 'text' # default level, method entries, for example
|
30
|
+
# Tag.val 'text' # prints more details
|
31
|
+
# Tag.dtl 'text' # likely prints megabytes of details
|
32
|
+
# Tag.err :feature, 'FAILURE'
|
33
|
+
# Tag.log :feature, 'log me'
|
34
|
+
# Tag.trc :feature, 'called method'
|
35
|
+
# Tag.val(:feature) { "text#{expr}" }
|
36
|
+
# Tag.dtl(:feature) { "text#{very complicated expr}" }
|
37
|
+
# Tag.err(:test) { raise 'aaaarg' if complex_paranoia_failure }
|
38
|
+
# Tag.err(:test) { raise 'CANTHAPPEN' if complex_paranoia_failure }
|
39
39
|
|
40
40
|
module Tag
|
41
|
-
|
42
|
-
# the default is :trc
|
43
|
-
TAG_DEFAULT_LEVEL = 3
|
44
|
-
|
45
41
|
# :all overrides the minimum level on ALL tags in the system
|
46
42
|
TAG_FEATURE_ALL = :all
|
47
43
|
|
@@ -66,81 +62,26 @@ module Tag
|
|
66
62
|
# level 5. Mostly used for exhaustive dumping of attribute values and minor details
|
67
63
|
DTL = 5
|
68
64
|
|
65
|
+
# the default is :trc
|
66
|
+
TAG_DEFAULT_LEVEL = TRC
|
67
|
+
|
69
68
|
# nil and :nil will both map to NONE
|
70
69
|
TAG_MAPPING = { none: NONE, err: ERR, log: LOG, trc: TRC, val: VAL, dtl: DTL,
|
71
70
|
nil: NONE,
|
72
71
|
nil => NONE
|
73
72
|
} # TAG_MAPPING
|
74
73
|
|
75
|
-
#
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
#
|
84
|
-
# @note feature and msg can be switched
|
85
|
-
# @param block [Proc,nil] If set the result overrides and msg passed.
|
86
|
-
# The call is silently ignored if called from inside another Tag block (likely
|
87
|
-
# a sign of a stack overflow in process).
|
88
|
-
# The call is silently ignored if the current tag level is too low.
|
89
|
-
# For trc it should be trc or val or dtl to actually print something.
|
90
|
-
# @!method trc feature = TAG_FEATURE_GENERIC, msg = '', &block
|
91
|
-
|
92
|
-
# see trc
|
93
|
-
# !method err feature = TAG_FEATURE_GENERIC, msg = '', &block
|
94
|
-
|
95
|
-
# see trc
|
96
|
-
# !method log feature = TAG_FEATURE_GENERIC, msg = '', &block
|
97
|
-
|
98
|
-
# see trc
|
99
|
-
# !method val feature = TAG_FEATURE_GENERIC, msg = '', &block
|
100
|
-
|
101
|
-
# see trc
|
102
|
-
# !method dtl feature = TAG_FEATURE_GENERIC, msg = '', &block
|
103
|
-
|
104
|
-
TAG_MAPPING.each do |meth, lev|
|
105
|
-
next if lev == NONE
|
106
|
-
define_method meth do |feature = TAG_FEATURE_GENERIC, msg = '', &msg_block|
|
107
|
-
msg, feature = feature, TAG_FEATURE_GENERIC if String === feature
|
108
|
-
#STDERR.puts "DEBUGTAG #{meth}. feature=#{feature}, level=#{Tag.level(feature)}, lev=#{lev}"
|
109
|
-
return if @@inside || (Tag.level(feature) || Tag::NONE) < lev
|
110
|
-
# either msg OR msg_block must be set
|
111
|
-
if msg_block
|
112
|
-
prev_inside = @@inside
|
113
|
-
begin
|
114
|
-
@@inside = true
|
115
|
-
msg = msg_block.call
|
116
|
-
ensure
|
117
|
-
@@inside = prev_inside
|
118
|
-
end
|
119
|
-
end
|
120
|
-
if msg
|
121
|
-
c = caller[0]
|
122
|
-
#STDERR.puts "DEBUGTAG c[#{idx}] = #{c}, caller[1]=#{caller[1]}, caller[2]=#{caller[2]}"
|
123
|
-
label = c[/\w+\.rb:\d+:in `[^']+'/]&.sub(/in `([^']+)'/, '\1:') ||
|
124
|
-
c[/\w+\.rb:\d+:/] ||
|
125
|
-
c[/[^:\/]+:\d+:/] ||
|
126
|
-
c
|
127
|
-
Tag.stream.print "#{label} #{msg}\n"
|
128
|
-
end
|
129
|
-
end # Tag.err, Tag.log, Tag.trc, Tag.val, Tag.dtl
|
130
|
-
end # each
|
131
|
-
|
132
|
-
# inside? -> true if we are currently executing a block in err/log/trc/val or dtl.
|
133
|
-
def inside?; @@inside; end
|
134
|
-
|
135
|
-
end # module Tag::InstanceMethods
|
74
|
+
# This class stores an instance of the global state of the Tag system
|
75
|
+
class GlobalState
|
76
|
+
private
|
77
|
+
def initialize
|
78
|
+
# @enabled[:feature] => 0..5
|
79
|
+
@enabled = {}
|
80
|
+
@inside = false
|
81
|
+
@stream = STDERR
|
82
|
+
end # GlobalState.initialize
|
136
83
|
|
137
|
-
|
138
|
-
include InstanceMethods
|
139
|
-
|
140
|
-
class << self
|
141
|
-
private # class methods of Tag
|
142
|
-
|
143
|
-
# @param level_spec [Integer,Symbol,String]
|
84
|
+
# @param level_spec [Integer,Symbol,String,nil]
|
144
85
|
# @param feature [Symbol]
|
145
86
|
# @return [0..5]
|
146
87
|
def debunk_level level_spec, feature
|
@@ -148,6 +89,7 @@ module Tag
|
|
148
89
|
# OK STDERR.puts "DEBUNK: level_spec=#{level_spec.inspect}, feature=#{feature.inspect}"
|
149
90
|
case level_spec
|
150
91
|
when 0..5 then return level_spec
|
92
|
+
when nil then return NONE
|
151
93
|
when Symbol
|
152
94
|
r = TAG_MAPPING[level_spec] and return r
|
153
95
|
when /\A(err|log|trc|val|dtl)\z/
|
@@ -161,9 +103,21 @@ module Tag
|
|
161
103
|
raise ArgumentError, "bad level #{level_spec.inspect}"
|
162
104
|
end # Tag::debunk_level
|
163
105
|
|
164
|
-
public #
|
106
|
+
public # methods of GlobalState
|
107
|
+
|
108
|
+
# @return [{Symbol} => 0..5]
|
109
|
+
attr :enabled
|
110
|
+
|
111
|
+
# @return [Bool] True if a Tag.err..dtl is currently active
|
112
|
+
attr_accessor :inside
|
113
|
+
alias inside? inside
|
165
114
|
|
166
|
-
# @
|
115
|
+
# @return [IO] Current output stream
|
116
|
+
attr_accessor :stream
|
117
|
+
|
118
|
+
# @param features [<Symbol>] To enable on :trc level
|
119
|
+
# @param opts [{Symbol => Symbol}] Keys are features, values levels.
|
120
|
+
# A block can be given to restore the original state afterwards
|
167
121
|
# enable :feature, ...[, feature: level, ...] [block]
|
168
122
|
# :generic is NO LONGER IMPLICETELY ENABLED as of version 1.0.0
|
169
123
|
# Use :all to set a default for all features not mentioned otherwise
|
@@ -172,62 +126,138 @@ module Tag
|
|
172
126
|
# Strings can be used in the shape of 'err' or '>=err' etc.
|
173
127
|
# If '>=LVL' is used the level will not lower, if already set in an outer block.
|
174
128
|
# If no level is specified for a feature the default is :trc (== TRC == 3)
|
175
|
-
# use nil
|
129
|
+
# use nil, :nil, :none or Tag::NONE to disable all tags, even the ERR level ones.
|
176
130
|
#
|
177
131
|
# enable performs a merge with an existing enable.
|
178
132
|
def enable *features, **opts
|
179
|
-
org_enabled =
|
133
|
+
org_enabled = @enabled.dup # to restore the state at the end (unused unless block_given)
|
180
134
|
features.each do |feature|
|
181
135
|
case feature
|
182
136
|
when 0..5 # not a feature, apply to :generic
|
183
|
-
|
137
|
+
@enabled[TAG_FEATURE_GENERIC] = feature
|
184
138
|
when Symbol
|
185
139
|
if TAG_MAPPING[feature] # not a feature
|
186
|
-
|
140
|
+
@enabled[TAG_FEATURE_GENERIC] = TAG_MAPPING[feature]
|
187
141
|
else
|
188
|
-
|
142
|
+
@enabled[feature] = TAG_DEFAULT_LEVEL
|
189
143
|
end
|
190
144
|
when String
|
191
|
-
|
145
|
+
@enabled[TAG_FEATURE_GENERIC] = debunk_level feature, TAG_FEATURE_GENERIC
|
192
146
|
else
|
193
147
|
raise ArgumentError "bad level #{feature.inspect}"
|
194
148
|
end # case
|
195
149
|
end # each
|
196
150
|
opts.each do |feature, level|
|
197
151
|
# OK STDERR.puts "OPTION!!!!!!!!!!!!!!!!!, calling debunk_level"
|
198
|
-
|
152
|
+
@enabled[feature] = debunk_level level, feature
|
199
153
|
end
|
200
154
|
if features.empty? && opts.empty?
|
201
|
-
|
155
|
+
@enabled[TAG_FEATURE_GENERIC] = TAG_DEFAULT_LEVEL
|
202
156
|
end
|
203
157
|
if block_given?
|
204
|
-
# STDERR.puts "TAG: block_given!"
|
205
158
|
begin
|
206
|
-
# STDERR.puts "TAG: yield!"
|
207
159
|
yield
|
208
160
|
ensure
|
209
|
-
|
161
|
+
@enabled = org_enabled
|
210
162
|
end # ensure
|
211
163
|
end # block_given?
|
212
|
-
end #
|
164
|
+
end # GlobalState.enable
|
165
|
+
|
166
|
+
# @param feature [Symbol]
|
167
|
+
# @return [0..5] Current effective level for feature.
|
168
|
+
def level feature
|
169
|
+
@enabled[feature] || @enabled[TAG_FEATURE_ALL] || Tag::NONE
|
170
|
+
end # GlobalState.level
|
171
|
+
end # GlobalState
|
172
|
+
|
173
|
+
class << self
|
174
|
+
|
175
|
+
public # class methods of Tag
|
176
|
+
|
177
|
+
# @return [GlobalState] Thread local data
|
178
|
+
def global_state
|
179
|
+
if gs = Thread.current[:dbg_tags_global_state]
|
180
|
+
gs
|
181
|
+
else
|
182
|
+
Thread.current[:dbg_tags_global_state] = GlobalState.new
|
183
|
+
end
|
184
|
+
end # Tag::global_state
|
185
|
+
|
186
|
+
# @param feature [Symbol,nil] Subsystem to print logging for. Fully dynamic/free
|
187
|
+
# @param msg [String,nil]
|
188
|
+
# @note feature and msg can be switched
|
189
|
+
# @param block [Proc,nil] If set the result overrides and msg passed.
|
190
|
+
# The call is silently ignored if called from inside another Tag block (likely
|
191
|
+
# a sign of a stack overflow in process).
|
192
|
+
# The call is silently ignored if the current tag level is too low.
|
193
|
+
# For trc it should be trc or val or dtl to actually print something.
|
194
|
+
# @!method trc feature = TAG_FEATURE_GENERIC, msg = '', &block
|
195
|
+
|
196
|
+
# @!method err feature = TAG_FEATURE_GENERIC, msg = '', &block
|
197
|
+
# @see trc
|
198
|
+
|
199
|
+
# @!method log feature = TAG_FEATURE_GENERIC, msg = '', &block
|
200
|
+
# @see trc
|
201
|
+
|
202
|
+
# @!method val feature = TAG_FEATURE_GENERIC, msg = '', &block
|
203
|
+
# @see trc
|
204
|
+
|
205
|
+
# @!method dtl feature = TAG_FEATURE_GENERIC, msg = '', &block
|
206
|
+
# @see trc
|
207
|
+
|
208
|
+
TAG_MAPPING.each do |meth, lev|
|
209
|
+
next if lev == NONE
|
210
|
+
define_method meth do |feature = TAG_FEATURE_GENERIC, msg = '', &msg_block|
|
211
|
+
state = global_state
|
212
|
+
msg, feature = feature, TAG_FEATURE_GENERIC if String === feature
|
213
|
+
#STDERR.puts "DEBUGTAG #{meth}. feature=#{feature}, level=#{Tag.level(feature)}, lev=#{lev}"
|
214
|
+
return if state.inside? || (state.level(feature) || Tag::NONE) < lev
|
215
|
+
# either msg OR msg_block must be set
|
216
|
+
if msg_block
|
217
|
+
prev_inside = state.inside?
|
218
|
+
begin
|
219
|
+
state.inside = true
|
220
|
+
msg = msg_block.call
|
221
|
+
ensure
|
222
|
+
state.inside = prev_inside
|
223
|
+
end
|
224
|
+
end
|
225
|
+
if msg
|
226
|
+
c = caller[0]
|
227
|
+
#STDERR.puts "DEBUGTAG c[#{idx}] = #{c}, caller[1]=#{caller[1]}, caller[2]=#{caller[2]}"
|
228
|
+
label = c[/\w+\.rb:\d+:in `[^']+'/]&.sub(/in `([^']+)'/, '\1:') ||
|
229
|
+
c[/\w+\.rb:\d+:/] ||
|
230
|
+
c[/[^:\/]+:\d+:/] ||
|
231
|
+
c
|
232
|
+
state.stream.print "#{label} #{msg}\n"
|
233
|
+
end
|
234
|
+
end # Tag.err, Tag.log, Tag.trc, Tag.val, Tag.dtl
|
235
|
+
end # each
|
236
|
+
|
237
|
+
# inside? -> true if we are currently executing a block in err/log/trc/val or dtl.
|
238
|
+
def inside?; global_state.inside?; end
|
239
|
+
|
240
|
+
# @see GlobalState.enable
|
241
|
+
def enable(...); global_state.enable(...); end
|
213
242
|
|
214
243
|
# @return [{Symbol=>0..5}] Keys are the features
|
215
|
-
def enabled;
|
244
|
+
def enabled; global_state.enabled; end
|
216
245
|
|
217
246
|
# @return [IO] By default this is STDERR
|
218
|
-
def stream;
|
247
|
+
def stream; global_state.stream; end
|
219
248
|
|
220
249
|
# @param val [IO]
|
221
250
|
# Override the output stream.
|
222
|
-
def stream= val;
|
251
|
+
def stream= val; global_state.stream = val; end
|
223
252
|
|
224
253
|
# @param feature [Symbol]
|
225
254
|
# @return [0..5] Current effective level for feature.
|
226
255
|
# 2023-08-14 no longer returns nil
|
227
|
-
def level feature;
|
256
|
+
def level feature; global_state.level feature; end
|
228
257
|
|
229
258
|
# @param feature [Symbol]
|
230
259
|
# @return [bool] Reflects explicit enable calls only. The :all feature is IGNORED
|
231
|
-
def enabled? feature; (
|
260
|
+
def enabled? feature; (global_state.enabled[feature] || NONE) > NONE; end
|
261
|
+
|
232
262
|
end # singleton class Tag
|
233
263
|
end # module Tag
|
data/spec/01_tag_spec.rb
CHANGED
@@ -175,6 +175,12 @@ describe 'tag' do
|
|
175
175
|
end
|
176
176
|
end
|
177
177
|
|
178
|
+
it 'is allowed to use nil for :nil in enable (tag_110)' do
|
179
|
+
Tag.enable feature: nil do
|
180
|
+
expect(Tag.enabled[:feature]).to eq Tag::NONE
|
181
|
+
end
|
182
|
+
end # it
|
183
|
+
|
178
184
|
# however, it only works with LAZY calls.
|
179
185
|
# def to_s; Tag.trc "HERE in #{self}"; super; end
|
180
186
|
# will OBVIOUSLY cause a stack overflow.
|
@@ -246,6 +252,44 @@ describe 'tag' do
|
|
246
252
|
end # it
|
247
253
|
end # context 'Nested levels'
|
248
254
|
|
255
|
+
it 'has thread local data to prevent mix ups (tag_300)' do
|
256
|
+
t1 = Thread.new do
|
257
|
+
Tag.enable threads: :trc do
|
258
|
+
Tag.trc(:threads) {
|
259
|
+
expect(Tag.inside?).to be true
|
260
|
+
sleep 1
|
261
|
+
nil
|
262
|
+
}
|
263
|
+
end
|
264
|
+
end
|
265
|
+
t2 = Thread.new do
|
266
|
+
sleep 0.2
|
267
|
+
expect(Tag.enabled).to eq({})
|
268
|
+
expect(Tag.inside?).to be false
|
269
|
+
end
|
270
|
+
t1.join
|
271
|
+
t2.join
|
272
|
+
end # it
|
273
|
+
|
274
|
+
it 'each thread has a private tag system (tag_301)' do
|
275
|
+
Tag.enable threads: :trc do
|
276
|
+
expect(Tag.enabled).to eq({threads: 3})
|
277
|
+
t1 = Thread.new do
|
278
|
+
expect(Tag.enabled).to eq({})
|
279
|
+
Tag.enable threads: :log do
|
280
|
+
expect(Tag.enabled).to eq({threads: 2})
|
281
|
+
Tag.trc(:threads) {
|
282
|
+
expect(Tag.inside?).to be true
|
283
|
+
sleep 1
|
284
|
+
nil
|
285
|
+
}
|
286
|
+
end
|
287
|
+
end
|
288
|
+
t1.join
|
289
|
+
expect(Tag.enabled).to eq({threads: 3})
|
290
|
+
end
|
291
|
+
end # it
|
292
|
+
|
249
293
|
it 'does not allow levels out of range (tag_900)' do
|
250
294
|
expect do
|
251
295
|
Tag.enable nest: 24
|
@@ -263,4 +307,5 @@ describe 'tag' do
|
|
263
307
|
Tag.enable nest: '>=foo'
|
264
308
|
end.to raise_error ArgumentError, /bad level/i
|
265
309
|
end # it
|
310
|
+
|
266
311
|
end # describe
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: dbg_tags
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eugene Brazwick
|
8
|
-
autorequire:
|
8
|
+
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2024-05-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -66,7 +66,7 @@ homepage: https://github.com/Eugene-Brazwick/dbg_tags
|
|
66
66
|
licenses:
|
67
67
|
- GPL-3.0
|
68
68
|
metadata: {}
|
69
|
-
post_install_message:
|
69
|
+
post_install_message:
|
70
70
|
rdoc_options: []
|
71
71
|
require_paths:
|
72
72
|
- lib
|
@@ -74,7 +74,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
74
74
|
requirements:
|
75
75
|
- - ">="
|
76
76
|
- !ruby/object:Gem::Version
|
77
|
-
version: '
|
77
|
+
version: '3.0'
|
78
78
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
@@ -82,7 +82,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
82
82
|
version: '0'
|
83
83
|
requirements: []
|
84
84
|
rubygems_version: 3.3.5
|
85
|
-
signing_key:
|
85
|
+
signing_key:
|
86
86
|
specification_version: 4
|
87
87
|
summary: a versatile dynamic debug tracing system
|
88
88
|
test_files:
|