ruby-static-tracing 0.0.1 → 0.0.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 77e9c7647715d271d4cfdf9cb78359842ef0bae3f3582ea3f0248f3cbea2d288
4
- data.tar.gz: bac4e1fb75dbbcea6304c1a1ee9e8597c31334dd56ff3b75eb3df32e173e130e
2
+ SHA1:
3
+ metadata.gz: 394cdc6b04834088de888916e5ebcfb9481a8c75
4
+ data.tar.gz: 744d75e5564b7e3e0021d64cf2e141b97090e999
5
5
  SHA512:
6
- metadata.gz: 482ef944a73814773fce74d5f4906ee7ab626c35b5838ec3ed26579706e544ccf0c86dd2cd45ad880e5b3d9e9f69c3d60785eb173f005eb700110ab16796cf8c
7
- data.tar.gz: 9e311329c44e0081533e62b32eb78a4b1ef08671d60b37ceeee44cc565aedb270b3e3310ff21edaa756182ff36baea878428045668501d85bebbc1e373d4fff3
6
+ metadata.gz: e23b757367de4ddb676dbaac7da56d0d4ccb70e0bc7d4762df30c66221d0c5ec9cd2a2e2cc448c11c3bc11607d2e52b76d9eae451ed40a49883abf4cc478f2ff
7
+ data.tar.gz: 8ab4b39ffc8e234d9570bfc3cc1b62a019c3cbe7b1a4bcb595a7d09e01e9acd5280d9e5b97d6c597d9bab85970395f85d1183a50b0290e61d59e5d29d13132ca
@@ -3,25 +3,26 @@ $LOAD_PATH.unshift File.expand_path("../../../lib", __FILE__)
3
3
  require 'mkmf'
4
4
  require 'ruby-static-tracing/platform'
5
5
 
6
- unless StaticTracing.linux?
7
- end
8
-
9
6
  def platform_dir(platform)
10
7
  File.expand_path("../../../ext/ruby-static-tracing/#{platform}/", __FILE__)
11
8
  end
12
9
 
13
- if StaticTracing.linux?
10
+ if StaticTracing::Platform.linux?
14
11
  abort 'libstapsdt.h is missing, please install libstapsdt' unless find_header('libstapsdt.h')
15
-
12
+
16
13
  have_header 'libstapsdt.h'
17
-
18
- $CFLAGS = "-D_GNU_SOURCE -Werror -Wall "
14
+
15
+ unless have_library('stapsdt')
16
+ abort "libstapsdt is missing, please install it"
17
+ end
18
+
19
+ $CFLAGS = "-D_GNU_SOURCE -Wall " # -Werror complaining
19
20
  if ENV.key?('DEBUG')
20
21
  $CFLAGS << "-O0 -g -DDEBUG"
21
22
  else
22
23
  $CFLAGS << "-O3"
23
24
  end
24
-
25
+
25
26
  create_makefile('ruby-static-tracing/ruby_static_tracing', platform_dir("linux"))
26
27
  else
27
28
  # FIXME properly stub this.
