ruby-dtrace-consumer 0.4.0

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.
Files changed (75) hide show
  1. data/LICENCE +20 -0
  2. data/README.md +51 -0
  3. data/ext/Makefile +187 -0
  4. data/ext/dtrace_aggdata.c +132 -0
  5. data/ext/dtrace_aggdata.c~ +141 -0
  6. data/ext/dtrace_aggdata.o +0 -0
  7. data/ext/dtrace_api.bundle +0 -0
  8. data/ext/dtrace_api.c +102 -0
  9. data/ext/dtrace_api.c~ +113 -0
  10. data/ext/dtrace_api.h +138 -0
  11. data/ext/dtrace_api.h~ +155 -0
  12. data/ext/dtrace_api.o +0 -0
  13. data/ext/dtrace_bufdata.c +130 -0
  14. data/ext/dtrace_bufdata.c~ +139 -0
  15. data/ext/dtrace_bufdata.o +0 -0
  16. data/ext/dtrace_dropdata.c +121 -0
  17. data/ext/dtrace_dropdata.c~ +131 -0
  18. data/ext/dtrace_dropdata.o +0 -0
  19. data/ext/dtrace_errdata.c +100 -0
  20. data/ext/dtrace_errdata.c~ +110 -0
  21. data/ext/dtrace_errdata.o +0 -0
  22. data/ext/dtrace_hdl.c +677 -0
  23. data/ext/dtrace_hdl.c~ +689 -0
  24. data/ext/dtrace_hdl.o +0 -0
  25. data/ext/dtrace_probedata.c +273 -0
  26. data/ext/dtrace_probedata.c~ +283 -0
  27. data/ext/dtrace_probedata.o +0 -0
  28. data/ext/dtrace_probedesc.c +93 -0
  29. data/ext/dtrace_probedesc.c~ +78 -0
  30. data/ext/dtrace_probedesc.o +0 -0
  31. data/ext/dtrace_process.c +44 -0
  32. data/ext/dtrace_process.c~ +56 -0
  33. data/ext/dtrace_process.o +0 -0
  34. data/ext/dtrace_program.c +52 -0
  35. data/ext/dtrace_program.c~ +62 -0
  36. data/ext/dtrace_program.o +0 -0
  37. data/ext/dtrace_programinfo.c +70 -0
  38. data/ext/dtrace_programinfo.c~ +60 -0
  39. data/ext/dtrace_programinfo.o +0 -0
  40. data/ext/dtrace_recdesc.c +37 -0
  41. data/ext/dtrace_recdesc.c~ +46 -0
  42. data/ext/dtrace_recdesc.o +0 -0
  43. data/ext/dtrace_util.c +92 -0
  44. data/ext/dtrace_util.o +0 -0
  45. data/ext/extconf.rb +7 -0
  46. data/lib/dtrace.rb +95 -0
  47. data/lib/dtrace/aggregate.rb +40 -0
  48. data/lib/dtrace/aggregateset.rb +19 -0
  49. data/lib/dtrace/consumer.rb +174 -0
  50. data/lib/dtrace/data.rb +85 -0
  51. data/lib/dtrace/dof.rb +8 -0
  52. data/lib/dtrace/printfrecord.rb +10 -0
  53. data/lib/dtrace/probedata.rb +23 -0
  54. data/lib/dtrace/probedesc.rb +15 -0
  55. data/lib/dtrace/record.rb +11 -0
  56. data/lib/dtrace/stackrecord.rb +31 -0
  57. data/lib/dtrace/tracer.rb +35 -0
  58. data/lib/dtrace/version.rb +8 -0
  59. data/lib/dtrace/version.rb~ +8 -0
  60. data/lib/dtraceconsumer.rb +9 -0
  61. data/test/test_aggregates.rb +45 -0
  62. data/test/test_drops_errors.rb +166 -0
  63. data/test/test_dtrace.rb +155 -0
  64. data/test/test_gc.rb +11 -0
  65. data/test/test_helper.rb +20 -0
  66. data/test/test_helper.rb~ +16 -0
  67. data/test/test_legacy_consumer.rb +47 -0
  68. data/test/test_probedata.rb +30 -0
  69. data/test/test_processes.rb +66 -0
  70. data/test/test_profile.rb +198 -0
  71. data/test/test_repeat.rb +50 -0
  72. data/test/test_rubyprobe.rb +52 -0
  73. data/test/test_rubyprobe.rb~ +52 -0
  74. data/test/test_typefilter.rb +94 -0
  75. metadata +121 -0
