gun_dog 0.0.1
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 +7 -0
- data/.gitignore +12 -0
- data/.rspec +2 -0
- data/.travis.yml +5 -0
- data/Gemfile +6 -0
- data/README.md +60 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/gun_dog.gemspec +30 -0
- data/lib/gun_dog/call_record.rb +73 -0
- data/lib/gun_dog/indexed_array.rb +24 -0
- data/lib/gun_dog/method_owner_stack_frame.rb +7 -0
- data/lib/gun_dog/trace_maker.rb +79 -0
- data/lib/gun_dog/trace_report.rb +74 -0
- data/lib/gun_dog/trace_stack.rb +57 -0
- data/lib/gun_dog/version.rb +3 -0
- data/lib/gun_dog.rb +17 -0
- metadata +144 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 61ac60f86383d4ec2f4df7d5dba8d6ab0f503dc7
|
4
|
+
data.tar.gz: 4dba94dd287a55fd391fdae2bce8168d2dc84bf9
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 340f5de44210a25028553ddb84a31183b997327258eb30331c1cfb0683450f77aef5518fb2cb18492d3aa427828bcd827782d05c7bccdfe6889777dc12d60d38
|
7
|
+
data.tar.gz: 595cb603c9f1c57030f5cbffa9e4ceb419ffe95869e3f085fb79aaea7fb82405cc56186d6439299e36b89527c75fc88f0f439e73a969a374294957cbef32534c
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.travis.yml
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# GunDog
|
2
|
+
|
3
|
+
GunDog is a Tracepoint tool for finding the interface of particular classes
|
4
|
+
within a given context.
|
5
|
+
|
6
|
+
Often times you'd like to refactor a class, but are not sure about what sort of
|
7
|
+
calls the class may receive. GunDog sets up special Tracepoint listeners to log
|
8
|
+
and record code execution metrics on a given class.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby gem 'gun_dog' ```
|
15
|
+
|
16
|
+
And then execute:
|
17
|
+
|
18
|
+
$ bundle
|
19
|
+
|
20
|
+
Or install it yourself as:
|
21
|
+
|
22
|
+
$ gem install gun_dog
|
23
|
+
|
24
|
+
## Usage
|
25
|
+
|
26
|
+
To use GunDog find the general area were you'd like to refactor a class.
|
27
|
+
|
28
|
+
```
|
29
|
+
trace = GunDog.trace(MyClassName) do
|
30
|
+
some_code_that_executes_your_class
|
31
|
+
end
|
32
|
+
```
|
33
|
+
|
34
|
+
Trace is a GunDog::TraceReport object that can be saved to JSON (and loaded from
|
35
|
+
JSON) for analysis.
|
36
|
+
|
37
|
+
GunDog is still a pup - here are some upcoming features.
|
38
|
+
|
39
|
+
- [ ] TraceReport introspect methods from CallRecords
|
40
|
+
- [ ] TraceReport pretty reports
|
41
|
+
- [ ] Trace Multiple Classes with one Dog
|
42
|
+
- [ ] Inhibit: Generate warnings when methods in a TraceReport are called.
|
43
|
+
|
44
|
+
|
45
|
+
## Development
|
46
|
+
|
47
|
+
After checking out the repo, run `bin/setup` to install dependencies. Then, run
|
48
|
+
`rake spec` to run the tests. You can also run `bin/console` for an interactive
|
49
|
+
prompt that will allow you to experiment.
|
50
|
+
|
51
|
+
To install this gem onto your local machine, run `bundle exec rake install`. To
|
52
|
+
release a new version, update the version number in `version.rb`, and then run
|
53
|
+
`bundle exec rake release`, which will create a git tag for the version, push
|
54
|
+
git commits and tags, and push the `.gem` file to
|
55
|
+
[rubygems.org](https://rubygems.org).
|
56
|
+
|
57
|
+
## Contributing
|
58
|
+
|
59
|
+
Bug reports and pull requests are welcome on GitHub at
|
60
|
+
https://github.com/stephenprater/gun_dog.
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require "bundler/setup"
|
4
|
+
require "gun_dog"
|
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__)
|
data/bin/setup
ADDED
data/gun_dog.gemspec
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path("../lib", __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require "gun_dog/version"
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "gun_dog"
|
8
|
+
spec.version = GunDog::VERSION
|
9
|
+
spec.authors = ["Stephen Prater"]
|
10
|
+
spec.email = ["me@stephenprater.com"]
|
11
|
+
|
12
|
+
spec.summary = %q{Log callsite information for a given class.}
|
13
|
+
spec.description = %q{Log callsite information for a given class.}
|
14
|
+
spec.homepage = "http://github.com/stephenprater/gun_dog"
|
15
|
+
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
17
|
+
f.match(%r{^(test|spec|features)/})
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_dependency "multi_json", "~> 1.12"
|
24
|
+
spec.add_dependency "activesupport", ">= 4.2.9"
|
25
|
+
|
26
|
+
spec.add_development_dependency "bundler", "~> 1.15"
|
27
|
+
spec.add_development_dependency "rake", "~> 10.0"
|
28
|
+
spec.add_development_dependency "rspec", "~> 3.0"
|
29
|
+
spec.add_development_dependency "pry-byebug"
|
30
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
module GunDog
|
2
|
+
class CallRecord
|
3
|
+
attr_accessor :args, :return_value, :method_name
|
4
|
+
attr_accessor :stack
|
5
|
+
|
6
|
+
attr_writer :internal, :cyclical
|
7
|
+
|
8
|
+
def self.from_json(json)
|
9
|
+
cr = new(const_get(json['klass']),
|
10
|
+
json['method_name'],
|
11
|
+
class_method: json['class_method'])
|
12
|
+
|
13
|
+
cr.instance_eval do
|
14
|
+
@internal = json['internal']
|
15
|
+
@cyclical = json['cyclical']
|
16
|
+
@args = json['args']
|
17
|
+
@return_value = json['return_value']
|
18
|
+
@stack = json['stack']
|
19
|
+
end
|
20
|
+
|
21
|
+
cr
|
22
|
+
end
|
23
|
+
|
24
|
+
def initialize(klass, method_name, class_method: false)
|
25
|
+
@klass = klass
|
26
|
+
@method_name = method_name
|
27
|
+
@class_method = class_method
|
28
|
+
end
|
29
|
+
|
30
|
+
def method_location
|
31
|
+
"#{@klass}#{method_separator}#{method_name}"
|
32
|
+
end
|
33
|
+
|
34
|
+
def internal?
|
35
|
+
!!@internal
|
36
|
+
end
|
37
|
+
|
38
|
+
def cyclical?
|
39
|
+
!!@cyclical
|
40
|
+
end
|
41
|
+
|
42
|
+
def class_method?
|
43
|
+
!!@class_method
|
44
|
+
end
|
45
|
+
|
46
|
+
def to_s
|
47
|
+
"def #{method_name}(#{type_signatures(args)}) => #{return_value}"
|
48
|
+
end
|
49
|
+
|
50
|
+
def as_json
|
51
|
+
{
|
52
|
+
"klass" => @klass,
|
53
|
+
"method_name" => method_name,
|
54
|
+
"class_method" => class_method?,
|
55
|
+
"internal" => internal?,
|
56
|
+
"cyclical" => cyclical?,
|
57
|
+
"args" => args,
|
58
|
+
"return_value" => return_value,
|
59
|
+
"stack" => stack
|
60
|
+
}.reject { |_,v| v.nil? }
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def type_signatures(args)
|
66
|
+
args.each_pair.map { |k,v| "#{k} : #{v}" }.join(', ')
|
67
|
+
end
|
68
|
+
|
69
|
+
def method_separator
|
70
|
+
class_method? ? '.' : '#'
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module GunDog
|
2
|
+
class IndexedArray < Array
|
3
|
+
attr_reader :lut
|
4
|
+
|
5
|
+
def initialize(*args)
|
6
|
+
super(args)
|
7
|
+
@lut = {}
|
8
|
+
end
|
9
|
+
|
10
|
+
def <<(obj)
|
11
|
+
super(obj)
|
12
|
+
@lut[obj.object_id] = length
|
13
|
+
obj
|
14
|
+
end
|
15
|
+
|
16
|
+
def index_of_object(obj)
|
17
|
+
@lut.fetch(obj.object_id)
|
18
|
+
end
|
19
|
+
|
20
|
+
def find_object(obj)
|
21
|
+
at(index_of_object(obj))
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
module GunDog
|
2
|
+
class TraceMaker
|
3
|
+
attr_reader :trace_report, :return_trace, :call_trace, :klass
|
4
|
+
|
5
|
+
def initialize(klass, &exec_block)
|
6
|
+
@klass = klass
|
7
|
+
@trace_report = TraceReport.new(klass)
|
8
|
+
@trace_report.stack << MethodOwnerStackFrame.new(GunDog, :trace)
|
9
|
+
@exec_block = exec_block
|
10
|
+
end
|
11
|
+
|
12
|
+
def exec
|
13
|
+
set_trace
|
14
|
+
|
15
|
+
call_trace.enable do
|
16
|
+
return_trace.enable do
|
17
|
+
@exec_block.call
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
trace_report.finalize_report
|
22
|
+
trace_report
|
23
|
+
ensure
|
24
|
+
call_trace.disable
|
25
|
+
return_trace.disable
|
26
|
+
end
|
27
|
+
|
28
|
+
def set_trace
|
29
|
+
set_return_trace
|
30
|
+
set_call_trace
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_return_trace
|
34
|
+
@return_trace ||= TracePoint.new(:return) do |tp|
|
35
|
+
trace_report.stack.pop
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def set_call_trace
|
40
|
+
@call_trace ||= TracePoint.new(:call) do |tp|
|
41
|
+
trace_report.stack << MethodOwnerStackFrame.new(tp.defined_class, tp.method_id)
|
42
|
+
next unless tp.defined_class == klass || tp.defined_class == klass.singleton_class
|
43
|
+
|
44
|
+
tp.disable
|
45
|
+
|
46
|
+
call_record = CallRecord.new(klass, tp.method_id, class_method: tp.defined_class == klass.singleton_class)
|
47
|
+
called_method = tp.self.method(tp.method_id)
|
48
|
+
call_record.args = called_method.parameters.each.with_object({}) do |p, memo|
|
49
|
+
memo[p.last] = tp.binding.local_variable_get(p.last).class
|
50
|
+
end
|
51
|
+
|
52
|
+
trace_report.call_records << call_record
|
53
|
+
|
54
|
+
set_method_return_trace(call_record).enable
|
55
|
+
|
56
|
+
tp.enable
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def set_method_return_trace(call_record)
|
61
|
+
# instantiate a new return tracepoint to watch for the return of this
|
62
|
+
# method only
|
63
|
+
#
|
64
|
+
TracePoint.new(:return) do |mrt|
|
65
|
+
next if mrt.method_id != call_record.method_name
|
66
|
+
mrt.disable
|
67
|
+
call_record.return_value = mrt.return_value.class
|
68
|
+
|
69
|
+
if trace_report.stack.internal_stack?
|
70
|
+
call_record.internal = true
|
71
|
+
call_record.stack = trace_report.stack.dup
|
72
|
+
elsif trace_report.stack.cyclical_stack?
|
73
|
+
call_record.cyclical = true
|
74
|
+
call_record.stack = trace_report.stack.dup
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module GunDog
|
2
|
+
class TraceReport
|
3
|
+
attr_reader :klass
|
4
|
+
|
5
|
+
def self.load(filename)
|
6
|
+
json = MultiJson.load(File.open(filename, 'r') { |f| f.read })
|
7
|
+
from_json(json)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.from_json(json)
|
11
|
+
tr = new(nil)
|
12
|
+
|
13
|
+
tr.instance_eval do
|
14
|
+
@klass = Kernel.const_get(json['klass'])
|
15
|
+
@stack = TraceStack.from_json(json.slice('klass','collaborating_classes'))
|
16
|
+
@call_records = json['call_records'].map { |cr| CallRecord.from_json(cr) }
|
17
|
+
end
|
18
|
+
|
19
|
+
tr
|
20
|
+
end
|
21
|
+
|
22
|
+
def call_records
|
23
|
+
@call_records ||= []
|
24
|
+
end
|
25
|
+
|
26
|
+
def initialize(klass)
|
27
|
+
@klass = klass
|
28
|
+
end
|
29
|
+
|
30
|
+
def collaborating_classes
|
31
|
+
stack.collaborating_classes - [GunDog, klass]
|
32
|
+
end
|
33
|
+
|
34
|
+
def stack
|
35
|
+
@stack ||= TraceStack.new(klass)
|
36
|
+
end
|
37
|
+
|
38
|
+
def finalize_report
|
39
|
+
@call_records.freeze
|
40
|
+
@stack.clear.freeze
|
41
|
+
@finalized = true
|
42
|
+
end
|
43
|
+
|
44
|
+
def finalized?
|
45
|
+
!!@finalized
|
46
|
+
end
|
47
|
+
|
48
|
+
def save(filename)
|
49
|
+
File.open(filename, 'w') { |f| f.puts(to_json) }
|
50
|
+
end
|
51
|
+
|
52
|
+
|
53
|
+
def as_json
|
54
|
+
{
|
55
|
+
"klass" => klass,
|
56
|
+
"collaborating_classes" => collaborating_classes.to_a,
|
57
|
+
"call_records" => call_records.map(&:as_json)
|
58
|
+
}
|
59
|
+
end
|
60
|
+
|
61
|
+
def to_json
|
62
|
+
MultiJson.dump(as_json)
|
63
|
+
end
|
64
|
+
|
65
|
+
def find_call_record(doc_name)
|
66
|
+
@find_cache ||= @call_records.group_by(&:method_location)
|
67
|
+
@find_cache[doc_name]
|
68
|
+
end
|
69
|
+
|
70
|
+
def method_list
|
71
|
+
@call_records.map(&:method_location)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
module GunDog
|
2
|
+
class TraceStack < Array
|
3
|
+
attr_reader :collaborating_classes, :klass
|
4
|
+
|
5
|
+
def self.from_json(json)
|
6
|
+
ts = new(json['klass'])
|
7
|
+
|
8
|
+
ts.instance_eval do
|
9
|
+
@collaborating_classes = Set.new(json['collaborating_classes'].map { |k| Kernel.const_get(k) })
|
10
|
+
end
|
11
|
+
|
12
|
+
ts
|
13
|
+
end
|
14
|
+
|
15
|
+
def classes_in_stack
|
16
|
+
self.group_by(&:klass).keys.to_set
|
17
|
+
end
|
18
|
+
|
19
|
+
def initialize(klass)
|
20
|
+
@klass = klass
|
21
|
+
@collaborating_classes = Set.new
|
22
|
+
end
|
23
|
+
|
24
|
+
def internal_stack?
|
25
|
+
# if the set of the classes contained in the trace is equivalent to the
|
26
|
+
# set of our own class then it is an interal stack (ie - all methods are
|
27
|
+
# internal to the traced class)
|
28
|
+
call_stack.classes_in_stack == self_set
|
29
|
+
end
|
30
|
+
|
31
|
+
def cyclical_stack?
|
32
|
+
# if the set of classes contained in the trace is a superset of the set
|
33
|
+
# of our class then it is a cyclical stack (ie, it contains calls both
|
34
|
+
# within and without of the class)
|
35
|
+
call_stack.classes_in_stack > self_set
|
36
|
+
end
|
37
|
+
|
38
|
+
def preceded_by_traced_klass?
|
39
|
+
traced_klasses = self.map(&:klass)
|
40
|
+
traced_klasses.include?(klass) || traced_klasses.include?(klass.singleton_class)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self_set
|
44
|
+
[klass].to_set
|
45
|
+
end
|
46
|
+
|
47
|
+
def call_stack
|
48
|
+
# the stack excluding the sentinel (element zero) and our selves (element -1)
|
49
|
+
self.slice(1 .. -2) || TraceStack.new(klass)
|
50
|
+
end
|
51
|
+
|
52
|
+
def <<(frame)
|
53
|
+
collaborating_classes.add(frame.klass) if preceded_by_traced_klass?
|
54
|
+
super(frame)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
data/lib/gun_dog.rb
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
require "gun_dog/version"
|
2
|
+
require 'json'
|
3
|
+
require 'multi_json'
|
4
|
+
require 'active_support/core_ext/hash/slice'
|
5
|
+
require 'active_support/core_ext/string/filters'
|
6
|
+
|
7
|
+
module GunDog
|
8
|
+
autoload :MethodOwnerStackFrame, 'gun_dog/method_owner_stack_frame'
|
9
|
+
autoload :CallRecord, 'gun_dog/call_record'
|
10
|
+
autoload :TraceMaker, 'gun_dog/trace_maker'
|
11
|
+
autoload :TraceReport, 'gun_dog/trace_report'
|
12
|
+
autoload :TraceStack, 'gun_dog/trace_stack'
|
13
|
+
|
14
|
+
def self.trace(klass, &block)
|
15
|
+
TraceMaker.new(klass, &block).exec
|
16
|
+
end
|
17
|
+
end
|
metadata
ADDED
@@ -0,0 +1,144 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: gun_dog
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Prater
|
8
|
+
autorequire:
|
9
|
+
bindir: exe
|
10
|
+
cert_chain: []
|
11
|
+
date: 2017-10-12 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: multi_json
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - "~>"
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '1.12'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - "~>"
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '1.12'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: activesupport
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 4.2.9
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 4.2.9
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: bundler
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - "~>"
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '1.15'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - "~>"
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '1.15'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rake
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '10.0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '10.0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: rspec
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - "~>"
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '3.0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - "~>"
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '3.0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
description: Log callsite information for a given class.
|
98
|
+
email:
|
99
|
+
- me@stephenprater.com
|
100
|
+
executables: []
|
101
|
+
extensions: []
|
102
|
+
extra_rdoc_files: []
|
103
|
+
files:
|
104
|
+
- ".gitignore"
|
105
|
+
- ".rspec"
|
106
|
+
- ".travis.yml"
|
107
|
+
- Gemfile
|
108
|
+
- README.md
|
109
|
+
- Rakefile
|
110
|
+
- bin/console
|
111
|
+
- bin/setup
|
112
|
+
- gun_dog.gemspec
|
113
|
+
- lib/gun_dog.rb
|
114
|
+
- lib/gun_dog/call_record.rb
|
115
|
+
- lib/gun_dog/indexed_array.rb
|
116
|
+
- lib/gun_dog/method_owner_stack_frame.rb
|
117
|
+
- lib/gun_dog/trace_maker.rb
|
118
|
+
- lib/gun_dog/trace_report.rb
|
119
|
+
- lib/gun_dog/trace_stack.rb
|
120
|
+
- lib/gun_dog/version.rb
|
121
|
+
homepage: http://github.com/stephenprater/gun_dog
|
122
|
+
licenses: []
|
123
|
+
metadata: {}
|
124
|
+
post_install_message:
|
125
|
+
rdoc_options: []
|
126
|
+
require_paths:
|
127
|
+
- lib
|
128
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
129
|
+
requirements:
|
130
|
+
- - ">="
|
131
|
+
- !ruby/object:Gem::Version
|
132
|
+
version: '0'
|
133
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
134
|
+
requirements:
|
135
|
+
- - ">="
|
136
|
+
- !ruby/object:Gem::Version
|
137
|
+
version: '0'
|
138
|
+
requirements: []
|
139
|
+
rubyforge_project:
|
140
|
+
rubygems_version: 2.5.2
|
141
|
+
signing_key:
|
142
|
+
specification_version: 4
|
143
|
+
summary: Log callsite information for a given class.
|
144
|
+
test_files: []
|