@@ -0,0 +1,145 @@
1
+ #include "provider.h"
2
+
3
+ static const rb_data_type_t
4
+ static_tracing_provider_type;
5
+
6
+ // Forward decls
7
+ static const char*
8
+ check_name_arg(VALUE name);
9
+
10
+ /*
11
+ Wraps ProviderInit from libstapsdt
12
+ */
13
+ VALUE
14
+ provider_initialize(VALUE self, VALUE name)
15
+ {
16
+ const char *c_name_str = NULL;
17
+ static_tracing_provider_t *res = NULL;
18
+
19
+ // Check and cast arguments
20
+ c_name_str = check_name_arg(name);
21
+
22
+ // Build semian resource structure
23
+ TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
24
+ res->sdt_provider = providerInit(c_name_str);
25
+ return self;
26
+ }
27
+
28
+ // Internal function used to register a tracepoint against a provider instance
29
+ SDTProbe_t
30
+ *provider_add_tracepoint_internal(VALUE self, const char* name, int argc, Tracepoint_arg_types *args)
31
+ {
32
+ static_tracing_provider_t *res = NULL;
33
+ SDTProbe_t *probe;
34
+
35
+ TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
36
+
37
+ switch(argc)
38
+ {
39
+ case 0: probe = providerAddProbe(res->sdt_provider, name, 0); break;
40
+ case 1: probe = providerAddProbe(res->sdt_provider, name, argc, args[0]); break;
41
+ case 2: probe = providerAddProbe(res->sdt_provider, name, argc, args[0], args[1]); break;
42
+ case 3: probe = providerAddProbe(res->sdt_provider, name, argc, args[0], args[1], args[2]); break;
43
+ case 4: probe = providerAddProbe(res->sdt_provider, name, argc, args[0], args[1], args[2], args[3]); break;
44
+ case 5: probe = providerAddProbe(res->sdt_provider, name, argc, args[0], args[1], args[2], args[3], args[4]); break;
45
+ case 6: probe = providerAddProbe(res->sdt_provider, name, argc, args[0], args[1], args[2], args[3], args[4], args[5]); break;
46
+ default: probe = providerAddProbe(res->sdt_provider, name, 0); break;
47
+ }
48
+
49
+ return probe;
50
+ }
51
+
52
+ /*
53
+ Wraps providerLoad from libstapsdt
54
+ */
55
+ VALUE
56
+ provider_enable(VALUE self)
57
+ {
58
+ static_tracing_provider_t *res = NULL;
59
+ TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
60
+ return providerLoad(res->sdt_provider) == 0 ? Qtrue : Qfalse;
61
+ }
62
+
63
+ /*
64
+ Wraps providerUnload from libstapsdt
65
+ */
66
+ VALUE
67
+ provider_disable(VALUE self)
68
+ {
69
+ static_tracing_provider_t *res = NULL;
70
+ TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
71
+ return providerUnload(res->sdt_provider) == 0 ? Qtrue : Qfalse;
72
+ }
73
+
74
+ /*
75
+ Wraps providerUnload from libstapsdt
76
+ */
77
+ VALUE
78
+ provider_destroy(VALUE self)
79
+ {
80
+ static_tracing_provider_t *res = NULL;
81
+ TypedData_Get_Struct(self, static_tracing_provider_t, &static_tracing_provider_type, res);
82
+ providerDestroy(res->sdt_provider);
83
+ return Qnil;
84
+ }
85
+
86
+ // Allocate a static_tracing_provider_type struct for ruby memory management
87
+ VALUE
88
+ static_tracing_provider_alloc(VALUE klass)
89
+ {
90
+ static_tracing_provider_t *res;
91
+ VALUE obj = TypedData_Make_Struct(klass, static_tracing_provider_t, &static_tracing_provider_type, res);
92
+ return obj;
93
+ }
94
+
95
+
96
+ static const char*
97
+ check_name_arg(VALUE name)
98
+ {
99
+ const char *c_name_str = NULL;
100
+
101
+ if (TYPE(name) != T_SYMBOL && TYPE(name) != T_STRING) {
102
+ rb_raise(rb_eTypeError, "name must be a symbol or string");
103
+ }
104
+ if (TYPE(name) == T_SYMBOL) {
105
+ c_name_str = rb_id2name(rb_to_id(name));
106
+ } else if (TYPE(name) == T_STRING) {
107
+ c_name_str = RSTRING_PTR(name);
108
+ }
109
+
110
+ return c_name_str;
111
+ }
112
+
113
+ static inline void
114
+ static_tracing_provider_mark(void *ptr)
115
+ {
116
+ /* noop */
117
+ }
118
+
119
+ static inline void
120
+ static_tracing_provider_free(void *ptr)
121
+ {
122
+ static_tracing_provider_t *res = (static_tracing_provider_t *) ptr;
123
+ //if (res->name) {
124
+ // free(res->name);
125
+ // res->name = NULL;
126
+ //}
127
+ xfree(res);
128
+ }
129
+
130
+ static inline size_t
131
+ static_tracing_provider_memsize(const void *ptr)
132
+ {
133
+ return sizeof(static_tracing_provider_t);
134
+ }
135
+
136
+ static const rb_data_type_t
137
+ static_tracing_provider_type = {
138
+ "static_tracing_provider",
139
+ {
140
+ static_tracing_provider_mark,
141
+ static_tracing_provider_free,
142
+ static_tracing_provider_memsize
143
+ },
144
+ NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
145
+ };
@@ -0,0 +1,69 @@
1
+ /*
2
+ For core static tracing functions exposed directly to ruby.
3
+ Functions here are associated with rubyland operations.
4
+ */
5
+ #ifndef STATIC_TRACING_PROVIDER_H
6
+ #define STATIC_TRACING_PROVIDER_H
7
+
8
+ #include <ruby.h>
9
+ // Include libstapsdt.h to wrap
10
+ #include <libstapsdt.h>
11
+
12
+ #include "ruby_static_tracing.h"
13
+ #include "tracepoint.h"
14
+
15
+ typedef struct {
16
+ char *name;
17
+ SDTProvider_t *sdt_provider;
18
+ VALUE tracepoints;
19
+ } static_tracing_provider_t;
20
+
21
+ /*
22
+ * call-seq:
23
+ * StaticTracing::Provider.new(id) -> provider
24
+ *
25
+ * Creates a new Provider.
26
+ */
27
+ VALUE
28
+ provider_initialize(VALUE self, VALUE id);
29
+
30
+ /*
31
+ * call-seq:
32
+ * provider.enable() -> true
33
+ *
34
+ * Enable this provider
35
+ *
36
+ * Return true if the enable operation succeeded
37
+ */
38
+ VALUE
39
+ provider_enable(VALUE self);
40
+
41
+ /*
42
+ * call-seq:
43
+ * provider.disable() -> true
44
+ *
45
+ * Disable this provider
46
+ *
47
+ * Return true if the disable operation succeeded
48
+ */
49
+ VALUE
50
+ provider_disable(VALUE self);
51
+ /*
52
+ * call-seq:
53
+ * provider.destroy() -> true
54
+ *
55
+ * Destroys this provider.
56
+ *
57
+ * Return true if the destory operation succeeded
58
+ */
59
+ VALUE
60
+ provider_destroy(VALUE self);
61
+
62
+ // Allocate a static_tracing_provider_type struct for ruby memory management
63
+ VALUE
64
+ static_tracing_provider_alloc(VALUE klass);
65
+
66
+ SDTProbe_t
67
+ *provider_add_tracepoint_internal(VALUE self, const char* name, int argc, Tracepoint_arg_types *args);
68
+
69
+ #endif //STATIC_TRACING_PROVIDER_H
@@ -1,4 +1,47 @@
1
+ #include "provider.h"
2
+ #include "tracepoint.h"
3
+
1
4
  void Init_ruby_static_tracing()
2
5
  {
6
+ VALUE cStaticTracing, cProvider, cTracepoint;
7
+
8
+ cStaticTracing = rb_const_get(rb_cObject, rb_intern("StaticTracing"));
9
+
10
+ /*
11
+ * Document-class: StaticTracing::Provider
12
+ *
13
+ * Provider is the wrapper around libstapsdt
14
+ */
15
+ cProvider = rb_const_get(cStaticTracing, rb_intern("Provider"));
16
+
17
+ /*
18
+ * Document-class: Statictracing::Tracepoint
19
+ *
20
+ * A Tracepoint is a wrapper around an SDTProbe
21
+ */
22
+ cTracepoint = rb_const_get(cStaticTracing, rb_intern("Tracepoint"));
3
23
 
24
+ /* Document-class: StaticTracing::SyscallError
25
+ *
26
+ * Represents failures to fire a tracepoint or register a provider
27
+ */
28
+ eUSDT = rb_const_get(cStaticTracing, rb_intern("USDTError"));
29
+
30
+ /* Document-class: StaticTracing::InternalError
31
+ *
32
+ * An internal StaticTracing error. These errors may constitute bugs.
33
+ */
34
+ eInternal = rb_const_get(cStaticTracing, rb_intern("InternalError"));
35
+
36
+ rb_define_alloc_func(cProvider, static_tracing_provider_alloc);
37
+ rb_define_method(cProvider, "provider_initialize", provider_initialize, 1);
38
+ rb_define_method(cProvider, "enable", provider_enable, 0);
39
+ rb_define_method(cProvider, "disable", provider_disable, 0);
40
+ rb_define_method(cProvider, "destroy", provider_destroy, 0);
41
+
42
+ rb_define_alloc_func(cTracepoint, static_tracing_tracepoint_alloc);
43
+ rb_define_method(cTracepoint, "tracepoint_initialize", tracepoint_initialize, 3);
44
+ rb_define_method(cTracepoint, "fire_tracepoint", tracepoint_fire, 1);
45
+ rb_define_method(cTracepoint, "enabled?", tracepoint_enabled, 0);
4
46
  }
47
+
@@ -0,0 +1,19 @@
1
+ /*
2
+ System, 3rd party, and project includes
3
+ Implements Init_ruby_static_tracing, which is used as C/Ruby entrypoint.
4
+ */
5
+
6
+ #ifndef RUBY_STATIC_TRACING_H
7
+ #define RUBY_STATIC_TRACING_H
8
+
9
+ typedef enum TRACEPOINT_ARG_TYPES_ENUM {
10
+ Integer = int64, // STAP enum type -8
11
+ String = uint64, // STAP enum type 8
12
+ } Tracepoint_arg_types;
13
+
14
+ #include "provider.h"
15
+
16
+ void Init_ruby_static_tracing();
17
+ VALUE eUSDT, eInternal;
18
+
19
+ #endif //RUBY_STATIC_TRACING_H
@@ -0,0 +1,226 @@
1
+ #include "tracepoint.h"
2
+ #include "provider.h"
3
+
4
+ static const rb_data_type_t
5
+ static_tracing_tracepoint_type;
6
+
7
+ static const char*
8
+ check_name_arg(VALUE provider);
9
+
10
+ static const char*
11
+ check_provider_arg(VALUE provider);
12
+
13
+ static Tracepoint_arg_types
14
+ *check_vargs(int *argc, VALUE vargs);
15
+
16
+ static Tracepoint_fire_arg
17
+ *check_fire_args(int *argc, VALUE vargs);
18
+
19
+ VALUE
20
+ tracepoint_initialize(VALUE self, VALUE provider, VALUE name, VALUE vargs)
21
+ {
22
+ VALUE cStaticTracing, cProvider, cProviderInst;
23
+ static_tracing_tracepoint_t *tracepoint = NULL;
24
+ const char *c_name_str = NULL;
25
+ int argc = 0;
26
+
27
+ c_name_str = check_name_arg(name);
28
+ check_provider_arg(provider); // FIXME should only accept string
29
+ Tracepoint_arg_types *args = check_vargs(&argc, vargs);
30
+
31
+ /// Get a handle to global provider list for lookup
32
+ cStaticTracing = rb_const_get(rb_cObject, rb_intern("StaticTracing"));
33
+ cProvider = rb_const_get(cStaticTracing, rb_intern("Provider"));
34
+ cProviderInst = rb_funcall(cProvider, rb_intern("register"), 1, provider);
35
+
36
+ // Use the provider to register a tracepoint
37
+ SDTProbe_t *probe = provider_add_tracepoint_internal(cProviderInst, c_name_str, argc, args);
38
+ TypedData_Get_Struct(self, static_tracing_tracepoint_t, &static_tracing_tracepoint_type, tracepoint);
39
+
40
+ // Stare the tracepoint handle in our struct
41
+ tracepoint->sdt_tracepoint = probe;
42
+ tracepoint->args = args;
43
+
44
+ return self;
45
+ }
46
+
47
+ VALUE
48
+ tracepoint_fire(VALUE self, VALUE vargs)
49
+ {
50
+ static_tracing_tracepoint_t *res = NULL;
51
+ TypedData_Get_Struct(self, static_tracing_tracepoint_t, &static_tracing_tracepoint_type, res);
52
+ int argc = 0;
53
+
54
+ Tracepoint_fire_arg *args = check_fire_args(&argc, vargs);
55
+ switch(argc)
56
+ {
57
+ case 0: probeFire(res->sdt_tracepoint); break;
58
+ case 1: probeFire(res->sdt_tracepoint, args[0]); break;
59
+ case 2: probeFire(res->sdt_tracepoint, args[0], args[1]); break;
60
+ case 3: probeFire(res->sdt_tracepoint, args[0], args[1], args[2]); break;
61
+ case 4: probeFire(res->sdt_tracepoint, args[0], args[1], args[2], args[3]); break;
62
+ case 5: probeFire(res->sdt_tracepoint, args[0], args[1], args[2], args[3], args[4]); break;
63
+ case 6: probeFire(res->sdt_tracepoint, args[0], args[1], args[2], args[3], args[4], args[5]); break;
64
+ default: probeFire(res->sdt_tracepoint); break;
65
+ }
66
+
67
+ return Qnil;
68
+ }
69
+
70
+ VALUE
71
+ tracepoint_enabled(VALUE self)
72
+ {
73
+ static_tracing_tracepoint_t *res = NULL;
74
+ TypedData_Get_Struct(self, static_tracing_tracepoint_t, &static_tracing_tracepoint_type, res);
75
+ return probeIsEnabled(res->sdt_tracepoint) == 1 ? Qtrue : Qfalse;
76
+ }
77
+
78
+ static const char*
79
+ check_name_arg(VALUE name)
80
+ {
81
+ const char *c_name_str = NULL;
82
+
83
+ if (TYPE(name) != T_SYMBOL && TYPE(name) != T_STRING) {
84
+ rb_raise(rb_eTypeError, "name must be a symbol or string");
85
+ }
86
+ if (TYPE(name) == T_SYMBOL) {
87
+ c_name_str = rb_id2name(rb_to_id(name));
88
+ } else if (TYPE(name) == T_STRING) {
89
+ c_name_str = RSTRING_PTR(name);
90
+ }
91
+
92
+ return c_name_str;
93
+ }
94
+
95
+ static const char*
96
+ check_provider_arg(VALUE provider)
97
+ {
98
+ const char *c_provider_str = NULL;
99
+
100
+ if (TYPE(provider) != T_SYMBOL && TYPE(provider) != T_STRING) {
101
+ rb_raise(rb_eTypeError, "provider must be a symbol or string");
102
+ }
103
+ if (TYPE(provider) == T_SYMBOL) {
104
+ c_provider_str = rb_id2name(rb_to_id(provider));
105
+ } else if (TYPE(provider) == T_STRING) {
106
+ c_provider_str = RSTRING_PTR(provider);
107
+ }
108
+
109
+ return c_provider_str;
110
+ }
111
+
112
+ static Tracepoint_arg_types
113
+ *check_vargs(int *argc, VALUE vargs)
114
+ {
115
+ if(TYPE(vargs) == T_ARRAY)
116
+ {
117
+ VALUE rLength = rb_funcall(vargs, rb_intern("length"), 0, Qnil);
118
+ *argc = NUM2INT(rLength);
119
+
120
+ if(*argc > 6)
121
+ {
122
+ printf("ERROR - passed %i args, maximum 6 argument types can be passed", *argc);
123
+ return NULL;
124
+ }
125
+
126
+ Tracepoint_arg_types *args = malloc(*argc * sizeof(Tracepoint_arg_types));
127
+ for (int i = 0; i < *argc; i++)
128
+ {
129
+ VALUE str = rb_funcall(rb_ary_entry(vargs, i), rb_intern("to_s"), 0, Qnil);
130
+ const char* cStr = RSTRING_PTR(str);
131
+ if (strcmp(cStr, "Integer")) {
132
+ args[i] = Integer;
133
+ } else if (strcmp(cStr, "String")) {
134
+ args[i] = String;
135
+ } else {
136
+ printf("ERROR - type \"%s\" is unsupported\n", cStr);
137
+ }
138
+ }
139
+ return args;
140
+ } else {
141
+ printf("ERROR - array was expected\n");
142
+ return NULL;
143
+ }
144
+ }
145
+
146
+ static Tracepoint_fire_arg
147
+ *check_fire_args(int *argc, VALUE vargs)
148
+ {
149
+ if(TYPE(vargs) == T_ARRAY)
150
+ {
151
+ VALUE rLength = rb_funcall(vargs, rb_intern("length"), 0, Qnil);
152
+ *argc = NUM2INT(rLength);
153
+
154
+ if(*argc > 6)
155
+ {
156
+ printf("ERROR - passed %i args, maximum 6 argument types can be passed", *argc);
157
+ return NULL;
158
+ }
159
+
160
+ Tracepoint_fire_arg *args = malloc(*argc * sizeof(Tracepoint_fire_arg));
161
+ //printf("SIZE: %i ARGC: %i \n", sizeof(Tracepoint_fire_arg), *argc);
162
+ for (int i = 0; i < *argc; i++)
163
+ {
164
+ VALUE val = rb_ary_entry(vargs, i);
165
+ switch(TYPE(val))
166
+ {
167
+ case T_FIXNUM:
168
+ args[i].intval = FIX2LONG(val);
169
+ break;
170
+ case T_STRING:
171
+ args[i].strval = RSTRING_PTR(val);
172
+ break;
173
+ default:
174
+ printf("ERROR unsupported type passed for argument %i to fire\n", i);
175
+ break;
176
+ }
177
+ }
178
+ return args;
179
+ } else {
180
+ printf("ERROR - array was expected\n");
181
+ return NULL;
182
+ }
183
+ }
184
+
185
+ // Allocate a static_tracing_tracepoint_type struct for ruby memory management
186
+ VALUE
187
+ static_tracing_tracepoint_alloc(VALUE klass)
188
+ {
189
+ static_tracing_tracepoint_t *res;
190
+ VALUE obj = TypedData_Make_Struct(klass, static_tracing_tracepoint_t, &static_tracing_tracepoint_type, res);
191
+ return obj;
192
+ }
193
+
194
+ static inline void
195
+ static_tracing_tracepoint_mark(void *ptr)
196
+ {
197
+ /* noop */
198
+ }
199
+
200
+ static inline void
201
+ static_tracing_tracepoint_free(void *ptr)
202
+ {
203
+ static_tracing_tracepoint_t *res = (static_tracing_tracepoint_t *) ptr;
204
+ //if (res->name) {
205
+ // free(res->name);
206
+ // res->name = NULL;
207
+ //}
208
+ xfree(res);
209
+ }
210
+
211
+ static inline size_t
212
+ static_tracing_tracepoint_memsize(const void *ptr)
213
+ {
214
+ return sizeof(static_tracing_provider_t);
215
+ }
216
+
217
+ static const rb_data_type_t
218
+ static_tracing_tracepoint_type = {
219
+ "static_tracing_tracepoint",
220
+ {
221
+ static_tracing_tracepoint_mark,
222
+ static_tracing_tracepoint_free,
223
+ static_tracing_tracepoint_memsize
224
+ },
225
+ NULL, NULL, RUBY_TYPED_FREE_IMMEDIATELY
226
+ };
@@ -0,0 +1,57 @@
1
+ /*
2
+ For core static tracing functions exposed directly to ruby.
3
+ Functions here are associated with rubyland operations.
4
+ */
5
+ #ifndef STATIC_TRACING_TRACEPOINT_H
6
+ #define STATIC_TRACING_TRACEPOINT_H
7
+
8
+ #include <ruby.h>
9
+ // Include libstapsdt.h to wrap
10
+ #include <libstapsdt.h>
11
+ // Probably need to include provider.h to be able to initialize self
12
+
13
+ #include "ruby_static_tracing.h"
14
+
15
+ typedef union {
16
+ unsigned long long intval;
17
+ char * strval;
18
+ } Tracepoint_fire_arg;
19
+
20
+ typedef struct {
21
+ char *name;
22
+ SDTProbe_t *sdt_tracepoint;
23
+ Tracepoint_arg_types *args;
24
+ } static_tracing_tracepoint_t;
25
+
26
+ /*
27
+ * call-seq:
28
+ * StaticTracing::Tracepoint.new(provider, id, *vargs) -> tracepoint
29
+ *
30
+ * Creates a new tracepoint on a provider
31
+ */
32
+ VALUE
33
+ tracepoint_initialize(VALUE self, VALUE provider, VALUE id, VALUE vargs);
34
+
35
+ /*
36
+ * call-seq:
37
+ * tracepoint.fire(*vargs) -> true
38
+ *
39
+ * Fires data for the tracepoint to be probed
40
+ */
41
+ VALUE
42
+ tracepoint_fire(VALUE self, VALUE vargs);
43
+
44
+ /*
45
+ * call-seq:
46
+ * tracepoint.enabled? -> true
47
+ *
48
+ * Checks if the tracepoint is enabled, indicating it is being traced
49
+ */
50
+ VALUE
51
+ tracepoint_enabled(VALUE self);
52
+
53
+ // Allocate a static_tracing_tracepoint_type struct for ruby memory management
54
+ VALUE
55
+ static_tracing_tracepoint_alloc(VALUE klass);
56
+
57
+ #endif //STATIC_TRACING_TRACEPOINT_H
@@ -1,26 +1,81 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'logger'
4
+
1
5
  require 'ruby-static-tracing/version'
2
6
  require 'ruby-static-tracing/platform'
7
+ require 'ruby-static-tracing/provider'
8
+ require 'ruby-static-tracing/tracepoint'
9
+ require 'ruby-static-tracing/configuration'
10
+ require 'ruby-static-tracing/tracers'
3
11
 
4
12
  # FIXME Including StaticTracing should cause every method in a module or class to be registered
5
13
  # Implement this by introspecting all methods on the includor, and wrapping them.
6
14
  module StaticTracing
7
15
  extend self
8
16
 
17
+ BaseError = Class.new(StandardError)
18
+ USDTError = Class.new(BaseError)
19
+ InternalError = Class.new(BaseError)
20
+
21
+ attr_accessor :logger
22
+
23
+ self.logger = Logger.new(STDERR)
24
+
25
+ def issue_disabled_tracepoints_warning
26
+ return if defined?(@warning_issued)
27
+ @warning_issued = true
28
+ logger.info("USDT tracepoints are not presently supported supported on #{RUBY_PLATFORM} - all operations will no-op")
29
+ end
30
+
31
+ # Efficiently return the current monotonic clocktime.
32
+ # Wraps libc clock_gettime
33
+ # The overhead of this is tested to be on the order of 10 microseconds under normal conditions
34
+ # You should inline this method in your tracer to avoid an extra method call.
35
+ def nsec
36
+ Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
37
+ end
38
+
9
39
  # Should indicate if static tracing is enabled - a global constant
10
40
  def enabled?
41
+ !!@enabled
11
42
  end
12
43
 
13
44
  # Overwrite the definition of all functions that are enabled
14
45
  # with a wrapped version that has tracing enabled
15
- def enable
46
+ def enable!
47
+ tracers.each(&:enable!)
48
+ @enabled = true
16
49
  end
17
50
 
18
51
  # Overwrite the definition of all functions to their original definition,
19
52
  # no longer wrapping them
20
- def disable
53
+ def disable!
54
+ @enabled = false
55
+ end
56
+
57
+ # Retrieves a hash of all registered providers
58
+ def providers
59
+ @providers ||= {}
60
+ end
61
+
62
+ def tracers
63
+ @tracers ||= []
64
+ end
65
+
66
+ def toggle_tracing!
67
+ enabled? ? disable! : enable!
68
+ end
69
+
70
+ def configure
71
+ yield Configuration.instance
21
72
  end
22
73
  end
23
74
 
24
75
  # FIXME add signal handlers to enable-disable on specific process signals
25
76
  # within a trap handler.
26
77
  # Specify default signals, but allow these to be overidden for easier integration
78
+
79
+ # This loads the actual C extension, we might want to guard it
80
+ # for cases where the extension isn't yet built
81
+ require 'ruby-static-tracing/ruby_static_tracing' if StaticTracing::Platform.linux?
@@ -0,0 +1,71 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'singleton'
4
+
5
+ module StaticTracing
6
+ class Configuration
7
+ module Modes
8
+ ON = 'ON'
9
+ OFF = 'OFF'
10
+ SIGNAL = 'SIGNAL'
11
+
12
+ module SIGNALS
13
+ SIGPROF = 'PROF'
14
+ end
15
+ end
16
+
17
+ class << self
18
+ def instance
19
+ @instance ||= new
20
+ end
21
+ end
22
+
23
+ attr_reader :mode, :signal
24
+
25
+ def initialize
26
+ @mode = Modes::SIGNAL
27
+ @signal = Modes::SIGNALS::SIGPROF
28
+ enable_trap
29
+ end
30
+
31
+ def mode=(new_mode)
32
+ handle_old_mode
33
+ @mode = new_mode
34
+ handle_new_mode
35
+ end
36
+
37
+ def signal=(new_signal)
38
+ disable_trap
39
+ @signal = new_signal
40
+ enable_trap
41
+ end
42
+
43
+ def add_tracer(tracer)
44
+ StaticTracing.tracers << tracer
45
+ end
46
+
47
+ private
48
+
49
+ def handle_old_mode
50
+ disable_trap if @mode == Modes::SIGNAL
51
+ end
52
+
53
+ def handle_new_mode
54
+ if @mode == Modes::SIGNAL
55
+ enable_trap
56
+ elsif @mode == Modes::ON
57
+ StaticTracing.enable!
58
+ elsif @mode == Modes::OFF
59
+ StaticTracing.disable!
60
+ end
61
+ end
62
+
63
+ def disable_trap
64
+ Signal.trap(@signal, 'DEFAULT')
65
+ end
66
+
67
+ def enable_trap
68
+ Signal.trap(@signal) { StaticTracing.toggle_tracing! }
69
+ end
70
+ end
71
+ end
@@ -1,5 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StaticTracing
2
- def self.linux?
3
- true
4
+ module Platform
5
+ extend self
6
+
7
+ def linux?
8
+ /linux/.match(RUBY_PLATFORM)
9
+ end
4
10
  end
5
11
  end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StaticTracing
4
+ class Provider #:nodoc:
5
+ attr_accessor :name
6
+ class ProviderNotFound < StandardError; end
7
+
8
+ class << self
9
+ def register(namespace)
10
+ providers[namespace] ||= new(namespace)
11
+ end
12
+
13
+ def fetch(namespace)
14
+ providers.fetch(namespace) do
15
+ raise ProviderNotFound
16
+ end
17
+ end
18
+
19
+ private
20
+
21
+ def providers
22
+ @providers ||= {}
23
+ end
24
+ end
25
+
26
+ attr_reader :namespace
27
+
28
+ def initialize(namespace)
29
+ if StaticTracing::Platform.linux?
30
+ provider_initialize(namespace)
31
+ else
32
+ StaticTracing.issue_disabled_tracepoints_warning
33
+ end
34
+ @namespace = namespace
35
+ end
36
+
37
+ def add_tracepoint(method_name, *args)
38
+ Tracepoint.new(namespace, method_name, *args)
39
+ end
40
+
41
+ # FIXME - how to store list of tracepoints on provider? Allocate map in C?
42
+ # def tracepoints
43
+ # []
44
+ # end
45
+ def enable
46
+ end
47
+
48
+ def disable
49
+ end
50
+
51
+ # FIXME add binding to check if enabled
52
+ def enabled?
53
+ end
54
+
55
+ def destroy
56
+ end
57
+
58
+ def provider_initialize(*)
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ module StaticTracing
4
+ class Tracepoint #:nodoc:
5
+
6
+ class InvalidArgumentError < StandardError; end
7
+ class InvalidArgType < StandardError; end
8
+
9
+ VALID_ARGS_TYPES = [Integer, String]
10
+
11
+ attr_reader :provider, :name, :args
12
+
13
+ def initialize(provider, name, *args)
14
+ @provider = provider
15
+ @name = name
16
+ validate_args(args)
17
+ @args = args
18
+
19
+ if StaticTracing::Platform.linux?
20
+ tracepoint_initialize(provider, name, args)
21
+ else
22
+ StaticTracing.issue_disabled_tracepoints_warning
23
+ end
24
+ end
25
+
26
+ def fire(*values)
27
+ values.each_with_index do |arg, i|
28
+ raise InvalidArgumentError unless arg.is_a?(args[i])
29
+ end
30
+ end
31
+
32
+ def enabled?
33
+ end
34
+
35
+ private
36
+
37
+ def validate_args(values)
38
+ raise InvalidArgType unless values.all? { |value| VALID_ARGS_TYPES.include?(value) }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,3 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'tracers/latency_tracer'
@@ -0,0 +1,16 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ruby-static-tracing/tracers/latency_tracer'
4
+
5
+ module StaticTracing
6
+ module Tracers
7
+ module Concerns
8
+ module LatencyTracer
9
+ def self.included(base)
10
+ methods = base.public_instance_methods(false)
11
+ StaticTracing::Tracers::LatencyTracer.register(base, methods)
12
+ end
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,67 @@
1
+ # frozen_string_literal: true
2
+ require 'unmixer'
3
+
4
+ using Unmixer
5
+
6
+ module StaticTracing
7
+ module Tracers
8
+ class LatencyTracer
9
+ class LatencyModuleGenerator < Module
10
+ def initialize(provider, methods)
11
+ methods.each do |method|
12
+ define_method(method) do |*args, &block|
13
+ start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
14
+ result = super(*args, &block)
15
+ duration = Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond) - start_time
16
+ LatencyTracer.fire_tracepoint(provider, method, duration)
17
+ result
18
+ end
19
+ end
20
+ end
21
+ end
22
+
23
+ class << self
24
+ def register(klass, method_names, provider: nil)
25
+ provider ||= underscore(klass.name)
26
+ latency_module = LatencyModuleGenerator.new(provider, Array(method_names))
27
+ modified_classes[klass] = latency_module
28
+ end
29
+
30
+ def enable!
31
+ modified_classes.each do |klass, latency_module|
32
+ klass.prepend latency_module
33
+ end
34
+ end
35
+
36
+ def disable!
37
+ modified_classes.each do |klass, latency_module|
38
+ klass.instance_eval { unprepend latency_module }
39
+ end
40
+ end
41
+
42
+ def fire_tracepoint(provider, name, duration)
43
+ return
44
+ tracepoint(provider, name).fire(name, duration)
45
+ end
46
+
47
+ private
48
+
49
+ def tracepoint(provider, name)
50
+ @tracepoints[name] ||= StaticTracing::Tracepoint.new(provider, name, String, Interger)
51
+ end
52
+
53
+ def modified_classes
54
+ @modified_classes ||= {}
55
+ end
56
+
57
+ def underscore(class_name)
58
+ class_name.gsub(/::/, '_').
59
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
60
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
61
+ tr("-", "_").
62
+ downcase
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module StaticTracing
2
- VERSION = '0.0.1'
4
+ VERSION = '0.0.2'
3
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ruby-static-tracing
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dale Hamel
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-21 00:00:00.000000000 Z
11
+ date: 2019-04-04 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake-compiler
@@ -38,6 +38,48 @@ dependencies:
38
38
  - - "<"
