stack_trace 0.5.0 → 0.6.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: 3e528eba64406556bc7638531e10cd80b0aa0027649d1dfcd223f3e0171e0c47
4
- data.tar.gz: c1a935f65476ba84ef18bed8873f82f54d39f3ae6fc384ce13571039c6b3571a
3
+ metadata.gz: a44fbab04e5a7a787dd995fbee5ea3e503080172df937a91e122728eb4884744
4
+ data.tar.gz: c004c70f42efc53e0776520d9e39a902346015eca012614913dd9a04e9822344
5
5
  SHA512:
6
- metadata.gz: d3adb5c1b7a759a18e0baad12bbefa11f27703396ae833ac887cf40bac0710268b9cda7e3e157c3df9ae313a1388e6222d7c7b50f02ac476b34d6f7d1941e022
7
- data.tar.gz: b5cc60e857c0c28c9f0ee2b0d2cd6b64641eb97ad1d62e100f694e1ce0bbcb13f438ebb576ccba6f42536d024fd5d38b8da7305f18a273f126b2516165366756
6
+ metadata.gz: aab482726e6436266555c91fbd51a0b44d8b5d0b6b0f3e72cd11448eaac96ea0d49582df77ab828cbbd38be93d177214cddb50a606ad8e899bb541179c43ed0f
7
+ data.tar.gz: 4e57a54efcb00a4a2701a5169130642be00fcd1aff13c4d508b0ac663f933fa5443eceffc78d74199d0fcf2ced21054559eabe85675ec2190b2f8ec768a02dc3
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- stack_trace (0.5.0)
4
+ stack_trace (0.6.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
@@ -0,0 +1,11 @@
1
+ #include "argument.h"
2
+
3
+ void free_arguments(Argument *arguments, int count) {
4
+ int i;
5
+
6
+ for(i = 0; i < count; i++) {
7
+ free(arguments[i].value);
8
+ }
9
+
10
+ free(arguments);
11
+ }
@@ -0,0 +1,3 @@
1
+ #include "types/argument.h"
2
+
3
+ void free_arguments(Argument *arguments, int count);
@@ -15,12 +15,7 @@ void serialize_event(char *buffer, Event *event) {
15
15
  return;
16
16
  }
17
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
18
  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
19
  char *method_name_str = RSTRING_PTR(method_name);
25
20
 
26
21
  sprintf(
@@ -30,8 +25,8 @@ void serialize_event(char *buffer, Event *event) {
30
25
  "method: %s, "
31
26
  "event: %d, "
32
27
  "for_singleton: %d",
33
- klass_name_str,
34
- self_name_str,
28
+ event->klass,
29
+ event->self_klass,
35
30
  method_name_str,
36
31
  event->event,
37
32
  event->for_singleton
@@ -6,6 +6,7 @@
6
6
  #include "current_trace.h"
7
7
  #include "utils.h"
8
8
  #include "configuration.h"
9
+ #include "st_name.h"
9
10
 
10
11
  struct MemoS {
11
12
  int i;
@@ -49,6 +50,12 @@ static void extract_arguments(Event *event, VALUE tp_val) {
49
50
  }
50
51
 
51
52
  void create_event(VALUE tp_val, void *_data) {
53
+ Trace *current_trace = get_current_trace();
54
+
55
+ // This can happen if a new thread spawns in trace scope.
56
+ // TODO: Save them with their thread identifier.
57
+ if(current_trace == NULL) return;
58
+
52
59
  Event event = {};
53
60
  int for_singleton = false;
54
61
 
@@ -56,33 +63,36 @@ void create_event(VALUE tp_val, void *_data) {
56
63
 
57
64
  VALUE klass = rb_tracearg_defined_class(trace_arg);
58
65
  VALUE self = rb_tracearg_self(trace_arg);
59
- VALUE receiver = rb_funcall(self, rb_intern("st_name"), 0);
60
66
  VALUE method = rb_tracearg_method_id(trace_arg);
61
67
  VALUE self_klass;
62
68
 
63
69
  if(FL_TEST(klass, FL_SINGLETON)) {
64
- klass = rb_ivar_get(klass, rb_intern("__attached__"));
65
70
  for_singleton = true;
66
- self_klass = rb_funcall(self, rb_intern("name"), 0);
71
+ klass = rb_ivar_get(klass, rb_intern("__attached__"));
72
+ self_klass = self;
67
73
  } else {
68
- VALUE class = rb_funcall(self, rb_intern("class"), 0);
69
- self_klass = rb_funcall(class, rb_intern("name"), 0);
74
+ self_klass = CLASS_OF(self);
70
75
  }
71
76
 
72
- event.trace = get_current_trace();
73
- event.tp_val = tp_val;
74
- event.trace_arg = trace_arg;
77
+ VALUE receiver = st_name(self, klass);
78
+ VALUE klass_name = get_cname(klass);
79
+ VALUE self_klass_name = get_cname(self_klass);
80
+
81
+ if(receiver == Qundef || klass_name == Qundef || self_klass_name == Qundef) return;
82
+ if(!rb_obj_is_kind_of(klass_name, rb_cString) || !rb_obj_is_kind_of(self_klass_name, rb_cString)) return; // These values can be Qnil
83
+
84
+ copy_str(&event.receiver, receiver);
85
+ copy_str(&event.klass, klass_name);
86
+ copy_str(&event.self_klass, self_klass_name);
87
+
88
+ event.trace = current_trace;
75
89
  event.event = rb_tracearg_event_flag(trace_arg);
76
- event.klass = klass;
77
- event.self_klass = self_klass;
78
90
  event.method = method;
79
91
  event.for_singleton = for_singleton;
80
92
  event.return_value = NULL;
81
93
  event.arguments = NULL;
82
94
  event.at = get_monotonic_m_secs();
83
95
 
84
- copy_str(&event.receiver, receiver);
85
-
86
96
  if(event.event == RUBY_EVENT_RAISE) {
87
97
  VALUE exception = rb_tracearg_raised_exception(trace_arg);
88
98
  VALUE exception_to_s = rb_funcall(exception, rb_intern("to_s"), 0);
@@ -1,5 +1,6 @@
1
1
  #include "span.h"
2
2
  #include "utils.h"
3
+ #include "argument.h"
3
4
 
4
5
  #define CHILDREN_BUF_INC_SIZE 10
5
6
 
@@ -49,17 +50,6 @@ Span *close_span(Span *span, Event *event) {
49
50
  return span->caller;
50
51
  }
51
52
 
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
-
62
-
63
53
  // Deallocate the memory occupied by span
64
54
  // and its children.
65
55
  void free_span(Span *span) {
@@ -75,11 +65,17 @@ void free_span(Span *span) {
75
65
  if(span->receiver != NULL)
76
66
  free(span->receiver);
77
67
 
68
+ if(span->klass != NULL)
69
+ free(span->klass);
70
+
71
+ if(span->self_klass != NULL)
72
+ free(span->self_klass);
73
+
78
74
  if(span->return_value != NULL)
79
75
  free(span->return_value);
80
76
 
81
77
  if(span->arguments != NULL)
82
- free_arguments(span);
78
+ free_arguments(span->arguments, span->arguments_count);
83
79
 
84
80
  if(span->exception != NULL)
85
81
  free(span->exception);
@@ -106,8 +102,8 @@ VALUE span_to_ruby_hash(Span *span) {
106
102
  VALUE hash = rb_hash_new();
107
103
 
108
104
  rb_hash_aset(hash, rb_str_new2("receiver"), rb_str_new_cstr(span->receiver));
109
- rb_hash_aset(hash, rb_str_new2("defined_class"), span->klass);
110
- rb_hash_aset(hash, rb_str_new2("self_class"), span->self_klass);
105
+ rb_hash_aset(hash, rb_str_new2("defined_class"), rb_str_new_cstr(span->klass));
106
+ rb_hash_aset(hash, rb_str_new2("self_class"), rb_str_new_cstr(span->self_klass));
111
107
  rb_hash_aset(hash, rb_str_new2("method_name"), span->method);
112
108
  rb_hash_aset(hash, rb_str_new2("singleton"), span->singleton);
113
109
  rb_hash_aset(hash, rb_str_new2("duration"), INT2FIX(duration_of(span)));
@@ -0,0 +1,47 @@
1
+ #include "st_name.h"
2
+
3
+ static VALUE extract_st_name(VALUE object) {
4
+ return rb_funcall(object, rb_intern("st_name"), 0);
5
+ }
6
+
7
+ VALUE get_cname(VALUE constant) {
8
+ if(rb_obj_is_kind_of(constant, rb_cClass)) {
9
+ return rb_class_name(constant);
10
+ } else if(rb_obj_is_kind_of(constant, rb_cModule)) {
11
+ return rb_mod_name(constant);
12
+ } else {
13
+ return Qundef; // This is still possible!
14
+ }
15
+ }
16
+
17
+ static VALUE object_name_for_cBasicObject(VALUE object, VALUE klass) {
18
+ VALUE cname = get_cname(klass);
19
+
20
+ if(cname == Qundef) return Qundef;
21
+
22
+ return rb_sprintf("#<%"PRIsVALUE":%p>", cname, (void*)object);
23
+ }
24
+
25
+ static VALUE object_name_for_cObject(VALUE object, VALUE klass) {
26
+ int status;
27
+
28
+ VALUE st_name = rb_protect(extract_st_name, object, &status);
29
+
30
+ if(status != 0) {
31
+ rb_set_errinfo(Qnil);
32
+
33
+ return object_name_for_cBasicObject(object, klass);
34
+ } else {
35
+ return st_name;
36
+ }
37
+ }
38
+
39
+ VALUE st_name(VALUE object, VALUE klass) {
40
+ if(rb_obj_is_kind_of(object, rb_cObject)) {
41
+ return object_name_for_cObject(object, klass);
42
+ } else if(rb_obj_is_kind_of(object, rb_cBasicObject)) {
43
+ return object_name_for_cBasicObject(object, klass);
44
+ } else {
45
+ return Qundef;
46
+ }
47
+ }
@@ -0,0 +1,4 @@
1
+ #include <ruby.h>
2
+
3
+ VALUE st_name(VALUE object, VALUE klass);
4
+ VALUE get_cname(VALUE constant);
@@ -8,18 +8,19 @@
8
8
  #include "span.h"
9
9
  #include "debug.h"
10
10
  #include "current_trace.h"
11
+ #include "argument.h"
11
12
 
12
13
  static VALUE check_proc;
13
14
 
14
15
  pthread_cond_t trace_finished = PTHREAD_COND_INITIALIZER;
15
16
  pthread_mutex_t trace_access_mutex = PTHREAD_MUTEX_INITIALIZER;
16
17
 
17
- void free_trace(Trace *trace) {
18
+ static void free_trace(Trace *trace) {
18
19
  free_span(trace->top_span);
19
20
  free(trace);
20
21
  }
21
22
 
22
- void process_obsolote_event(Event *event) {
23
+ static void process_obsolote_event(Event *event) {
23
24
  // Free this trace as there is no reference to it anymore!
24
25
  free_trace(event->trace);
25
26
  }
@@ -28,16 +29,51 @@ void set_check_proc(VALUE proc) {
28
29
  check_proc = proc;
29
30
  }
30
31
 
31
- bool is_tracked_event(Event *event) {
32
+ static VALUE call_proc(VALUE val) {
33
+ Event *event = (Event *)val;
34
+
35
+ return rb_funcall(check_proc, rb_intern("call"), 2, rb_str_new_cstr(event->self_klass), event->method);
36
+ }
37
+
38
+ static bool is_tracked_event(Event *event) {
32
39
  if(!RTEST(check_proc)) return true; // Check proc is not configured, all the events will be tracked.
33
40
 
34
- VALUE result = rb_funcall(check_proc, rb_intern("call"), 2, event->self_klass, event->method);
41
+ int state;
42
+ VALUE result = rb_protect(call_proc, (VALUE)event, &state); // I don't really like allocating a new array for each call so that's why I use this hack!
43
+
44
+ if(state != 0) {
45
+ rb_p(rb_errinfo());
46
+
47
+ rb_set_errinfo(Qnil);
48
+
49
+ return false;
50
+ }
35
51
 
36
52
  return RTEST(result);
37
53
  }
38
54
 
55
+ static void free_event_members(Event *event) {
56
+ if(event->receiver != NULL)
57
+ free(event->receiver);
58
+
59
+ if(event->klass != NULL)
60
+ free(event->klass);
61
+
62
+ if(event->self_klass != NULL)
63
+ free(event->self_klass);
64
+
65
+ if(event->return_value != NULL)
66
+ free(event->return_value);
67
+
68
+ if(event->raised_exception != NULL)
69
+ free(event->raised_exception);
70
+
71
+ if(event->arguments != NULL)
72
+ free_arguments(event->arguments, event->arguments_count);
73
+ }
74
+
39
75
  void create_new_span(Event *event) {
40
- if(!is_tracked_event(event)) return;
76
+ if(!is_tracked_event(event)) return free_event_members(event);
41
77
 
42
78
  Span *new_span = create_span(event);
43
79
 
@@ -47,7 +83,7 @@ void create_new_span(Event *event) {
47
83
  }
48
84
 
49
85
  void close_current_span(Event *event) {
50
- if(!is_tracked_event(event)) return;
86
+ if(!is_tracked_event(event)) return free_event_members(event);
51
87
 
52
88
  Trace *trace = event->trace;
53
89
 
@@ -17,13 +17,11 @@
17
17
 
18
18
  struct EventS {
19
19
  Trace *trace;
20
- VALUE tp_val;
21
20
  rb_event_flag_t event;
22
- rb_trace_arg_t *trace_arg;
23
21
  char *receiver;
24
- VALUE klass;
25
- VALUE self_klass;
26
- VALUE method;
22
+ char *klass;
23
+ char *self_klass;
24
+ VALUE method; // This is a symbol anyway
27
25
  char *return_value;
28
26
  Argument *arguments;
29
27
  int arguments_count;
@@ -10,8 +10,8 @@
10
10
  long int finished_at;
11
11
 
12
12
  char *receiver;
13
- VALUE klass;
14
- VALUE self_klass;
13
+ char *klass;
14
+ char *self_klass;
15
15
  VALUE method;
16
16
  VALUE singleton;
17
17
  char *return_value;
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module StackTrace
4
- VERSION = "0.5.0"
4
+ VERSION = "0.6.0"
5
5
  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.5.0
4
+ version: 0.6.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-06 00:00:00.000000000 Z
11
+ date: 2023-04-09 00:00:00.000000000 Z
12
12
  dependencies: []
13
13
  description: StackTrace
14
14
  email:
@@ -26,6 +26,8 @@ files:
26
26
  - LICENSE.txt
27
27
  - README.md
28
28
  - Rakefile
29
+ - ext/stack_trace/argument.c
30
+ - ext/stack_trace/argument.h
29
31
  - ext/stack_trace/configuration.c
30
32
  - ext/stack_trace/configuration.h
31
33
  - ext/stack_trace/current_trace.c
@@ -41,6 +43,8 @@ files:
41
43
  - ext/stack_trace/sidecar.h
42
44
  - ext/stack_trace/span.c
43
45
  - ext/stack_trace/span.h
46
+ - ext/stack_trace/st_name.c
47
+ - ext/stack_trace/st_name.h
44
48
  - ext/stack_trace/stack_trace.c
45
49
  - ext/stack_trace/trace.c
46
50
  - ext/stack_trace/trace.h