stack_trace 0.2.1 → 0.4.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.tool-versions +1 -0
- data/CODE_OF_CONDUCT.md +84 -0
- data/Gemfile +6 -1
- data/Gemfile.lock +19 -23
- data/LICENSE.txt +1 -1
- data/README.md +15 -191
- data/Rakefile +8 -1
- data/ext/stack_trace/configuration.c +23 -0
- data/ext/stack_trace/configuration.h +6 -0
- data/ext/stack_trace/current_trace.c +43 -0
- data/ext/stack_trace/current_trace.h +7 -0
- data/ext/stack_trace/debug.c +43 -0
- data/ext/stack_trace/debug.h +37 -0
- data/ext/stack_trace/event_producer.c +65 -0
- data/ext/stack_trace/event_producer.h +3 -0
- data/ext/stack_trace/event_store.c +109 -0
- data/ext/stack_trace/event_store.h +5 -0
- data/ext/stack_trace/extconf.rb +7 -0
- data/ext/stack_trace/sidecar.c +77 -0
- data/ext/stack_trace/sidecar.h +1 -0
- data/ext/stack_trace/span.c +106 -0
- data/ext/stack_trace/span.h +9 -0
- data/ext/stack_trace/stack_trace.c +54 -0
- data/ext/stack_trace/trace.c +132 -0
- data/ext/stack_trace/trace.h +8 -0
- data/ext/stack_trace/types/event.h +31 -0
- data/ext/stack_trace/types/span.h +22 -0
- data/ext/stack_trace/types/trace.h +15 -0
- data/ext/stack_trace/utils.c +8 -0
- data/ext/stack_trace/utils.h +1 -0
- data/lib/stack_trace/argument_extractor.rb +22 -0
- data/lib/stack_trace/configuration.rb +2 -57
- data/lib/stack_trace/patch/class.rb +7 -0
- data/lib/stack_trace/patch/false_class.rb +7 -0
- data/lib/stack_trace/patch/nil_class.rb +7 -0
- data/lib/stack_trace/patch/numeric.rb +7 -0
- data/lib/stack_trace/patch/object.rb +7 -0
- data/lib/stack_trace/patch/symbol.rb +7 -0
- data/lib/stack_trace/patch/true_class.rb +7 -0
- data/lib/stack_trace/version.rb +3 -1
- data/lib/stack_trace.rb +30 -34
- data/stack_trace.gemspec +22 -20
- metadata +45 -77
- data/.gitignore +0 -11
- data/.travis.yml +0 -7
- data/bin/console +0 -14
- data/bin/setup +0 -8
- data/lib/stack_trace/integration/rspec.rb +0 -79
- data/lib/stack_trace/module_extensions.rb +0 -13
- data/lib/stack_trace/setup.rb +0 -62
- data/lib/stack_trace/span.rb +0 -94
- data/lib/stack_trace/trace.rb +0 -83
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ac9e909692657f9e1b0cd9fc6475faf494458954513aa2e659e9faeacfb3d51b
|
4
|
+
data.tar.gz: d4819f5e40ef2d81cc5cc539247916ed16416eed9400f63007fe85edc8c9c4cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 072443043f5910dfd02ded927653a23abacefede4f17fd87155521275818b0b90aa769544c30e9f06b5c46c24193e9bac12f711ae39c4f887340d435402f40c2
|
7
|
+
data.tar.gz: d3a5c0ae3803776ea0ad504c825c75ca0d9a70d5153a22133f809633631f824a7540fe7dd72c76c9e4eece214bb578d04765445f39089adadc6076abbe7af10a
|
data/.tool-versions
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
ruby 3.0.4
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,84 @@
|
|
1
|
+
# Contributor Covenant Code of Conduct
|
2
|
+
|
3
|
+
## Our Pledge
|
4
|
+
|
5
|
+
We as members, contributors, and leaders pledge to make participation in our community a harassment-free experience for everyone, regardless of age, body size, visible or invisible disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation.
|
6
|
+
|
7
|
+
We pledge to act and interact in ways that contribute to an open, welcoming, diverse, inclusive, and healthy community.
|
8
|
+
|
9
|
+
## Our Standards
|
10
|
+
|
11
|
+
Examples of behavior that contributes to a positive environment for our community include:
|
12
|
+
|
13
|
+
* Demonstrating empathy and kindness toward other people
|
14
|
+
* Being respectful of differing opinions, viewpoints, and experiences
|
15
|
+
* Giving and gracefully accepting constructive feedback
|
16
|
+
* Accepting responsibility and apologizing to those affected by our mistakes, and learning from the experience
|
17
|
+
* Focusing on what is best not just for us as individuals, but for the overall community
|
18
|
+
|
19
|
+
Examples of unacceptable behavior include:
|
20
|
+
|
21
|
+
* The use of sexualized language or imagery, and sexual attention or
|
22
|
+
advances of any kind
|
23
|
+
* Trolling, insulting or derogatory comments, and personal or political attacks
|
24
|
+
* Public or private harassment
|
25
|
+
* Publishing others' private information, such as a physical or email
|
26
|
+
address, without their explicit permission
|
27
|
+
* Other conduct which could reasonably be considered inappropriate in a
|
28
|
+
professional setting
|
29
|
+
|
30
|
+
## Enforcement Responsibilities
|
31
|
+
|
32
|
+
Community leaders are responsible for clarifying and enforcing our standards of acceptable behavior and will take appropriate and fair corrective action in response to any behavior that they deem inappropriate, threatening, offensive, or harmful.
|
33
|
+
|
34
|
+
Community leaders have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct, and will communicate reasons for moderation decisions when appropriate.
|
35
|
+
|
36
|
+
## Scope
|
37
|
+
|
38
|
+
This Code of Conduct applies within all community spaces, and also applies when an individual is officially representing the community in public spaces. Examples of representing our community include using an official e-mail address, posting via an official social media account, or acting as an appointed representative at an online or offline event.
|
39
|
+
|
40
|
+
## Enforcement
|
41
|
+
|
42
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported to the community leaders responsible for enforcement at mehmetemininac@gmail.com. All complaints will be reviewed and investigated promptly and fairly.
|
43
|
+
|
44
|
+
All community leaders are obligated to respect the privacy and security of the reporter of any incident.
|
45
|
+
|
46
|
+
## Enforcement Guidelines
|
47
|
+
|
48
|
+
Community leaders will follow these Community Impact Guidelines in determining the consequences for any action they deem in violation of this Code of Conduct:
|
49
|
+
|
50
|
+
### 1. Correction
|
51
|
+
|
52
|
+
**Community Impact**: Use of inappropriate language or other behavior deemed unprofessional or unwelcome in the community.
|
53
|
+
|
54
|
+
**Consequence**: A private, written warning from community leaders, providing clarity around the nature of the violation and an explanation of why the behavior was inappropriate. A public apology may be requested.
|
55
|
+
|
56
|
+
### 2. Warning
|
57
|
+
|
58
|
+
**Community Impact**: A violation through a single incident or series of actions.
|
59
|
+
|
60
|
+
**Consequence**: A warning with consequences for continued behavior. No interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, for a specified period of time. This includes avoiding interactions in community spaces as well as external channels like social media. Violating these terms may lead to a temporary or permanent ban.
|
61
|
+
|
62
|
+
### 3. Temporary Ban
|
63
|
+
|
64
|
+
**Community Impact**: A serious violation of community standards, including sustained inappropriate behavior.
|
65
|
+
|
66
|
+
**Consequence**: A temporary ban from any sort of interaction or public communication with the community for a specified period of time. No public or private interaction with the people involved, including unsolicited interaction with those enforcing the Code of Conduct, is allowed during this period. Violating these terms may lead to a permanent ban.
|
67
|
+
|
68
|
+
### 4. Permanent Ban
|
69
|
+
|
70
|
+
**Community Impact**: Demonstrating a pattern of violation of community standards, including sustained inappropriate behavior, harassment of an individual, or aggression toward or disparagement of classes of individuals.
|
71
|
+
|
72
|
+
**Consequence**: A permanent ban from any sort of public interaction within the community.
|
73
|
+
|
74
|
+
## Attribution
|
75
|
+
|
76
|
+
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 2.0,
|
77
|
+
available at https://www.contributor-covenant.org/version/2/0/code_of_conduct.html.
|
78
|
+
|
79
|
+
Community Impact Guidelines were inspired by [Mozilla's code of conduct enforcement ladder](https://github.com/mozilla/diversity).
|
80
|
+
|
81
|
+
[homepage]: https://www.contributor-covenant.org
|
82
|
+
|
83
|
+
For answers to common questions about this code of conduct, see the FAQ at
|
84
|
+
https://www.contributor-covenant.org/faq. Translations are available at https://www.contributor-covenant.org/translations.
|
data/Gemfile
CHANGED
data/Gemfile.lock
CHANGED
@@ -1,41 +1,37 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
stack_trace (0.
|
4
|
+
stack_trace (0.4.0)
|
5
5
|
|
6
6
|
GEM
|
7
7
|
remote: https://rubygems.org/
|
8
8
|
specs:
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
rspec-
|
19
|
-
|
20
|
-
rspec-core (3.8.2)
|
21
|
-
rspec-support (~> 3.8.0)
|
22
|
-
rspec-expectations (3.8.4)
|
9
|
+
diff-lcs (1.5.0)
|
10
|
+
rake (13.0.6)
|
11
|
+
rake-compiler (1.2.1)
|
12
|
+
rake
|
13
|
+
rspec (3.12.0)
|
14
|
+
rspec-core (~> 3.12.0)
|
15
|
+
rspec-expectations (~> 3.12.0)
|
16
|
+
rspec-mocks (~> 3.12.0)
|
17
|
+
rspec-core (3.12.1)
|
18
|
+
rspec-support (~> 3.12.0)
|
19
|
+
rspec-expectations (3.12.2)
|
23
20
|
diff-lcs (>= 1.2.0, < 2.0)
|
24
|
-
rspec-support (~> 3.
|
25
|
-
rspec-mocks (3.
|
21
|
+
rspec-support (~> 3.12.0)
|
22
|
+
rspec-mocks (3.12.5)
|
26
23
|
diff-lcs (>= 1.2.0, < 2.0)
|
27
|
-
rspec-support (~> 3.
|
28
|
-
rspec-support (3.
|
24
|
+
rspec-support (~> 3.12.0)
|
25
|
+
rspec-support (3.12.0)
|
29
26
|
|
30
27
|
PLATFORMS
|
31
|
-
|
28
|
+
arm64-darwin-21
|
32
29
|
|
33
30
|
DEPENDENCIES
|
34
|
-
bundler (~> 2.0)
|
35
|
-
pry
|
36
31
|
rake (~> 13.0)
|
32
|
+
rake-compiler
|
37
33
|
rspec (~> 3.0)
|
38
34
|
stack_trace!
|
39
35
|
|
40
36
|
BUNDLED WITH
|
41
|
-
2.
|
37
|
+
2.2.33
|
data/LICENSE.txt
CHANGED
data/README.md
CHANGED
@@ -1,214 +1,38 @@
|
|
1
1
|
# StackTrace
|
2
2
|
|
3
|
-
|
3
|
+
Creates call stack trace for given block of Ruby code.
|
4
4
|
|
5
5
|
## Installation
|
6
6
|
|
7
|
-
|
7
|
+
Install the gem and add to the application's Gemfile by executing:
|
8
8
|
|
9
|
-
|
10
|
-
gem 'stack_trace'
|
11
|
-
```
|
12
|
-
|
13
|
-
And then execute:
|
14
|
-
|
15
|
-
$ bundle
|
9
|
+
$ bundle add stack_trace
|
16
10
|
|
17
|
-
|
11
|
+
If bundler is not being used to manage dependencies, install the gem by executing:
|
18
12
|
|
19
13
|
$ gem install stack_trace
|
20
14
|
|
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
|
-
|
34
15
|
## Usage
|
35
16
|
|
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
17
|
```ruby
|
89
18
|
StackTrace.trace do
|
90
|
-
|
91
|
-
|
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;
|
19
|
+
Foo.bar
|
20
|
+
end
|
98
21
|
|
99
|
-
|
100
|
-
StackTrace.trace do
|
101
|
-
# Do something usefull
|
102
|
-
StackTrace::Trace.as_json
|
103
|
-
end
|
22
|
+
StackTrace.current # => Returns a Hash that contains all the method calls and exception information.
|
104
23
|
```
|
105
24
|
|
106
|
-
|
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;
|
25
|
+
## Configuration
|
123
26
|
|
124
27
|
```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
28
|
StackTrace.configure do |config|
|
136
|
-
config.
|
137
|
-
config.
|
138
|
-
|
139
|
-
|
140
|
-
end
|
141
|
-
```
|
29
|
+
config.trace_ruby = true
|
30
|
+
config.trace_c = true
|
31
|
+
config.inspect_return_values = true # Default `false` for performance reasons
|
32
|
+
config.inspect_arguments = true # Default `false` for performance reasons
|
142
33
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
StackTrace.trace do
|
147
|
-
Greeting.new.hello("john", "doe")
|
148
|
-
result = StackTrace::Trace.as_json
|
34
|
+
config.check_proc = -> (klass_name, method_name) do # If you want to limit the tracing for a set of classes
|
35
|
+
klass_name == "Bar"
|
36
|
+
end
|
149
37
|
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
38
|
```
|
201
|
-
|
202
|
-
## Development
|
203
|
-
|
204
|
-
After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
|
205
|
-
|
206
|
-
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).
|
207
|
-
|
208
|
-
## Contributing
|
209
|
-
|
210
|
-
Bug reports and pull requests are welcome on GitHub at https://github.com/meinac/stack_trace.
|
211
|
-
|
212
|
-
## License
|
213
|
-
|
214
|
-
The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
|
data/Rakefile
CHANGED
@@ -1,6 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "bundler/gem_tasks"
|
2
4
|
require "rspec/core/rake_task"
|
5
|
+
require "rake/extensiontask"
|
3
6
|
|
4
7
|
RSpec::Core::RakeTask.new(:spec)
|
5
8
|
|
6
|
-
task :
|
9
|
+
task default: [:compile, :spec]
|
10
|
+
|
11
|
+
Rake::ExtensionTask.new "stack_trace" do |ext|
|
12
|
+
ext.lib_dir = "lib/stack_trace/ext"
|
13
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
static VALUE inspect_return_values = Qfalse;
|
4
|
+
static VALUE inspect_arguments = Qfalse;
|
5
|
+
|
6
|
+
// We are setting this static variable to gain some performance.
|
7
|
+
// Otherwise each time we need this, we would need to get the constant
|
8
|
+
// and make method calls.
|
9
|
+
VALUE rb_set_inspect_return_values(VALUE self, VALUE val) {
|
10
|
+
return inspect_return_values = val;
|
11
|
+
}
|
12
|
+
|
13
|
+
VALUE get_inspect_return_values() {
|
14
|
+
return inspect_return_values;
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE rb_set_inspect_arguments(VALUE self, VALUE val) {
|
18
|
+
return inspect_arguments = val;
|
19
|
+
}
|
20
|
+
|
21
|
+
VALUE get_inspect_arguments() {
|
22
|
+
return inspect_arguments;
|
23
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#include "current_trace.h"
|
2
|
+
#include "event_store.h"
|
3
|
+
#include "types/event.h"
|
4
|
+
|
5
|
+
static __thread Trace *current_trace = NULL;
|
6
|
+
|
7
|
+
Trace *get_current_trace() {
|
8
|
+
return current_trace;
|
9
|
+
}
|
10
|
+
|
11
|
+
VALUE rb_create_trace(VALUE _self) {
|
12
|
+
if(current_trace != NULL) {
|
13
|
+
current_trace->active = false;
|
14
|
+
|
15
|
+
Event event = {};
|
16
|
+
event.trace = current_trace;
|
17
|
+
event.event = END_OF_OBSOLOTE_TRACE_EVENT;
|
18
|
+
|
19
|
+
produce_event(event); // This will tell sidecar to free the memory
|
20
|
+
}
|
21
|
+
|
22
|
+
Span *span = malloc(sizeof(Span));
|
23
|
+
span->children_count = 0;
|
24
|
+
span->caller = NULL;
|
25
|
+
|
26
|
+
current_trace = malloc(sizeof(Trace));
|
27
|
+
current_trace->finished = false;
|
28
|
+
current_trace->top_span = span;
|
29
|
+
current_trace->current_span = span;
|
30
|
+
current_trace->active = true;
|
31
|
+
|
32
|
+
return Qtrue;
|
33
|
+
}
|
34
|
+
|
35
|
+
VALUE rb_send_eot(VALUE _self) {
|
36
|
+
Event event = {};
|
37
|
+
event.trace = current_trace;
|
38
|
+
event.event = END_OF_TRACE;
|
39
|
+
|
40
|
+
produce_event(event);
|
41
|
+
|
42
|
+
return Qtrue;
|
43
|
+
}
|
@@ -0,0 +1,43 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
|
3
|
+
#include "debug.h"
|
4
|
+
|
5
|
+
void serialize_event(char *buffer, Event *event) {
|
6
|
+
switch(event->event) {
|
7
|
+
case END_OF_TRACE:
|
8
|
+
sprintf(buffer, "End of trace");
|
9
|
+
return;
|
10
|
+
case END_OF_OBSOLOTE_TRACE_EVENT:
|
11
|
+
sprintf(buffer, "End of obsolote trace");
|
12
|
+
return;
|
13
|
+
case NOOP_EVENT:
|
14
|
+
sprintf(buffer, "NO-OP event");
|
15
|
+
return;
|
16
|
+
}
|
17
|
+
|
18
|
+
VALUE klass_name = rb_funcall(event->klass, rb_intern("name"), 0);
|
19
|
+
VALUE self_name = rb_funcall(event->self_klass, rb_intern("name"), 0);
|
20
|
+
VALUE method_name = rb_funcall(event->method, rb_intern("name"), 0);
|
21
|
+
|
22
|
+
char *klass_name_str = RSTRING_PTR(klass_name);
|
23
|
+
char *self_name_str = RSTRING_PTR(self_name);
|
24
|
+
char *method_name_str = RSTRING_PTR(method_name);
|
25
|
+
|
26
|
+
sprintf(
|
27
|
+
buffer,
|
28
|
+
"klass: %s, "
|
29
|
+
"self: %s, "
|
30
|
+
"method: %s, "
|
31
|
+
"event: %d, "
|
32
|
+
"for_singleton: %d",
|
33
|
+
klass_name_str,
|
34
|
+
self_name_str,
|
35
|
+
method_name_str,
|
36
|
+
event->event,
|
37
|
+
event->for_singleton
|
38
|
+
);
|
39
|
+
}
|
40
|
+
|
41
|
+
void serialize_unknown(char *buffer, void *var) {
|
42
|
+
sprintf(buffer, "Address: %p", var);
|
43
|
+
}
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#include "types/event.h"
|
2
|
+
|
3
|
+
#ifdef ST_DEBUG
|
4
|
+
void serialize_event(char *buffer, Event *event);
|
5
|
+
void serialize_unknown(char *buffer, void *var);
|
6
|
+
|
7
|
+
static FILE *debug_fp = NULL;
|
8
|
+
|
9
|
+
#define OPEN_DEBUG_FILE() if(!debug_fp) debug_fp = fopen("debug.log", "a")
|
10
|
+
|
11
|
+
#define SERIALIZE_STRUCT(s, buffer) \
|
12
|
+
_Generic((s), \
|
13
|
+
Event*: serialize_event, \
|
14
|
+
default: serialize_unknown \
|
15
|
+
)(buffer, s)
|
16
|
+
|
17
|
+
#define DEBUG(msg, s) \
|
18
|
+
do { \
|
19
|
+
OPEN_DEBUG_FILE(); \
|
20
|
+
char buffer[512]; \
|
21
|
+
SERIALIZE_STRUCT(s, buffer); \
|
22
|
+
fprintf(debug_fp, "DEBUG: %s:%d:%s(): " msg "{ %s }\n", \
|
23
|
+
__FILE__, __LINE__, __func__, buffer); \
|
24
|
+
fflush(debug_fp); \
|
25
|
+
} while(0)
|
26
|
+
|
27
|
+
#define DEBUG_TEXT(msg, ...) \
|
28
|
+
do { \
|
29
|
+
OPEN_DEBUG_FILE(); \
|
30
|
+
fprintf(debug_fp, "DEBUG: %s:%d:%s(): " msg "\n", \
|
31
|
+
__FILE__, __LINE__, __func__, ##__VA_ARGS__); \
|
32
|
+
fflush(debug_fp); \
|
33
|
+
} while(0)
|
34
|
+
#else
|
35
|
+
#define DEBUG(msg, ...)
|
36
|
+
#define DEBUG_TEXT(msg, ...)
|
37
|
+
#endif
|
@@ -0,0 +1,65 @@
|
|
1
|
+
#include <ruby.h>
|
2
|
+
#include <ruby/debug.h>
|
3
|
+
|
4
|
+
#include "types/event.h"
|
5
|
+
#include "event_store.h"
|
6
|
+
#include "current_trace.h"
|
7
|
+
#include "utils.h"
|
8
|
+
#include "configuration.h"
|
9
|
+
|
10
|
+
VALUE extract_arguments(VALUE tp_val) {
|
11
|
+
VALUE main_module = rb_const_get(rb_cObject, rb_intern("StackTrace"));
|
12
|
+
VALUE extractor_class = rb_const_get(main_module, rb_intern("ArgumentExtractor"));
|
13
|
+
|
14
|
+
VALUE arguments = rb_funcall(extractor_class, rb_intern("extract"), 1, tp_val);
|
15
|
+
rb_gc_register_address(&arguments);
|
16
|
+
|
17
|
+
return arguments;
|
18
|
+
}
|
19
|
+
|
20
|
+
void create_event(VALUE tp_val, void *_data) {
|
21
|
+
Event event = {};
|
22
|
+
int for_singleton = false;
|
23
|
+
|
24
|
+
rb_trace_arg_t *trace_arg = rb_tracearg_from_tracepoint(tp_val);
|
25
|
+
|
26
|
+
VALUE klass = rb_tracearg_defined_class(trace_arg);
|
27
|
+
VALUE self = rb_tracearg_self(trace_arg);
|
28
|
+
VALUE method = rb_tracearg_method_id(trace_arg);
|
29
|
+
VALUE self_klass;
|
30
|
+
|
31
|
+
if(FL_TEST(klass, FL_SINGLETON)) {
|
32
|
+
klass = rb_ivar_get(klass, rb_intern("__attached__"));
|
33
|
+
for_singleton = true;
|
34
|
+
self_klass = rb_funcall(self, rb_intern("name"), 0);
|
35
|
+
} else {
|
36
|
+
VALUE class = rb_funcall(self, rb_intern("class"), 0);
|
37
|
+
self_klass = rb_funcall(class, rb_intern("name"), 0);
|
38
|
+
}
|
39
|
+
|
40
|
+
event.trace = get_current_trace();
|
41
|
+
event.tp_val = tp_val;
|
42
|
+
event.trace_arg = trace_arg;
|
43
|
+
event.event = rb_tracearg_event_flag(trace_arg);
|
44
|
+
event.klass = klass;
|
45
|
+
event.self_klass = self_klass;
|
46
|
+
event.receiver = rb_funcall(self, rb_intern("st_name"), 0);
|
47
|
+
event.method = method;
|
48
|
+
event.for_singleton = for_singleton;
|
49
|
+
event.return_value = Qundef;
|
50
|
+
event.arguments = Qundef;
|
51
|
+
event.at = get_monotonic_m_secs();
|
52
|
+
|
53
|
+
if(event.event == RUBY_EVENT_RAISE)
|
54
|
+
event.raised_exception = rb_tracearg_raised_exception(trace_arg);
|
55
|
+
|
56
|
+
if(RTEST(get_inspect_arguments()) &&
|
57
|
+
(event.event == RUBY_EVENT_CALL || event.event == RUBY_EVENT_C_CALL || event.event == RUBY_EVENT_B_CALL))
|
58
|
+
event.arguments = extract_arguments(tp_val);
|
59
|
+
|
60
|
+
if(RTEST(get_inspect_return_values()) &&
|
61
|
+
(event.event == RUBY_EVENT_RETURN || event.event == RUBY_EVENT_C_RETURN || event.event == RUBY_EVENT_B_RETURN))
|
62
|
+
event.return_value = rb_tracearg_return_value(trace_arg);
|
63
|
+
|
64
|
+
produce_event(event);
|
65
|
+
}
|