39
39
  - !ruby/object:Gem::Version
40
40
  version: '11.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: mocha
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'
69
+ - !ruby/object:Gem::Dependency
70
+ name: pry-byebug
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
41
83
  description: " A Ruby C extension that enables defining static tracepoints\n from
42
84
  within a ruby context. \n"
43
85
  email: dale.hamel@srvthe.net
@@ -47,9 +89,20 @@ extensions:
47
89
  extra_rdoc_files: []
48
90
  files:
49
91
  - ext/ruby-static-tracing/extconf.rb
92
+ - ext/ruby-static-tracing/linux/provider.c
93
+ - ext/ruby-static-tracing/linux/provider.h
50
94
  - ext/ruby-static-tracing/linux/ruby_static_tracing.c
95
+ - ext/ruby-static-tracing/linux/ruby_static_tracing.h
96
+ - ext/ruby-static-tracing/linux/tracepoint.c
97
+ - ext/ruby-static-tracing/linux/tracepoint.h
51
98
  - lib/ruby-static-tracing.rb
99
+ - lib/ruby-static-tracing/configuration.rb
52
100
  - lib/ruby-static-tracing/platform.rb
101
+ - lib/ruby-static-tracing/provider.rb
102
+ - lib/ruby-static-tracing/tracepoint.rb
103
+ - lib/ruby-static-tracing/tracers.rb
104
+ - lib/ruby-static-tracing/tracers/concerns/latency_tracer.rb
105
+ - lib/ruby-static-tracing/tracers/latency_tracer.rb
53
106
  - lib/ruby-static-tracing/version.rb
54
107
  homepage: https://github.com/dalehamel/ruby-static-tracing
55
108
  licenses:
@@ -71,7 +124,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
71
124
  version: '0'
72
125
  requirements: []
73
126
  rubyforge_project:
74
- rubygems_version: 2.7.9
127
+ rubygems_version: 2.6.8
75
128
  signing_key:
76
129
  specification_version: 4
77
130
  summary: USDT tracing for Ruby