Binary file
@@ -0,0 +1,273 @@
1
+ /* Ruby-DTrace
2
+ * (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ RUBY_EXTERN VALUE eDTraceException;
8
+
9
+ static VALUE _handle_ustack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
10
+ {
11
+ /* TODO, apple and solaris ustack */
12
+ VALUE stack = rb_ary_new();
13
+ return stack;
14
+ }
15
+
16
+ static VALUE _handle_stack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
17
+ {
18
+ VALUE stack = Qnil;
19
+ int size, i;
20
+ int depth;
21
+ uint64_t pc;
22
+ dtrace_syminfo_t dts;
23
+ char c[PATH_MAX * 2];
24
+ int ret;
25
+
26
+ #ifdef __APPLE__
27
+ __GElf_Sym sym;
28
+ #else
29
+ GElf_Sym sym;
30
+ #endif
31
+
32
+ size = rec->dtrd_size / rec->dtrd_arg;
33
+ depth = rec->dtrd_arg;
34
+
35
+ stack = rb_ary_new2(depth);
36
+
37
+ for (i = 0; i < depth; i++) {
38
+
39
+ switch (size) {
40
+ case sizeof (uint32_t):
41
+ pc = *((uint32_t *)addr);
42
+ break;
43
+
44
+ case sizeof (uint64_t):
45
+ pc = *((uint64_t *)addr);
46
+ break;
47
+
48
+ default:
49
+ rb_raise(eDTraceException, "bad stack pc");
50
+ return Qnil;
51
+ }
52
+
53
+ if (pc == (uint64_t)NULL)
54
+ break;
55
+
56
+ #ifdef __APPLE__
57
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, &sym, &dts);
58
+ #else
59
+ ret = dtrace_lookup_by_addr(handle, pc, &sym, &dts);
60
+ #endif
61
+
62
+ if (ret == 0) {
63
+
64
+ if (pc > sym.st_value)
65
+ (void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
66
+ dts.dts_object, dts.dts_name,
67
+ pc - sym.st_value);
68
+ else
69
+ (void) snprintf(c, sizeof (c), "%s`%s",
70
+ dts.dts_object, dts.dts_name);
71
+
72
+ }
73
+ else {
74
+
75
+ #ifdef __APPLE__
76
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, NULL, &dts);
77
+ #else
78
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, &dts);
79
+ #endif
80
+
81
+ if (ret == 0)
82
+ (void) snprintf(c, sizeof (c), "%s`0x%llx", dts.dts_object, pc);
83
+ else
84
+ (void) snprintf(c, sizeof (c), "0x%llx", pc);
85
+
86
+ }
87
+
88
+ rb_ary_push(stack, rb_str_new2(c));
89
+ addr += size;
90
+ }
91
+
92
+ return stack;
93
+ }
94
+
95
+ /*
96
+ * Returns the enabled probe id which generated this data
97
+ */
98
+ VALUE dtraceprobedata_epid(VALUE self)
99
+ {
100
+ dtrace_probedata_t *data;
101
+
102
+ Data_Get_Struct(self, dtrace_probedata_t, data);
103
+ return INT2FIX(data->dtpda_edesc->dtepd_epid);
104
+ }
105
+
106
+ /*
107
+ * Returns the DTraceProbe for the probe which generated this data
108
+ */
109
+ VALUE dtraceprobedata_probe(VALUE self)
110
+ {
111
+ VALUE dtraceprobe;
112
+ dtrace_probedata_t *data;
113
+ dtrace_probedesc_t *pd;
114
+
115
+ Data_Get_Struct(self, dtrace_probedata_t, data);
116
+ pd = data->dtpda_pdesc;
117
+
118
+ if (pd) {
119
+ dtraceprobe = dtraceprobedesc_init(pd);
120
+ return dtraceprobe;
121
+ }
122
+
123
+ return Qnil;
124
+ }
125
+
126
+ /* Returns the CPU which generated this data */
127
+ VALUE dtraceprobedata_cpu(VALUE self)
128
+ {
129
+ dtrace_probedata_t *data;
130
+ processorid_t cpu;
131
+
132
+ Data_Get_Struct(self, dtrace_probedata_t, data);
133
+
134
+ if (data) {
135
+ cpu = data->dtpda_cpu;
136
+ return INT2FIX(cpu);
137
+ }
138
+ else {
139
+ return Qnil;
140
+ }
141
+ }
142
+
143
+ /* Returns the indent level given to this data by DTrace */
144
+ VALUE dtraceprobedata_indent(VALUE self)
145
+ {
146
+ dtrace_probedata_t *data;
147
+ int indent;
148
+
149
+ Data_Get_Struct(self, dtrace_probedata_t, data);
150
+
151
+ if (data) {
152
+ indent = data->dtpda_indent;
153
+ return INT2FIX(indent / 2);
154
+ }
155
+ else {
156
+ return Qnil;
157
+ }
158
+ }
159
+
160
+ /* Returns the prefix given to this data by DTrace */
161
+ VALUE dtraceprobedata_prefix(VALUE self)
162
+ {
163
+ dtrace_probedata_t *data;
164
+ const char *prefix;
165
+
166
+ Data_Get_Struct(self, dtrace_probedata_t, data);
167
+ prefix = data->dtpda_prefix;
168
+
169
+ if (prefix)
170
+ return rb_str_new2(prefix);
171
+ else
172
+ return Qnil;
173
+ }
174
+
175
+ /* Returns the flow kind given to this data by DTrace */
176
+ VALUE dtraceprobedata_flow(VALUE self)
177
+ {
178
+ dtrace_probedata_t *data;
179
+
180
+ Data_Get_Struct(self, dtrace_probedata_t, data);
181
+
182
+ switch (data->dtpda_flow) {
183
+ case DTRACEFLOW_ENTRY:
184
+ return rb_str_new2("->");
185
+ break;
186
+ case DTRACEFLOW_RETURN:
187
+ return rb_str_new2("<-");
188
+ break;
189
+ default:
190
+ return Qnil;
191
+ }
192
+ }
193
+
194
+ /*
195
+ * Yields each record in this DTraceProbedata in turn. Records are
196
+ * yielded as either DTraceRecords or DTraceStackRecords as
197
+ * appropriate for the type of action.
198
+ */
199
+ VALUE dtraceprobedata_each_record(VALUE self)
200
+ {
201
+ dtrace_probedata_t *data;
202
+ dtrace_eprobedesc_t *eprobe;
203
+ dtrace_recdesc_t *rec;
204
+ dtrace_handle_t *handle;
205
+ dtrace_actkind_t act;
206
+ int i;
207
+ caddr_t addr;
208
+ VALUE dtracerecord;
209
+ VALUE dtrace;
210
+ VALUE v;
211
+ VALUE class;
212
+
213
+ Data_Get_Struct(self, dtrace_probedata_t, data);
214
+ dtrace = rb_iv_get(self, "@handle");
215
+ Data_Get_Struct(dtrace, dtrace_handle_t, handle);
216
+
217
+ eprobe = data->dtpda_edesc;
218
+
219
+ for (i = 0; i < eprobe->dtepd_nrecs; i++) {
220
+ v = 0;
221
+ rec = &eprobe->dtepd_rec[i];
222
+ if (rec->dtrd_size > 0) {
223
+ act = rec->dtrd_action;
224
+ addr = data->dtpda_data + rec->dtrd_offset;
225
+
226
+ switch (act) {
227
+ case DTRACEACT_STACK:
228
+ v = _handle_stack_record(handle->hdl, addr, rec);
229
+ class = rb_path2class("DTrace::StackRecord");
230
+ break;
231
+ case DTRACEACT_USTACK:
232
+ v = _handle_ustack_record(handle->hdl, addr, rec);
233
+ class = rb_path2class("DTrace::StackRecord");
234
+ break;
235
+ case DTRACEACT_JSTACK:
236
+ /* not sure how to handle jstack */
237
+ break;
238
+ case DTRACEACT_PRINTA:
239
+ /* don't want the probedata record for a printa() action */
240
+ break;
241
+ default:
242
+ class = rb_path2class("DTrace::Record");
243
+ switch (rec->dtrd_size) {
244
+ case 1:
245
+ v = INT2FIX((int)(*((uint8_t *)addr)));
246
+ break;
247
+ case 2:
248
+ v = INT2FIX((int)(*((uint16_t *)addr)));
249
+ break;
250
+ case 4:
251
+ v = INT2FIX(*((int32_t *)addr));
252
+ break;
253
+ case 8:
254
+ v = LL2NUM(*((int64_t *)addr));
255
+ break;
256
+ default:
257
+ v = handle_bytedata(addr, rec->dtrd_size);
258
+ break;
259
+ }
260
+ }
261
+
262
+ if (v) {
263
+ dtracerecord = rb_class_new_instance(0, NULL, class);
264
+ rb_iv_set(dtracerecord, "@value", v);
265
+ rb_iv_set(dtracerecord, "@from", rb_str_new2("probedata"));
266
+ rb_iv_set(dtracerecord, "@index", INT2FIX(i));
267
+ rb_iv_set(dtracerecord, "@action", INT2FIX(act));
268
+ rb_yield(dtracerecord);
269
+ }
270
+ }
271
+ }
272
+ return Qnil;
273
+ }
@@ -0,0 +1,283 @@
1
+ /* Ruby-DTrace
2
+ * (c) 2007 Chris Andrews <chris@nodnol.org>
3
+ */
4
+
5
+ #include "dtrace_api.h"
6
+
7
+ RUBY_EXTERN VALUE eDTraceException;
8
+ RUBY_EXTERN VALUE cDTraceProbeDesc;
9
+
10
+ /* :nodoc: */
11
+ VALUE dtraceprobedata_init(VALUE self)
12
+ {
13
+ dtrace_probedata_t *data;
14
+
15
+ Data_Get_Struct(self, dtrace_probedata_t, data);
16
+ return self;
17
+ }
18
+
19
+ static VALUE _handle_ustack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
20
+ {
21
+ /* TODO, apple and solaris ustack */
22
+ VALUE stack = rb_ary_new();
23
+ return stack;
24
+ }
25
+
26
+ static VALUE _handle_stack_record(dtrace_hdl_t *handle, caddr_t addr, const dtrace_recdesc_t *rec)
27
+ {
28
+ VALUE stack = Qnil;
29
+ int size, i;
30
+ int depth;
31
+ uint64_t pc;
32
+ dtrace_syminfo_t dts;
33
+ char c[PATH_MAX * 2];
34
+ int ret;
35
+
36
+ #ifdef __APPLE__
37
+ __GElf_Sym sym;
38
+ #else
39
+ GElf_Sym sym;
40
+ #endif
41
+
42
+ size = rec->dtrd_size / rec->dtrd_arg;
43
+ depth = rec->dtrd_arg;
44
+
45
+ stack = rb_ary_new2(depth);
46
+
47
+ for (i = 0; i < depth; i++) {
48
+
49
+ switch (size) {
50
+ case sizeof (uint32_t):
51
+ pc = *((uint32_t *)addr);
52
+ break;
53
+
54
+ case sizeof (uint64_t):
55
+ pc = *((uint64_t *)addr);
56
+ break;
57
+
58
+ default:
59
+ rb_raise(eDTraceException, "bad stack pc");
60
+ return Qnil;
61
+ }
62
+
63
+ if (pc == (uint64_t)NULL)
64
+ break;
65
+
66
+ #ifdef __APPLE__
67
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, &sym, &dts);
68
+ #else
69
+ ret = dtrace_lookup_by_addr(handle, pc, &sym, &dts);
70
+ #endif
71
+
72
+ if (ret == 0) {
73
+
74
+ if (pc > sym.st_value)
75
+ (void) snprintf(c, sizeof (c), "%s`%s+0x%llx",
76
+ dts.dts_object, dts.dts_name,
77
+ pc - sym.st_value);
78
+ else
79
+ (void) snprintf(c, sizeof (c), "%s`%s",
80
+ dts.dts_object, dts.dts_name);
81
+
82
+ }
83
+ else {
84
+
85
+ #ifdef __APPLE__
86
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, 0, NULL, &dts);
87
+ #else
88
+ ret = dtrace_lookup_by_addr(handle, pc, NULL, &dts);
89
+ #endif
90
+
91
+ if (ret == 0)
92
+ (void) snprintf(c, sizeof (c), "%s`0x%llx", dts.dts_object, pc);
93
+ else
94
+ (void) snprintf(c, sizeof (c), "0x%llx", pc);
95
+
96
+ }
97
+
98
+ rb_ary_push(stack, rb_str_new2(c));
99
+ addr += size;
100
+ }
101
+
102
+ return stack;
103
+ }
104
+
105
+ /*
106
+ * Returns the enabled probe id which generated this data
107
+ */
108
+ VALUE dtraceprobedata_epid(VALUE self)
109
+ {
110
+ dtrace_probedata_t *data;
111
+
112
+ Data_Get_Struct(self, dtrace_probedata_t, data);
113
+ return INT2FIX(data->dtpda_edesc->dtepd_epid);
114
+ }
115
+
116
+ /*
117
+ * Returns the DTraceProbe for the probe which generated this data
118
+ */
119
+ VALUE dtraceprobedata_probe(VALUE self)
120
+ {
121
+ VALUE dtraceprobe;
122
+ dtrace_probedata_t *data;
123
+ dtrace_probedesc_t *pd;
124
+
125
+ Data_Get_Struct(self, dtrace_probedata_t, data);
126
+ pd = data->dtpda_pdesc;
127
+
128
+ if (pd) {
129
+ dtraceprobe = Data_Wrap_Struct(cDTraceProbeDesc, 0, NULL, (dtrace_probedesc_t *)pd);
130
+ return dtraceprobe;
131
+ }
132
+
133
+ return Qnil;
134
+ }
135
+
136
+ /* Returns the CPU which generated this data */
137
+ VALUE dtraceprobedata_cpu(VALUE self)
138
+ {
139
+ dtrace_probedata_t *data;
140
+ processorid_t cpu;
141
+
142
+ Data_Get_Struct(self, dtrace_probedata_t, data);
143
+
144
+ if (data) {
145
+ cpu = data->dtpda_cpu;
146
+ return INT2FIX(cpu);
147
+ }
148
+ else {
149
+ return Qnil;
150
+ }
151
+ }
152
+
153
+ /* Returns the indent level given to this data by DTrace */
154
+ VALUE dtraceprobedata_indent(VALUE self)
155
+ {
156
+ dtrace_probedata_t *data;
157
+ int indent;
158
+
159
+ Data_Get_Struct(self, dtrace_probedata_t, data);
160
+
161
+ if (data) {
162
+ indent = data->dtpda_indent;
163
+ return INT2FIX(indent / 2);
164
+ }
165
+ else {
166
+ return Qnil;
167
+ }
168
+ }
169
+
170
+ /* Returns the prefix given to this data by DTrace */
171
+ VALUE dtraceprobedata_prefix(VALUE self)
172
+ {
173
+ dtrace_probedata_t *data;
174
+ const char *prefix;
175
+
176
+ Data_Get_Struct(self, dtrace_probedata_t, data);
177
+ prefix = data->dtpda_prefix;
178
+
179
+ if (prefix)
180
+ return rb_str_new2(prefix);
181
+ else
182
+ return Qnil;
183
+ }
184
+
185
+ /* Returns the flow kind given to this data by DTrace */
186
+ VALUE dtraceprobedata_flow(VALUE self)
187
+ {
188
+ dtrace_probedata_t *data;
189
+
190
+ Data_Get_Struct(self, dtrace_probedata_t, data);
191
+
192
+ switch (data->dtpda_flow) {
193
+ case DTRACEFLOW_ENTRY:
194
+ return rb_str_new2("->");
195
+ break;
196
+ case DTRACEFLOW_RETURN:
197
+ return rb_str_new2("<-");
198
+ break;
199
+ default:
200
+ return Qnil;
201
+ }
202
+ }
203
+
204
+ /*
205
+ * Yields each record in this DTraceProbedata in turn. Records are
206
+ * yielded as either DTraceRecords or DTraceStackRecords as
207
+ * appropriate for the type of action.
208
+ */
209
+ VALUE dtraceprobedata_each_record(VALUE self)
210
+ {
211
+ dtrace_probedata_t *data;
212
+ dtrace_eprobedesc_t *eprobe;
213
+ dtrace_recdesc_t *rec;
214
+ dtrace_handle_t *handle;
215
+ dtrace_actkind_t act;
216
+ int i;
217
+ caddr_t addr;
218
+ VALUE dtracerecord;
219
+ VALUE dtrace;
220
+ VALUE v;
221
+ VALUE class;
222
+
223
+ Data_Get_Struct(self, dtrace_probedata_t, data);
224
+ dtrace = rb_iv_get(self, "@handle");
225
+ Data_Get_Struct(dtrace, dtrace_handle_t, handle);
226
+
227
+ eprobe = data->dtpda_edesc;
228
+
229
+ for (i = 0; i < eprobe->dtepd_nrecs; i++) {
230
+ v = 0;
231
+ rec = &eprobe->dtepd_rec[i];
232
+ if (rec->dtrd_size > 0) {
233
+ act = rec->dtrd_action;
234
+ addr = data->dtpda_data + rec->dtrd_offset;
235
+
236
+ switch (act) {
237
+ case DTRACEACT_STACK:
238
+ v = _handle_stack_record(handle->hdl, addr, rec);
239
+ class = rb_path2class("DTrace::StackRecord");
240
+ break;
241
+ case DTRACEACT_USTACK:
242
+ v = _handle_ustack_record(handle->hdl, addr, rec);
243
+ class = rb_path2class("DTrace::StackRecord");
244
+ break;
245
+ case DTRACEACT_JSTACK:
246
+ /* not sure how to handle jstack */
247
+ break;
248
+ case DTRACEACT_PRINTA:
249
+ /* don't want the probedata record for a printa() action */
250
+ break;
251
+ default:
252
+ class = rb_path2class("DTrace::Record");
253
+ switch (rec->dtrd_size) {
254
+ case 1:
255
+ v = INT2FIX((int)(*((uint8_t *)addr)));
256
+ break;
257
+ case 2:
258
+ v = INT2FIX((int)(*((uint16_t *)addr)));
259
+ break;
260
+ case 4:
261
+ v = INT2FIX(*((int32_t *)addr));
262
+ break;
263
+ case 8:
264
+ v = LL2NUM(*((int64_t *)addr));
265
+ break;
266
+ default:
267
+ v = handle_bytedata(addr, rec->dtrd_size);
268
+ break;
269
+ }
270
+ }
271
+
272
+ if (v) {
273
+ dtracerecord = rb_class_new_instance(0, NULL, class);
274
+ rb_iv_set(dtracerecord, "@value", v);
275
+ rb_iv_set(dtracerecord, "@from", rb_str_new2("probedata"));
276
+ rb_iv_set(dtracerecord, "@index", INT2FIX(i));
277
+ rb_iv_set(dtracerecord, "@action", INT2FIX(act));
278
+ rb_yield(dtracerecord);
279
+ }
280
+ }
281
+ }
282
+ return Qnil;
283
+ }