tracer 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []