ruby-static-tracing 0.0.1 → 0.0.2

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
- 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