stack_trace 0.3.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/Rakefile +1 -1
- data/ext/stack_trace/event_producer.c +53 -12
- data/ext/stack_trace/span.c +43 -11
- data/ext/stack_trace/trace.c +8 -3
- data/ext/stack_trace/types/argument.h +12 -0
- data/ext/stack_trace/types/event.h +7 -4
- data/ext/stack_trace/types/span.h +7 -4
- data/lib/stack_trace/argument_extractor.rb +2 -2
- data/lib/stack_trace/patch/false_class.rb +1 -1
- data/lib/stack_trace/patch/nil_class.rb +1 -1
- data/lib/stack_trace/patch/numeric.rb +1 -1
- data/lib/stack_trace/patch/true_class.rb +1 -1
- data/lib/stack_trace/version.rb +1 -1
- data/lib/stack_trace.rb +2 -0
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 3e528eba64406556bc7638531e10cd80b0aa0027649d1dfcd223f3e0171e0c47
|
4
|
+
data.tar.gz: c1a935f65476ba84ef18bed8873f82f54d39f3ae6fc384ce13571039c6b3571a
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3adb5c1b7a759a18e0baad12bbefa11f27703396ae833ac887cf40bac0710268b9cda7e3e157c3df9ae313a1388e6222d7c7b50f02ac476b34d6f7d1941e022
|
7
|
+
data.tar.gz: b5cc60e857c0c28c9f0ee2b0d2cd6b64641eb97ad1d62e100f694e1ce0bbcb13f438ebb576ccba6f42536d024fd5d38b8da7305f18a273f126b2516165366756
|
data/Gemfile.lock
CHANGED
data/Rakefile
CHANGED
@@ -7,14 +7,45 @@
|
|
7
7
|
#include "utils.h"
|
8
8
|
#include "configuration.h"
|
9
9
|
|
10
|
-
|
10
|
+
struct MemoS {
|
11
|
+
int i;
|
12
|
+
Argument *arguments;
|
13
|
+
};
|
14
|
+
|
15
|
+
static void copy_str(char **target, VALUE string) {
|
16
|
+
*target = malloc(sizeof(char) * RSTRING_LEN(string) + 1);
|
17
|
+
|
18
|
+
memcpy(*target, RSTRING_PTR(string), RSTRING_LEN(string));
|
19
|
+
}
|
20
|
+
|
21
|
+
static int extract_kv(VALUE key, VALUE value, VALUE data) {
|
22
|
+
struct MemoS *memo = (struct MemoS *)data;
|
23
|
+
|
24
|
+
memo->arguments[memo->i].key = key;
|
25
|
+
copy_str(&memo->arguments[memo->i].value, value);
|
26
|
+
|
27
|
+
memo->i++;
|
28
|
+
|
29
|
+
return ST_CONTINUE;
|
30
|
+
}
|
31
|
+
|
32
|
+
static void extract_arguments(Event *event, VALUE tp_val) {
|
11
33
|
VALUE main_module = rb_const_get(rb_cObject, rb_intern("StackTrace"));
|
12
34
|
VALUE extractor_class = rb_const_get(main_module, rb_intern("ArgumentExtractor"));
|
13
35
|
|
14
|
-
VALUE
|
15
|
-
|
36
|
+
VALUE arguments_hash = rb_funcall(extractor_class, rb_intern("extract"), 1, tp_val);
|
37
|
+
VALUE hash_size = rb_funcall(arguments_hash, rb_intern("size"), 0);
|
16
38
|
|
17
|
-
|
39
|
+
int arguments_count = FIX2INT(hash_size);
|
40
|
+
|
41
|
+
if(arguments_count == 0) return;
|
42
|
+
|
43
|
+
event->arguments_count = arguments_count;
|
44
|
+
event->arguments = malloc(sizeof(Argument) * arguments_count);
|
45
|
+
|
46
|
+
struct MemoS memo = { 0, event->arguments };
|
47
|
+
|
48
|
+
rb_hash_foreach(arguments_hash, extract_kv, (VALUE)&memo);
|
18
49
|
}
|
19
50
|
|
20
51
|
void create_event(VALUE tp_val, void *_data) {
|
@@ -25,6 +56,7 @@ void create_event(VALUE tp_val, void *_data) {
|
|
25
56
|
|
26
57
|
VALUE klass = rb_tracearg_defined_class(trace_arg);
|
27
58
|
VALUE self = rb_tracearg_self(trace_arg);
|
59
|
+
VALUE receiver = rb_funcall(self, rb_intern("st_name"), 0);
|
28
60
|
VALUE method = rb_tracearg_method_id(trace_arg);
|
29
61
|
VALUE self_klass;
|
30
62
|
|
@@ -43,23 +75,32 @@ void create_event(VALUE tp_val, void *_data) {
|
|
43
75
|
event.event = rb_tracearg_event_flag(trace_arg);
|
44
76
|
event.klass = klass;
|
45
77
|
event.self_klass = self_klass;
|
46
|
-
event.receiver = rb_funcall(self, rb_intern("st_name"), 0);
|
47
78
|
event.method = method;
|
48
79
|
event.for_singleton = for_singleton;
|
49
|
-
event.return_value =
|
50
|
-
event.arguments =
|
80
|
+
event.return_value = NULL;
|
81
|
+
event.arguments = NULL;
|
51
82
|
event.at = get_monotonic_m_secs();
|
52
83
|
|
53
|
-
|
54
|
-
|
84
|
+
copy_str(&event.receiver, receiver);
|
85
|
+
|
86
|
+
if(event.event == RUBY_EVENT_RAISE) {
|
87
|
+
VALUE exception = rb_tracearg_raised_exception(trace_arg);
|
88
|
+
VALUE exception_to_s = rb_funcall(exception, rb_intern("to_s"), 0);
|
89
|
+
|
90
|
+
copy_str(&event.raised_exception, exception_to_s);
|
91
|
+
}
|
55
92
|
|
56
93
|
if(RTEST(get_inspect_arguments()) &&
|
57
94
|
(event.event == RUBY_EVENT_CALL || event.event == RUBY_EVENT_C_CALL || event.event == RUBY_EVENT_B_CALL))
|
58
|
-
event
|
95
|
+
extract_arguments(&event, tp_val);
|
59
96
|
|
60
97
|
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
|
-
|
98
|
+
(event.event == RUBY_EVENT_RETURN || event.event == RUBY_EVENT_C_RETURN || event.event == RUBY_EVENT_B_RETURN)) {
|
99
|
+
VALUE return_value = rb_tracearg_return_value(trace_arg);
|
100
|
+
VALUE return_value_st_name = rb_funcall(return_value, rb_intern("st_name"), 0);
|
101
|
+
|
102
|
+
copy_str(&event.return_value, return_value_st_name);
|
103
|
+
}
|
63
104
|
|
64
105
|
produce_event(event);
|
65
106
|
}
|
data/ext/stack_trace/span.c
CHANGED
@@ -11,9 +11,10 @@ Span *create_span(Event *event) {
|
|
11
11
|
span->klass = event->klass;
|
12
12
|
span->self_klass = event->self_klass;
|
13
13
|
span->method = event->method;
|
14
|
-
span->return_value =
|
14
|
+
span->return_value = NULL;
|
15
15
|
span->arguments = event->arguments;
|
16
|
-
span->
|
16
|
+
span->arguments_count = event->arguments_count;
|
17
|
+
span->exception = NULL;
|
17
18
|
span->children_count = 0;
|
18
19
|
span->singleton = event->for_singleton ? Qtrue : Qfalse;
|
19
20
|
|
@@ -48,6 +49,16 @@ Span *close_span(Span *span, Event *event) {
|
|
48
49
|
return span->caller;
|
49
50
|
}
|
50
51
|
|
52
|
+
static void free_arguments(Span *span) {
|
53
|
+
int i;
|
54
|
+
|
55
|
+
for(i = 0; i < span->arguments_count; i++) {
|
56
|
+
free(span->arguments[i].value);
|
57
|
+
}
|
58
|
+
|
59
|
+
free(span->arguments);
|
60
|
+
}
|
61
|
+
|
51
62
|
|
52
63
|
// Deallocate the memory occupied by span
|
53
64
|
// and its children.
|
@@ -61,6 +72,18 @@ void free_span(Span *span) {
|
|
61
72
|
free(span->children);
|
62
73
|
}
|
63
74
|
|
75
|
+
if(span->receiver != NULL)
|
76
|
+
free(span->receiver);
|
77
|
+
|
78
|
+
if(span->return_value != NULL)
|
79
|
+
free(span->return_value);
|
80
|
+
|
81
|
+
if(span->arguments != NULL)
|
82
|
+
free_arguments(span);
|
83
|
+
|
84
|
+
if(span->exception != NULL)
|
85
|
+
free(span->exception);
|
86
|
+
|
64
87
|
free(span);
|
65
88
|
}
|
66
89
|
|
@@ -68,10 +91,21 @@ int duration_of(Span *span) {
|
|
68
91
|
return (int)(span->finished_at - span->started_at);
|
69
92
|
}
|
70
93
|
|
94
|
+
VALUE serialize_arguments(Argument *arguments, int count) {
|
95
|
+
VALUE hash = rb_hash_new();
|
96
|
+
int i;
|
97
|
+
|
98
|
+
for(i = 0; i < count; i++) {
|
99
|
+
rb_hash_aset(hash, arguments[i].key, rb_str_new_cstr(arguments[i].value));
|
100
|
+
}
|
101
|
+
|
102
|
+
return hash;
|
103
|
+
}
|
104
|
+
|
71
105
|
VALUE span_to_ruby_hash(Span *span) {
|
72
106
|
VALUE hash = rb_hash_new();
|
73
107
|
|
74
|
-
rb_hash_aset(hash, rb_str_new2("receiver"), span->receiver);
|
108
|
+
rb_hash_aset(hash, rb_str_new2("receiver"), rb_str_new_cstr(span->receiver));
|
75
109
|
rb_hash_aset(hash, rb_str_new2("defined_class"), span->klass);
|
76
110
|
rb_hash_aset(hash, rb_str_new2("self_class"), span->self_klass);
|
77
111
|
rb_hash_aset(hash, rb_str_new2("method_name"), span->method);
|
@@ -79,16 +113,14 @@ VALUE span_to_ruby_hash(Span *span) {
|
|
79
113
|
rb_hash_aset(hash, rb_str_new2("duration"), INT2FIX(duration_of(span)));
|
80
114
|
rb_hash_aset(hash, rb_str_new2("spans"), to_ruby_array(span->children_count, span->children));
|
81
115
|
|
82
|
-
if(span->exception !=
|
83
|
-
rb_hash_aset(hash, rb_str_new2("exception"), span->exception);
|
84
|
-
|
85
|
-
if(span->return_value != Qundef)
|
86
|
-
rb_hash_aset(hash, rb_str_new2("return_value"), rb_funcall(span->return_value, rb_intern("st_name"), 0));
|
116
|
+
if(span->exception != NULL)
|
117
|
+
rb_hash_aset(hash, rb_str_new2("exception"), rb_str_new_cstr(span->exception));
|
87
118
|
|
88
|
-
if(span->
|
89
|
-
|
119
|
+
if(span->return_value != NULL)
|
120
|
+
rb_hash_aset(hash, rb_str_new2("return_value"), rb_str_new_cstr(span->return_value));
|
90
121
|
|
91
|
-
|
122
|
+
if(span->arguments != NULL) {
|
123
|
+
rb_hash_aset(hash, rb_str_new2("arguments"), serialize_arguments(span->arguments, span->arguments_count));
|
92
124
|
}
|
93
125
|
|
94
126
|
return hash;
|
data/ext/stack_trace/trace.c
CHANGED
@@ -20,7 +20,8 @@ void free_trace(Trace *trace) {
|
|
20
20
|
}
|
21
21
|
|
22
22
|
void process_obsolote_event(Event *event) {
|
23
|
-
//
|
23
|
+
// Free this trace as there is no reference to it anymore!
|
24
|
+
free_trace(event->trace);
|
24
25
|
}
|
25
26
|
|
26
27
|
void set_check_proc(VALUE proc) {
|
@@ -118,10 +119,14 @@ VALUE to_ruby_hash(Trace *trace) {
|
|
118
119
|
}
|
119
120
|
|
120
121
|
VALUE rb_get_current_trace(VALUE _self) {
|
122
|
+
VALUE main_module = rb_const_get(rb_cObject, rb_intern("StackTrace"));
|
123
|
+
VALUE tracePoint = rb_iv_get(main_module, "@trace_point");
|
124
|
+
VALUE is_tracepoint_enabled = rb_funcall(tracePoint, rb_intern("enabled?"), 0);
|
125
|
+
|
126
|
+
if(RTEST(is_tracepoint_enabled)) rb_raise(rb_eRuntimeError, "Trace is active!");
|
127
|
+
|
121
128
|
Trace *trace = get_current_trace_without_gvl();
|
122
129
|
VALUE ruby_hash = to_ruby_hash(trace);
|
123
130
|
|
124
|
-
free_trace(trace);
|
125
|
-
|
126
131
|
return ruby_hash;
|
127
132
|
}
|
@@ -4,6 +4,8 @@
|
|
4
4
|
#include <stdbool.h>
|
5
5
|
#include <sys/time.h>
|
6
6
|
|
7
|
+
#include "types/argument.h"
|
8
|
+
|
7
9
|
#ifndef EVENT_H
|
8
10
|
#define EVENT_H
|
9
11
|
|
@@ -18,13 +20,14 @@
|
|
18
20
|
VALUE tp_val;
|
19
21
|
rb_event_flag_t event;
|
20
22
|
rb_trace_arg_t *trace_arg;
|
23
|
+
char *receiver;
|
21
24
|
VALUE klass;
|
22
25
|
VALUE self_klass;
|
23
|
-
VALUE receiver;
|
24
26
|
VALUE method;
|
25
|
-
|
26
|
-
|
27
|
-
|
27
|
+
char *return_value;
|
28
|
+
Argument *arguments;
|
29
|
+
int arguments_count;
|
30
|
+
char *raised_exception;
|
28
31
|
bool for_singleton;
|
29
32
|
long int at;
|
30
33
|
};
|
@@ -1,3 +1,5 @@
|
|
1
|
+
#include "types/argument.h"
|
2
|
+
|
1
3
|
#ifndef SPAN_H
|
2
4
|
#define SPAN_H
|
3
5
|
|
@@ -7,14 +9,15 @@
|
|
7
9
|
long int started_at;
|
8
10
|
long int finished_at;
|
9
11
|
|
12
|
+
char *receiver;
|
10
13
|
VALUE klass;
|
11
14
|
VALUE self_klass;
|
12
|
-
VALUE receiver;
|
13
15
|
VALUE method;
|
14
16
|
VALUE singleton;
|
15
|
-
|
16
|
-
|
17
|
-
|
17
|
+
char *return_value;
|
18
|
+
Argument *arguments;
|
19
|
+
int arguments_count;
|
20
|
+
char *exception;
|
18
21
|
Span *caller;
|
19
22
|
int children_count;
|
20
23
|
Span **children;
|
@@ -7,14 +7,14 @@ module StackTrace
|
|
7
7
|
trace_point.parameters
|
8
8
|
.map(&:last)
|
9
9
|
.each_with_object({}) do |parameter, memo|
|
10
|
-
memo[parameter] = extract_argument(trace_point, parameter)
|
10
|
+
memo[parameter] = extract_argument(trace_point, parameter).st_name
|
11
11
|
end
|
12
12
|
end
|
13
13
|
|
14
14
|
private
|
15
15
|
|
16
16
|
def extract_argument(trace_point, parameter)
|
17
|
-
trace_point.binding.eval(parameter.to_s)
|
17
|
+
trace_point.binding.eval(parameter.to_s)
|
18
18
|
rescue Exception # SyntaxError can happen as we are calling `eval` here!
|
19
19
|
end
|
20
20
|
end
|
data/lib/stack_trace/version.rb
CHANGED
data/lib/stack_trace.rb
CHANGED
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.
|
4
|
+
version: 0.5.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: 2023-04-
|
11
|
+
date: 2023-04-06 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: StackTrace
|
14
14
|
email:
|
@@ -44,6 +44,7 @@ files:
|
|
44
44
|
- ext/stack_trace/stack_trace.c
|
45
45
|
- ext/stack_trace/trace.c
|
46
46
|
- ext/stack_trace/trace.h
|
47
|
+
- ext/stack_trace/types/argument.h
|
47
48
|
- ext/stack_trace/types/event.h
|
48
49
|
- ext/stack_trace/types/span.h
|
49
50
|
- ext/stack_trace/types/trace.h
|