ruby-dtrace-consumer 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
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
+ }