stack_trace 0.1.0 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b44fd93d88276fa812cfa13f22d2cbee7ab4fa3007c32372ef0a2ba8bccee182
4
- data.tar.gz: a9308ce4f7223a1bd72860c4a1db54d81328ec0992c4135f94c9055c0a7c6f3d
3
+ metadata.gz: 6c29060d98a3ca570339220779da0a26b5d5d8be19994b3ce6a3b808caf51d8c
4
+ data.tar.gz: ecc897ccf6ea4257cc950a2f349450f14e3026a6f32fb2bb45342d3367af63d5
5
5
  SHA512:
6
- metadata.gz: 7e655afe6d165fe287322d42ad5d1244d59f05151656dfbae99efdc3ac8c78030fec755eca1a3264daeff2435e564cec7ffd0a780e9b12ad9d5289135ea342c9
7
- data.tar.gz: 01d0bee421dc2e2c021d3bcb8c38bef1bda022384a711d9d04eaa323043d3af9bbdb7b84dbc5efd30fa82b0fe275bf7bf0e2c4132e8fe0649f636d521988d52a
6
+ metadata.gz: 93084a9322b703052f22124360a76bec238ab218dcd38004167db5d5d71b6b2f191323bd1f233aff153ddfed2944ad204be1471f5ac477efe51e869203950d57
7
+ data.tar.gz: fc08282fc1f32aa5983ebe68213f22a87d5f9a1f34388b1b80ef7e04629237a71570141b005d93291506020e93aa775a56f4edf91573e38fb3b255924d961d69
@@ -0,0 +1,41 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ stack_trace (0.2.0)
5
+
6
+ GEM
7
+ remote: https://rubygems.org/
8
+ specs:
9
+ coderay (1.1.2)
10
+ diff-lcs (1.3)
11
+ method_source (0.9.2)
12
+ pry (0.12.2)
13
+ coderay (~> 1.1.0)
14
+ method_source (~> 0.9.0)
15
+ rake (13.0.1)
16
+ rspec (3.8.0)
17
+ rspec-core (~> 3.8.0)
18
+ rspec-expectations (~> 3.8.0)
19
+ rspec-mocks (~> 3.8.0)
20
+ rspec-core (3.8.2)
21
+ rspec-support (~> 3.8.0)
22
+ rspec-expectations (3.8.4)
23
+ diff-lcs (>= 1.2.0, < 2.0)
24
+ rspec-support (~> 3.8.0)
25
+ rspec-mocks (3.8.1)
26
+ diff-lcs (>= 1.2.0, < 2.0)
27
+ rspec-support (~> 3.8.0)
28
+ rspec-support (3.8.2)
29
+
30
+ PLATFORMS
31
+ ruby
32
+
33
+ DEPENDENCIES
34
+ bundler (~> 2.0)
35
+ pry
36
+ rake (~> 13.0)
37
+ rspec (~> 3.0)
38
+ stack_trace!
39
+
40
+ BUNDLED WITH
41
+ 2.0.1
data/README.md CHANGED
@@ -1,8 +1,6 @@
1
1
  # StackTrace
2
2
 
3
- Welcome to your new gem! In this directory, you'll find the files you need to be able to package up your Ruby library into a gem. Put your Ruby code in the file `lib/stack_trace`. To experiment with that code, run `bin/console` for an interactive prompt.
4
-
5
- TODO: Delete this and the text above, and describe your gem
3
+ StackTrace traces method calls in your application which can give you an overview about how your application works, which objects depends on which ones and what are the bottlenecks.
6
4
 
7
5
  ## Installation
8
6
 
@@ -20,9 +18,186 @@ Or install it yourself as:
20
18
 
21
19
  $ gem install stack_trace
22
20
 
