tracer 0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 32f50385faf52046ed48365c62f294a7d2d64fc99b5457c13e2bb7d239944883
4
+ data.tar.gz: 14942209dd335bdde1267eaf6382b4ce1aad47200cfa6c3af82eadb8c03fae49
5
+ SHA512:
6
+ metadata.gz: 8969d4d076f10f25d0b1281d4decb8fd4c3b2aa39429e16a4771be45942b103450f7459afed93ad97bc44a73d50e9601805248729659bf9da36d50a279c0cfe7
7
+ data.tar.gz: a83839fd50491fcfe4374acc42be6ab8000d3335431947d6d7a12c69a5fc1e0a5875fa2afb9ce00a41f7d24a66f69a7774195869083416f184282fa7dd3a34ea
@@ -0,0 +1,8 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /_yardoc/
4
+ /coverage/
5
+ /doc/
6
+ /pkg/
7
+ /spec/reports/
8
+ /tmp/
@@ -0,0 +1,6 @@
1
+ sudo: false
2
+ language: ruby
3
+ rvm:
4
+ - 2.5.1
5
+ - ruby-head
6
+ before_install: gem install bundler -v 1.16.2
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "https://rubygems.org"
2
+
3
+ git_source(:github) {|repo_name| "https://github.com/#{repo_name}" }
4
+
5
+ # Specify your gem's dependencies in tracer.gemspec
6
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (C) 1993-2013 Yukihiro Matsumoto. All rights reserved.
2
+
3
+ Redistribution and use in source and binary forms, with or without
4
+ modification, are permitted provided that the following conditions
5
+ are met:
6
+ 1. Redistributions of source code must retain the above copyright
7
+ notice, this list of conditions and the following disclaimer.
8
+ 2. Redistributions in binary form must reproduce the above copyright
9
+ notice, this list of conditions and the following disclaimer in the
10
+ documentation and/or other materials provided with the distribution.
11
+
12
+ THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
13
+ ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
14
+ IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
15
+ ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
16
+ FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
17
+ DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
18
+ OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
19
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
20
+ LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
21
+ OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
22
+ SUCH DAMAGE.
@@ -0,0 +1,84 @@
1
+ # Tracer
2
+
3
+ Outputs a source level execution trace of a Ruby program.
4
+
5
+ It does this by registering an event handler with Kernel#set_trace_func for processing incoming events. It also provides methods for filtering unwanted trace output (see Tracer.add_filter, Tracer.on, and Tracer.off).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ ```ruby
12
+ gem 'tracer'
13
+ ```
14
+
15
+ And then execute:
16
+
17
+ $ bundle
18
+
19
+ Or install it yourself as:
20
+
21
+ $ gem install tracer
22
+
23
+ ## Usage
24
+
25
+ Consider the following Ruby script
26
+
27
+ ```
28
+ class A
29
+ def square(a)
30
+ return a*a
31
+ end
32
+ end
33
+
34
+ a = A.new
35
+ a.square(5)
36
+ ```
37
+
38
+ Running the above script using <code>ruby -r tracer example.rb</code> will output the following trace to STDOUT (Note you can also explicitly <code>require 'tracer'</code>)
39
+
40
+ ```
41
+ #0:<internal:lib/rubygems/custom_require>:38:Kernel:<: -
42
+ #0:example.rb:3::-: class A
43
+ #0:example.rb:3::C: class A
44
+ #0:example.rb:4::-: def square(a)
45
+ #0:example.rb:7::E: end
46
+ #0:example.rb:9::-: a = A.new
47
+ #0:example.rb:10::-: a.square(5)
48
+ #0:example.rb:4:A:>: def square(a)
49
+ #0:example.rb:5:A:-: return a*a
50
+ #0:example.rb:6:A:<: end
51
+ | | | | |
52
+ | | | | ---------------------+ event
53
+ | | | ------------------------+ class
54
+ | | --------------------------+ line
55
+ | ------------------------------------+ filename
56
+ ---------------------------------------+ thread
57
+ ```
58
+
59
+ Symbol table used for displaying incoming events:
60
+
61
+ ```
62
+ +}+:: call a C-language routine
63
+ +{+:: return from a C-language routine
64
+ +>+:: call a Ruby method
65
+ +C+:: start a class or module definition
66
+ +E+:: finish a class or module definition
67
+ +-+:: execute code on a new line
68
+ +^+:: raise an exception
69
+ +<+:: return from a Ruby method
70
+ ```
71
+
72
+ ## Development
73
+
74
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
75
+
76
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
77
+
78
+ ## Contributing
79
+
80
+ Bug reports and pull requests are welcome on GitHub at https://github.com/ruby/tracer.
81
+
82
+ ## License
83
+
84
+ The gem is available as open source under the terms of the [2-Clause BSD License](https://opensource.org/licenses/BSD-2-Clause).
@@ -0,0 +1,10 @@
1
+ require "bundler/gem_tasks"
2
+ require "rake/testtask"
3
+
4
+ Rake::TestTask.new(:test) do |t|
5
+ t.libs << "test" << "test/lib"
6
+ t.libs << "lib"
7
+ t.test_files = FileList["test/**/test_*.rb"]
8
+ end
9
+
10
+ task :default => :test
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "tracer"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,287 @@
1
+ # frozen_string_literal: false
2
+ #--
3
+ # $Release Version: 0.3$
4
+ # $Revision: 1.12 $
5
+
6
+ ##
7
+ # Outputs a source level execution trace of a Ruby program.
8
+ #
9
+ # It does this by registering an event handler with Kernel#set_trace_func for
10
+ # processing incoming events. It also provides methods for filtering unwanted
11
+ # trace output (see Tracer.add_filter, Tracer.on, and Tracer.off).
12
+ #
13
+ # == Example
14
+ #
15
+ # Consider the following Ruby script
16
+ #
17
+ # class A
18
+ # def square(a)
19
+ # return a*a
20
+ # end
21
+ # end
22
+ #
23
+ # a = A.new
24
+ # a.square(5)
25
+ #
26
+ # Running the above script using <code>ruby -r tracer example.rb</code> will
27
+ # output the following trace to STDOUT (Note you can also explicitly
28
+ # <code>require 'tracer'</code>)
29
+ #
30
+ # #0:<internal:lib/rubygems/custom_require>:38:Kernel:<: -
31
+ # #0:example.rb:3::-: class A
32
+ # #0:example.rb:3::C: class A
33
+ # #0:example.rb:4::-: def square(a)
34
+ # #0:example.rb:7::E: end
35
+ # #0:example.rb:9::-: a = A.new
36
+ # #0:example.rb:10::-: a.square(5)
37
+ # #0:example.rb:4:A:>: def square(a)
38
+ # #0:example.rb:5:A:-: return a*a
39
+ # #0:example.rb:6:A:<: end
40
+ # | | | | |
41
+ # | | | | ---------------------+ event
42
+ # | | | ------------------------+ class
43
+ # | | --------------------------+ line
44
+ # | ------------------------------------+ filename
45
+ # ---------------------------------------+ thread
46
+ #
47
+ # Symbol table used for displaying incoming events:
48
+ #
49
+ # +}+:: call a C-language routine
50
+ # +{+:: return from a C-language routine
51
+ # +>+:: call a Ruby method
52
+ # +C+:: start a class or module definition
53
+ # +E+:: finish a class or module definition
54
+ # +-+:: execute code on a new line
55
+ # +^+:: raise an exception
56
+ # +<+:: return from a Ruby method
57
+ #
58
+ # == Copyright
59
+ #
60
+ # by Keiju ISHITSUKA(keiju@ishitsuka.com)
61
+ #
62
+ class Tracer
63
+
64
+ class << self
65
+ # display additional debug information (defaults to false)
66
+ attr_accessor :verbose
67
+ alias verbose? verbose
68
+
69
+ # output stream used to output trace (defaults to STDOUT)
70
+ attr_accessor :stdout
71
+
72
+ # mutex lock used by tracer for displaying trace output
73
+ attr_reader :stdout_mutex
74
+
75
+ # display process id in trace output (defaults to false)
76
+ attr_accessor :display_process_id
77
+ alias display_process_id? display_process_id
78
+
79
+ # display thread id in trace output (defaults to true)
80
+ attr_accessor :display_thread_id
81
+ alias display_thread_id? display_thread_id
82
+
83
+ # display C-routine calls in trace output (defaults to false)
84
+ attr_accessor :display_c_call
85
+ alias display_c_call? display_c_call
86
+ end
87
+
88
+ Tracer::stdout = STDOUT
89
+ Tracer::verbose = false
90
+ Tracer::display_process_id = false
91
+ Tracer::display_thread_id = true
92
+ Tracer::display_c_call = false
93
+
94
+ @stdout_mutex = Thread::Mutex.new
95
+
96
+ # Symbol table used for displaying trace information
97
+ EVENT_SYMBOL = {
98
+ "line" => "-",
99
+ "call" => ">",
100
+ "return" => "<",
101
+ "class" => "C",
102
+ "end" => "E",
103
+ "raise" => "^",
104
+ "c-call" => "}",
105
+ "c-return" => "{",
106
+ "unknown" => "?"
107
+ }
108
+
109
+ def initialize # :nodoc:
110
+ @threads = Hash.new
111
+ if defined? Thread.main
112
+ @threads[Thread.main.object_id] = 0
113
+ else
114
+ @threads[Thread.current.object_id] = 0
115
+ end
116
+
117
+ @get_line_procs = {}
118
+
119
+ @filters = []
120
+ end
121
+
122
+ def stdout # :nodoc:
123
+ Tracer.stdout
124
+ end
125
+
126
+ def on # :nodoc:
127
+ if block_given?
128
+ on
129
+ begin
130
+ yield
131
+ ensure
132
+ off
133
+ end
134
+ else
135
+ set_trace_func method(:trace_func).to_proc
136
+ stdout.print "Trace on\n" if Tracer.verbose?
137
+ end
138
+ end
139
+
140
+ def off # :nodoc:
141
+ set_trace_func nil
142
+ stdout.print "Trace off\n" if Tracer.verbose?
143
+ end
144
+
145
+ def add_filter(p = proc) # :nodoc:
146
+ @filters.push p
147
+ end
148
+
149
+ def set_get_line_procs(file, p = proc) # :nodoc:
150
+ @get_line_procs[file] = p
151
+ end
152
+
153
+ def get_line(file, line) # :nodoc:
154
+ if p = @get_line_procs[file]
155
+ return p.call(line)
156
+ end
157
+
158
+ unless list = SCRIPT_LINES__[file]
159
+ list = File.readlines(file) rescue []
160
+ SCRIPT_LINES__[file] = list
161
+ end
162
+
163
+ if l = list[line - 1]
164
+ l
165
+ else
166
+ "-\n"
167
+ end
168
+ end
169
+
170
+ def get_thread_no # :nodoc:
171
+ if no = @threads[Thread.current.object_id]
172
+ no
173
+ else
174
+ @threads[Thread.current.object_id] = @threads.size
175
+ end
176
+ end
177
+
178
+ def trace_func(event, file, line, id, binding, klass, *) # :nodoc:
179
+ return if file == __FILE__
180
+
181
+ for p in @filters
182
+ return unless p.call event, file, line, id, binding, klass
183
+ end
184
+
185
+ return unless Tracer::display_c_call? or
186
+ event != "c-call" && event != "c-return"
187
+
188
+ Tracer::stdout_mutex.synchronize do
189
+ if EVENT_SYMBOL[event]
190
+ stdout.printf("<%d>", $$) if Tracer::display_process_id?
191
+ stdout.printf("#%d:", get_thread_no) if Tracer::display_thread_id?
192
+ if line == 0
193
+ source = "?\n"
194
+ else
195
+ source = get_line(file, line)
196
+ end
197
+ stdout.printf("%s:%d:%s:%s: %s",
198
+ file,
199
+ line,
200
+ klass || '',
201
+ EVENT_SYMBOL[event],
202
+ source)
203
+ end
204
+ end
205
+
206
+ end
207
+
208
+ # Reference to singleton instance of Tracer
209
+ Single = new
210
+
211
+ ##
212
+ # Start tracing
213
+ #
214
+ # === Example
215
+ #
216
+ # Tracer.on
217
+ # # code to trace here
218
+ # Tracer.off
219
+ #
220
+ # You can also pass a block:
221
+ #
222
+ # Tracer.on {
223
+ # # trace everything in this block
224
+ # }
225
+
226
+ def Tracer.on
227
+ if block_given?
228
+ Single.on{yield}
229
+ else
230
+ Single.on
231
+ end
232
+ end
233
+
234
+ ##
235
+ # Disable tracing
236
+
237
+ def Tracer.off
238
+ Single.off
239
+ end
240
+
241
+ ##
242
+ # Register an event handler <code>p</code> which is called everytime a line
243
+ # in +file_name+ is executed.
244
+ #
245
+ # Example:
246
+ #
247
+ # Tracer.set_get_line_procs("example.rb", lambda { |line|
248
+ # puts "line number executed is #{line}"
249
+ # })
250
+
251
+ def Tracer.set_get_line_procs(file_name, p = proc)
252
+ Single.set_get_line_procs(file_name, p)
253
+ end
254
+
255
+ ##
256
+ # Used to filter unwanted trace output
257
+ #
258
+ # Example which only outputs lines of code executed within the Kernel class:
259
+ #
260
+ # Tracer.add_filter do |event, file, line, id, binding, klass, *rest|
261
+ # "Kernel" == klass.to_s
262
+ # end
263
+
264
+ def Tracer.add_filter(p = proc)
265
+ Single.add_filter(p)
266
+ end
267
+ end
268
+
269
+ # :stopdoc:
270
+ SCRIPT_LINES__ = {} unless defined? SCRIPT_LINES__
271
+
272
+ if $0 == __FILE__
273
+ # direct call
274
+
275
+ $0 = ARGV[0]
276
+ ARGV.shift
277
+ Tracer.on
278
+ require $0
279
+ else
280
+ # call Tracer.on only if required by -r command-line option
281
+ count = caller.count {|bt| %r%/rubygems/core_ext/kernel_require\.rb:% !~ bt}
282
+ if (defined?(Gem) and count == 0) or
283
+ (!defined?(Gem) and count <= 1)
284
+ Tracer.on
285
+ end
286
+ end
287
+ # :startdoc:
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ class Tracer
4
+ VERSION = "0.1.0"
5
+ end
@@ -0,0 +1,26 @@
1
+ begin
2
+ require_relative "lib/tracer/version"
3
+ rescue LoadError
4
+ # for Ruby core repository
5
+ require_relative "version"
6
+ end
7
+
8
+ Gem::Specification.new do |spec|
9
+ spec.name = "tracer"
10
+ spec.version = Tracer::VERSION
11
+ spec.authors = ["Keiju ISHITSUKA"]
12
+ spec.email = ["keiju@ruby-lang.org"]
13
+
14
+ spec.summary = %q{Outputs a source level execution trace of a Ruby program.}
15
+ spec.description = %q{Outputs a source level execution trace of a Ruby program.}
16
+ spec.homepage = "https://github.com/ruby/tracer"
17
+ spec.license = "BSD-2-Clause"
18
+
19
+ spec.files = [".gitignore", ".travis.yml", "Gemfile", "LICENSE.txt", "README.md", "Rakefile", "bin/console", "bin/setup", "lib/tracer.rb", "lib/tracer/version.rb", "tracer.gemspec"]
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_development_dependency "bundler"
25
+ spec.add_development_dependency "rake"
26
+ end
metadata ADDED
@@ -0,0 +1,82 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: tracer
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Keiju ISHITSUKA
8
+ autorequire:
9
+ bindir: exe
10
+ cert_chain: []
11
+ date: 2020-04-01 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Outputs a source level execution trace of a Ruby program.
42
+ email:
43
+ - keiju@ruby-lang.org
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - ".gitignore"
49
+ - ".travis.yml"
50
+ - Gemfile
51
+ - LICENSE.txt
52
+ - README.md
53
+ - Rakefile
54
+ - bin/console
55
+ - bin/setup
56
+ - lib/tracer.rb
57
+ - lib/tracer/version.rb
58
+ - tracer.gemspec
59
+ homepage: https://github.com/ruby/tracer
60
+ licenses:
61
+ - BSD-2-Clause
62
+ metadata: {}
63
+ post_install_message:
64
+ rdoc_options: []
65
+ require_paths:
66
+ - lib
67
+ required_ruby_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: '0'
72
+ required_rubygems_version: !ruby/object:Gem::Requirement
73
+ requirements:
74
+ - - ">="
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ requirements: []
78
+ rubygems_version: 3.2.0.pre1
79
+ signing_key:
80
+ specification_version: 4
81
+ summary: Outputs a source level execution trace of a Ruby program.
82
+ test_files: []