21
+ ## Terminology
22
+
23
+ Before we jump into details we should talk about the two important terms that you should grasp first to understand the tracing output, which are `trace` and `span`.
24
+
25
+ #### Trace
26
+
27
+ Trace is an object which encapsulates the whole process. Whenever you start tracing, there will be a `trace` object associated which has a unique identifier(uuid v4) and holds all the `spans`.
28
+
29
+ #### Span
30
+
31
+ Span holds the information about the actual **unit of work**. StackTrace will create a new span for each method call if it's been told to do so by the configuration. Spans hold all the information that you need about the method calls like the time taken, arguments etc. as well as the child spans if the method calls othre methods.
32
+ You will see detailed information about the spans in the `Getting tracing information` chapter.
33
+
23
34
  ## Usage
24
35
 
25
- TODO: Write usage instructions here
36
+ Using StackTrace gem is pretty straight forward. First you should configure it to set which modules/classes and which methods should be traced and then you can start tracing the execution of your code with `StackTrace::trace` method.
37
+
38
+ #### Configuration
39
+
40
+ With the belove configuration, StackTrace will trace all the methods of **Foo** `module/class` and only the `zoo` method of **Bar** `module/class`.
41
+
42
+ ```ruby
43
+ StackTrace.configure do |config|
44
+ config.enabled = true
45
+ config.modules = {
46
+ Foo => {
47
+ instance_methods: :all,
48
+ class_methods: :all
49
+ },
50
+ Bar => { instance_methods: [:zoo] }
51
+ }
52
+ end
53
+ ```
54
+
55
+ `instance_methods` and `class_methods` can be configured with the following values;
56
+
57
+ - `:all` to trace all methods
58
+ - `:skip_inherited` to trace only the methods defined in module/class
59
+ - `:path` to trace all the classes/modules defined in a specific path regex(Make sure that StackTrace gem is loaded into memory before any files to use this configuration)
60
+ - Array of symbols to specify method names one by one
61
+ - Regular expression to trace all methods with matching method names
62
+
63
+ Also the keys for `modules` hash can have the following values;
64
+
65
+ - `Class/Module` to trace methods of given value
66
+ - An array of `Class/Module` to trace methods of all given values
67
+ - Regular expression to trace methods of all matching modules or classes.
68
+ - { inherits: Class } to trace methods of all classes inherited from base class.
69
+
70
+ Here are the example usages;
71
+
72
+ ```ruby
73
+ StackTrace.configure do |config|
74
+ config.enabled = true
75
+ config.modules = {
76
+ Foo => { instance_methods: :skip_inherited },
77
+ [Too, Joo] => { class_methods: :all }
78
+ /Ba.*/ => { instance_methods: :all },
79
+ { inherits: Zoo } => { instance_methods: [:foo, :bar, :zoo] }
80
+ }
81
+ end
82
+ ```
83
+
84
+ #### Tracing
85
+
86
+ After configuring the StackTrace, you can call `StackTrace::trace` method to create a tracing information of the code execution as shown below;
87
+
88
+ ```ruby
89
+ StackTrace.trace do
90
+ foo = Foo.new
91
+ foo.do_something
92
+ end
93
+ ```
94
+
95
+ #### Getting tracing information
96
+
97
+ Currently StackTrace gem provides tracing information as a Ruby `Hash` object. You can use `StackTrace::Trace::as_json` method to receive the `Hash` for the current trace like so;
98
+
99
+ ```ruby
100
+ StackTrace.trace do
101
+ # Do something usefull
102
+ StackTrace::Trace.as_json
103
+ end
104
+ ```
105
+
106
+ #### What does StackTrace collect?
107
+
108
+ The `Hash` object returned by `StackTrace::Trace::as_json` method has the following structure;
109
+
110
+ * **uuid**: This is a UUID V4 value to identify the trace.
111
+ * **spans**: This is an array of spans which has the following structure;
112
+ * **receiver**: The identifier for the receiver object.
113
+ * **method_name**: The name of the method which this span is created for.
114
+ * **arguments**: Arguments received by the method.
115
+ * **value**: The return value of the method.
116
+ * **exception**: The exception information if an exception is raised in this method. This attribute has the following child attributes:
117
+ * **message**: The error message(`error.message`).
118
+ * **backtrace**: The backtrace information of the excption as an array of strings.
119
+ * **time**: How long the execution of this unit of work took.
120
+ * **spans**: Child spans of the span.
121
+
122
+ Imagine you have the following configuration and class;
123
+
124
+ ```ruby
125
+ class Greeting
126
+ def hello(first_name, last_name)
127
+ "Hello, #{capitalize(first_name)} #{capitalize(last_name)}"
128
+ end
129
+
130
+ def capitalize(string)
131
+ string.capitalize
132
+ end
133
+ end
134
+
135
+ StackTrace.configure do |config|
136
+ config.enabled = true
137
+ config.modules = {
138
+ Greeting => { instance_methods: :all }
139
+ }
140
+ end
141
+ ```
142
+
143
+ The the execution of the following code leads to below return object from `StackTrace::Trace.as_json` method;
144
+
145
+ ```ruby
146
+ StackTrace.trace do
147
+ Greeting.new.hello("john", "doe")
148
+ result = StackTrace::Trace.as_json
149
+ end
150
+
151
+ result == {
152
+ uuid: "12e2a347-8d5a-4d1d-a5ad-efe012ffcdf9",
153
+ spans: [
154
+ {
155
+ receiver: "Greeting#123124312",
156
+ method_name: "initialize",
157
+ arguments: {},
158
+ value: nil,
159
+ exception: nil,
160
+ time: "10.927719116210938 µs",
161
+ spans: []
162
+ },
163
+ {
164
+ receiver: "Greeting#123124312",
165
+ method_name: "hello",
166
+ arguments: {
167
+ first_name: "john",
168
+ last_name: "doe"
169
+ },
170
+ value: "Hello, John Doe",
171
+ exception: nil,
172
+ time: "20.831909134113330 µs",
173
+ spans: [
174
+ {
175
+ receiver: "Greeting#123124312",
176
+ method_name: "capitalize",
177
+ arguments: {
178
+ string: "john"
179
+ },
180
+ value: "John",
181
+ exception: nil,
182
+ time: "6.198883056640625 µs",
183
+ spans: []
184
+ },
185
+ {
186
+ receiver: "Greeting#123124312",
187
+ method_name: "capitalize",
188
+ arguments: {
189
+ string: "doe"
190
+ },
191
+ value: "Doe",
192
+ exception: nil,
193
+ time: "4.291534423828125 µs",
194
+ spans: []
195
+ }
196
+ ]
197
+ }
198
+ ]
199
+ }
200
+ ```
26
201
 
27
202
  ## Development
28
203
 
@@ -32,7 +207,7 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
32
207
 
33
208
  ## Contributing
34
209
 
35
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/stack_trace.
210
+ Bug reports and pull requests are welcome on GitHub at https://github.com/meinac/stack_trace.
36
211
 
37
212
  ## License
38
213
 
@@ -1,43 +1,48 @@
1
1
  # frozen-string-literal: true
2
2
 
3
- require "stack_trace/version"
3
+ require "stack_trace/configuration"
4
+ require "stack_trace/module_extensions"
5
+ require "stack_trace/setup"
4
6
  require "stack_trace/span"
5
7
  require "stack_trace/trace"
8
+ require "stack_trace/version"
6
9
 
7
10
  module StackTrace
8
- def trace(*method_names)
9
- self.traced_methods = method_names
10
- end
11
-
12
- def method_added(method_name)
13
- return unless should_override?(method_name)
11
+ TRACED_EVENTS = %i(call c_call return c_return raise).freeze
14
12
 
15
- overridden_methods << method_name
16
- define_trace_method(method_name)
17
- end
13
+ class << self
14
+ def configure
15
+ yield configuration
16
+ trace_point.enable
17
+ end
18
18
 
19
- private
19
+ def configuration
20
+ @configuration ||= Configuration.new
21
+ end
20
22
 
21
- attr_accessor :traced_methods
23
+ def trace
24
+ return unless block_given?
22
25
 
23
- def should_override?(method_name)
24
- traced_methods.include?(method_name) && !overridden_methods.include?(method_name)
25
- end
26
-
27
- def overridden_methods
28
- @overridden_methods ||= []
29
- end
26
+ Trace.start
27
+ yield
28
+ end
30
29
 
31
- def define_trace_method(method_name)
32
- traced_method_name = traced_method_name(method_name)
33
- alias_method(traced_method_name, method_name)
30
+ def current
31
+ Trace.current
32
+ end
34
33
 
35
- define_method(method_name) do |*args|
36
- Trace.track(method_name, *args) { send(traced_method_name, *args) }
34
+ def as_json
35
+ Trace.as_json
37
36
  end
38
- end
39
37
 
40
- def traced_method_name(original_method_name)
41
- "_traced_#{original_method_name}"
38
+ def trace_point
39
+ @trace_point ||= TracePoint.new(*TRACED_EVENTS) { |tp| Trace.track(tp) }
40
+ end
42
41
  end
43
42
  end
43
+
44
+ TracePoint.new(:class) do |tp|
45
+ tp.binding.eval <<~RUBY
46
+ self.stack_trace_source_location = __FILE__
47
+ RUBY
48
+ end.enable
@@ -0,0 +1,62 @@
1
+ # frozen-string-literal: true
2
+
3
+ require "objspace"
4
+
5
+ module StackTrace
6
+ class Configuration
7
+ CONFIG_ATTRIBUTES = {
8
+ enabled: false,
9
+ modules: {},
10
+ }
11
+
12
+ attr_writer *CONFIG_ATTRIBUTES.keys
13
+
14
+ CONFIG_ATTRIBUTES.each do |attr_name, default_value|
15
+ define_method(attr_name) do
16
+ instance_variable_get("@#{attr_name}") || default_value
17
+ end
18
+ end
19
+
20
+ def for(klass)
21
+ config_holder = config_holder_for(klass)
22
+ modules.find { |module_name_conf, _| config_for_class?(module_name_conf, config_holder) }
23
+ end
24
+
25
+ private
26
+
27
+ # Configuration for StackTrace is done by specifying the class/module itself
28
+ # so if the klass we receive here is a singleton_class, we should get the
29
+ # class/module of that singleton_class first.
30
+ def config_holder_for(klass)
31
+ klass.singleton_class? ? ObjectSpace.each_object(klass).first : klass
32
+ end
33
+
34
+ def config_for_class?(config, klass)
35
+ case config
36
+ when Regexp
37
+ klass.name =~ config
38
+ when Hash
39
+ match_hash_config(config, klass)
40
+ else
41
+ [config].flatten.include?(klass)
42
+ end
43
+ end
44
+
45
+ def match_hash_config(config, klass)
46
+ inherits_config?(klass, config) || path_config?(klass, config)
47
+ end
48
+
49
+ def inherits_config?(klass, inherits: nil, **)
50
+ inherits &&
51
+ klass.ancestors.include?(inherits) &&
52
+ klass != inherits
53
+ end
54
+
55
+ def path_config?(klass, path: nil, **)
56
+ path &&
57
+ klass.respond_to?(:stack_trace_source_location) &&
58
+ klass.stack_trace_source_location &&
59
+ klass.stack_trace_source_location.match(path)
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,79 @@
1
+ # frozen-string-literal: true
2
+
3
+ require "json"
4
+
5
+ RSpec.configuration.before(:suite) do
6
+ StackTrace::Integration::Rspec.create_tracing_directory
7
+ end
8
+
9
+ RSpec.configuration.after(:suite) do
10
+ StackTrace::Integration::Rspec.finish_tracing
11
+ end
12
+
13
+ RSpec.configuration.around(:each) do |example|
14
+ StackTrace.trace do
15
+ example.run
16
+ StackTrace::Integration::Rspec.save_trace_for(example)
17
+ end
18
+ end
19
+
20
+ module StackTrace
21
+ module Integration
22
+ class Rspec
23
+ EXAMPLE_META_KEYS = %i(file_path line_number scoped_id description full_description)
24
+ FINAL_MESSAGE = <<~TEXT
25
+ \e[1m
26
+ StackTrace:
27
+
28
+ Trace information is saved into \e[32m%{file_path}\e[0m
29
+ \e[22m
30
+ TEXT
31
+
32
+ class << self
33
+ def create_tracing_directory
34
+ Dir.mkdir(tracing_dir_path) unless Dir.exist?(tracing_dir_path)
35
+ end
36
+
37
+ def finish_tracing
38
+ save_examples
39
+ print_message
40
+ end
41
+
42
+ def save_trace_for(example)
43
+ examples << example_data(example)
44
+ end
45
+
46
+ private
47
+
48
+ def examples
49
+ @examples ||= []
50
+ end
51
+
52
+ def save_examples
53
+ File.write(tracing_file_path, examples.to_json)
54
+ end
55
+
56
+ def tracing_file_path
57
+ File.join(tracing_dir_path, trace_file_name)
58
+ end
59
+
60
+ def tracing_dir_path
61
+ File.expand_path("stack_trace")
62
+ end
63
+
64
+ def trace_file_name
65
+ @trace_file_name ||= Time.now.strftime('%d_%m_%Y %H_%M_%S.json')
66
+ end
67
+
68
+ def example_data(example)
69
+ example.metadata.slice(*EXAMPLE_META_KEYS)
70
+ .merge!(trace: Trace.current.as_json)
71
+ end
72
+
73
+ def print_message
74
+ puts format(FINAL_MESSAGE, file_path: tracing_file_path)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,13 @@
1
+ # frozen-string-literal: true
2
+
3
+ module StackTrace
4
+ module ModuleExtensions
5
+ attr_accessor :stack_trace_source_location
6
+
7
+ def trace_method?(method_id)
8
+ Setup.trackable?(self, method_id)
9
+ end
10
+ end
11
+ end
12
+
13
+ Module.include(StackTrace::ModuleExtensions)
@@ -0,0 +1,62 @@
1
+ # frozen-string-literal: true
2
+
3
+ module StackTrace
4
+ class Setup
5
+ class << self
6
+ def trackable?(mod, method_id)
7
+ store[mod].trace?(method_id)
8
+ end
9
+
10
+ def store
11
+ @store ||= Hash.new do |h, k|
12
+ h[k.singleton_class] = new(k, :class_methods)
13
+ h[k] = new(k, :instance_methods)
14
+ end
15
+ end
16
+ end
17
+
18
+ def initialize(klass, context)
19
+ self.klass = klass
20
+ self.context = context
21
+ end
22
+
23
+ def trace?(method_id)
24
+ enabled? && traced_method?(method_id)
25
+ end
26
+
27
+ private
28
+
29
+ attr_accessor :klass, :context
30
+
31
+ def enabled?
32
+ defined?(@enabled) ? @enabled : (@enabled = !config.nil?)
33
+ end
34
+
35
+ def config
36
+ @config ||= StackTrace.configuration.for(klass)
37
+ end
38
+
39
+ def traced_method?(method_id)
40
+ method_lookup[method_id]
41
+ end
42
+
43
+ def method_lookup
44
+ @method_lookup ||= Hash.new { |lookup, method_id| lookup[method_id] = method_enabled?(method_id) }
45
+ end
46
+
47
+ def method_enabled?(method_id)
48
+ case method_config
49
+ when Array
50
+ method_config.include?(method_id)
51
+ when Symbol
52
+ method_config != :skip_inherited || instance_methods(false).include?(method_id)
53
+ when Regexp
54
+ method_id =~ method_config
55
+ end
56
+ end
57
+
58
+ def method_config
59
+ @method_config ||= config[1].fetch(context, [])
60
+ end
61
+ end
62
+ end
@@ -2,29 +2,69 @@
2
2
 
3
3
  module StackTrace
4
4
  class Span
5
- attr_accessor :value, :exception
6
- attr_reader :method_name, :args, :spans
5
+ class << self
6
+ def start_from(trace_point, parent)
7
+ new(
8
+ receiver(trace_point),
9
+ trace_point.method_id,
10
+ extract_arguments(trace_point),
11
+ parent
12
+ )
13
+ end
7
14
 
8
- def initialize(method_name, *args)
9
- self.started_at = Time.now.to_f
15
+ private
16
+
17
+ def receiver(trace_point)
18
+ trace_point.binding.eval("self").to_s
19
+ end
20
+
21
+ def extract_arguments(trace_point)
22
+ trace_point.parameters
23
+ .map(&:last)
24
+ .each_with_object({}) do |parameter, memo|
25
+ memo[parameter] = trace_point.binding.eval(parameter.to_s).inspect
26
+ end
27
+ end
28
+ end
29
+
30
+ attr_writer :exception
31
+
32
+ def initialize(receiver, method_name, args, parent)
33
+ self.receiver = receiver
10
34
  self.method_name = method_name
11
35
  self.args = args
36
+ self.parent = parent
37
+ self.started_at = Time.now.to_f
12
38
  self.spans = []
13
39
  end
14
40
 
15
- def add(method_name, *args)
16
- (spans << span = Span.new(method_name, *args)) && span
41
+ def <<(span)
42
+ (spans << span) && span
17
43
  end
18
44
 
19
- def close
20
- @finished_at = Time.now.to_f
21
- @closed = true
45
+ def close(trace_point)
46
+ self.value = trace_point.return_value.inspect
47
+ self.finished_at = Time.now.to_f
48
+ parent
22
49
  end
23
50
 
24
- def open?
25
- !@closed
51
+ def as_json
52
+ {
53
+ receiver: receiver,
54
+ method_name: method_name,
55
+ arguments: args,
56
+ value: value,
57
+ exception: exception_as_json,
58
+ time: time,
59
+ spans: spans.map(&:as_json)
60
+ }
26
61
  end
27
62
 
63
+ private
64
+
65
+ attr_accessor :receiver, :method_name, :args, :value, :parent, :spans, :started_at, :finished_at
66
+ attr_reader :exception
67
+
28
68
  def time
29
69
  case time_ns
30
70
  when 0..1_000
@@ -38,22 +78,15 @@ module StackTrace
38
78
  end
39
79
  end
40
80
 
41
- def as_json
81
+ def exception_as_json
82
+ return unless exception
83
+
42
84
  {
43
- method_name: method_name,
44
- arguments: args,
45
- value: value,
46
- exception: exception,
47
- time: time,
48
- spans: spans.map(&:as_json)
85
+ message: exception.message,
86
+ backtrace: exception.backtrace
49
87
  }
50
88
  end
51
89
 
52
- private
53
-
54
- attr_accessor :started_at, :finished_at
55
- attr_writer :method_name, :args, :spans
56
-
57
90
  def time_ns
58
91
  (finished_at - started_at) * 1_000_000_000
59
92
  end
@@ -1,16 +1,16 @@
1
1
  # frozen-string-literal: true
2
2
 
3
+ require "securerandom"
4
+
3
5
  module StackTrace
4
6
  class Trace
7
+ TRACE_START_EVENTS = %i(call c_call).freeze
8
+ TRACE_END_EVENTS = %i(return c_return).freeze
9
+ TRACE_RAISE_EVENT = :raise
10
+
5
11
  class << self
6
- def track(method_name, *args)
7
- span = current.add(method_name, *args)
8
- span.value = yield
9
- rescue StandardError => e
10
- span.exception = e
11
- raise e
12
- ensure
13
- span.close
12
+ def track(trace_point)
13
+ current.add(trace_point) if trackable?(trace_point)
14
14
  end
15
15
 
16
16
  def start
@@ -24,32 +24,60 @@ module StackTrace
24
24
  def as_json
25
25
  current.as_json
26
26
  end
27
+
28
+ private
29
+
30
+ def trackable?(trace_point)
31
+ trace_point.defined_class&.trace_method?(trace_point.method_id)
32
+ end
27
33
  end
28
34
 
29
- attr_reader :spans
35
+ attr_reader :uuid, :spans
30
36
 
31
37
  def initialize
38
+ @uuid = SecureRandom.uuid
32
39
  @spans = []
33
40
  end
34
41
 
35
- def add(method_name, *args)
36
- add_to_active_span(method_name, *args) || create_new_span(method_name, *args)
42
+ def add(trace_point)
43
+ case trace_point.event
44
+ when *TRACE_START_EVENTS
45
+ create_new_span(trace_point)
46
+ when *TRACE_END_EVENTS
47
+ close_current_span(trace_point)
48
+ else
49
+ apply_exception_to_current_span(trace_point)
50
+ end
37
51
  end
38
52
 
39
53
  def as_json
40
- { spans: spans.map(&:as_json) }
54
+ {
55
+ uuid: uuid,
56
+ spans: spans.map(&:as_json)
57
+ }
58
+ end
59
+
60
+ def <<(span)
61
+ spans << span
41
62
  end
42
63
 
43
64
  private
44
65
 
45
- def add_to_active_span(method_name, *args)
46
- return unless @current_span&.open?
66
+ def create_new_span(trace_point)
67
+ span = Span.start_from(trace_point, container)
68
+ container << (@active_span = span)
69
+ end
70
+
71
+ def close_current_span(trace_point)
72
+ @active_span = @active_span&.close(trace_point)
73
+ end
47
74
 
48
- @current_span.add(method_name, *args)
75
+ def apply_exception_to_current_span(trace_point)
76
+ @active_span.exception = trace_point.raised_exception
49
77
  end
50
78
 
51
- def create_new_span(method_name, *args)
52
- (spans << @current_span = Span.new(method_name, *args)) && @current_span
79
+ def container
80
+ @active_span || self
53
81
  end
54
82
  end
55
83
  end
@@ -1,3 +1,3 @@
1
1
  module StackTrace
2
- VERSION = "0.1.0"
2
+ VERSION = "0.2.0"
3
3
  end
@@ -23,7 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ["lib"]
25
25
 
26
+ spec.required_ruby_version = '>= 1.9.2'
27
+
26
28
  spec.add_development_dependency "bundler", "~> 2.0"
27
- spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rake", "~> 13.0"
28
30
  spec.add_development_dependency "rspec", "~> 3.0"
31
+ spec.add_development_dependency "pry"
29
32
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stack_trace
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mehmet Emin INAC
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2020-02-27 00:00:00.000000000 Z
11
+ date: 2020-10-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -30,14 +30,14 @@ dependencies:
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '10.0'
33
+ version: '13.0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: '10.0'
40
+ version: '13.0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: rspec
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: pry
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
55
69
  description: This library tracks the execution of methods, their arguments, return
56
70
  values etc.
57
71
  email:
@@ -64,12 +78,17 @@ files:
64
78
  - ".rspec"
65
79
  - ".travis.yml"
66
80
  - Gemfile
81
+ - Gemfile.lock
67
82
  - LICENSE.txt
68
83
  - README.md
69
84
  - Rakefile
70
85
  - bin/console
71
86
  - bin/setup
72
87
  - lib/stack_trace.rb
88
+ - lib/stack_trace/configuration.rb
89
+ - lib/stack_trace/integration/rspec.rb
90
+ - lib/stack_trace/module_extensions.rb
91
+ - lib/stack_trace/setup.rb
73
92
  - lib/stack_trace/span.rb
74
93
  - lib/stack_trace/trace.rb
75
94
  - lib/stack_trace/version.rb
@@ -86,14 +105,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
86
105
  requirements:
87
106
  - - ">="
88
107
  - !ruby/object:Gem::Version
89
- version: '0'
108
+ version: 1.9.2
90
109
  required_rubygems_version: !ruby/object:Gem::Requirement
91
110
  requirements:
92
111
  - - ">="
93
112
  - !ruby/object:Gem::Version
94
113
  version: '0'
95
114
  requirements: []
96
- rubygems_version: 3.0.3
115
+ rubygems_version: 3.0.8
97
116
  signing_key:
98
117
  specification_version: 4
99
118
  summary: Tracks the execution of methods configured