ruby-dtrace 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.
data/History.txt CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.0.2 / 2007-12-07
2
+
3
+ * Implement the dtrace_work-based API
4
+ * Add a "Consumer" class
5
+ * Update Rails plugin to use new API
6
+
1
7
  == 0.0.1 / 2007-12-01
2
8
 
3
9
  * Initial public release.
10
+
data/Manifest.txt CHANGED
@@ -2,16 +2,24 @@ History.txt
2
2
  Manifest.txt
3
3
  README.txt
4
4
  Rakefile
5
- ext/dtrace_aggregate.c
5
+ ext/dtrace_aggdata.c
6
6
  ext/dtrace_api.c
7
7
  ext/dtrace_api.h
8
+ ext/dtrace_bufdata.c
8
9
  ext/dtrace_hdl.c
9
10
  ext/dtrace_probe.c
11
+ ext/dtrace_probedata.c
10
12
  ext/dtrace_program.c
11
13
  ext/dtrace_programinfo.c
12
14
  ext/dtrace_recdesc.c
15
+ ext/dtrace_util.c
13
16
  ext/extconf.rb
14
17
  lib/dtrace.rb
18
+ lib/dtraceaggregate.rb
19
+ lib/dtraceconsumer.rb
20
+ lib/dtraceprobe.rb
21
+ lib/dtraceprobedata.rb
22
+ lib/dtracerecord.rb
15
23
  plugin/dtrace/README
16
24
  plugin/dtrace/Rakefile
17
25
  plugin/dtrace/bin/dtracer.rb
@@ -26,3 +34,4 @@ plugin/dtrace/tasks/dtrace.rake
26
34
  plugin/dtrace/test/dtrace_test.rb
27
35
  plugin/dtrace/views/dtrace/_report.rhtml
28
36
  test/test_dtrace.rb
37
+ test/test_dtrace_workapi.rb
data/Rakefile CHANGED
@@ -2,7 +2,9 @@
2
2
 
3
3
  require 'rubygems'
4
4
  require 'hoe'
5
- require './lib/dtrace'
5
+
6
+ $: << './lib'
7
+ require 'dtrace'
6
8
 
7
9
  Hoe.new('ruby-dtrace', Dtrace::VERSION) do |p|
8
10
  p.rubyforge_name = 'ruby-dtrace'
@@ -0,0 +1,139 @@
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
+ /* :nodoc: */
10
+ VALUE dtraceaggdata_init(VALUE self)
11
+ {
12
+ dtrace_bufdata_t *data;
13
+
14
+ Data_Get_Struct(self, dtrace_bufdata_t, data);
15
+ return self;
16
+ }
17
+
18
+
19
+ VALUE dtraceaggdata_value(VALUE self)
20
+ {
21
+ dtrace_bufdata_t *bufdata;
22
+ const dtrace_aggdata_t *aggdata;
23
+ const dtrace_aggdesc_t *aggdesc;
24
+ const dtrace_recdesc_t *rec;
25
+ const char *s;
26
+ dtrace_actkind_t act = DTRACEACT_NONE;
27
+ int64_t aggid;
28
+ uint64_t normal;
29
+ caddr_t addr;
30
+ int64_t value;
31
+ VALUE v = Qnil;
32
+
33
+ Data_Get_Struct(self, dtrace_bufdata_t, bufdata);
34
+ aggdata = bufdata->dtbda_aggdata;
35
+ s = bufdata->dtbda_buffered;
36
+ rec = bufdata->dtbda_recdesc;
37
+
38
+ if (aggdata == NULL) {
39
+ rb_raise(eDtraceException, "null aggdata");
40
+ return Qnil;
41
+ }
42
+
43
+ aggdesc = aggdata->dtada_desc;
44
+
45
+ if (aggdesc == NULL) {
46
+ rb_raise(eDtraceException, "null aggdesc");
47
+ return Qnil;
48
+ }
49
+
50
+ aggid = *((int64_t *)(aggdata->dtada_data +
51
+ aggdesc->dtagd_rec[0].dtrd_offset));
52
+ if (aggid < 0) {
53
+ rb_raise(eDtraceException, "negative aggregation ID");
54
+ return Qnil;
55
+ }
56
+
57
+ act = rec->dtrd_action;
58
+
59
+ if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGKEY) {
60
+
61
+ switch (act) {
62
+ case DTRACEACT_STACK:
63
+ case DTRACEACT_USTACK:
64
+ case DTRACEACT_JSTACK:
65
+ /* todo */
66
+ break;
67
+ case DTRACEACT_USYM:
68
+ case DTRACEACT_UADDR:
69
+ case DTRACEACT_UMOD:
70
+ case DTRACEACT_SYM:
71
+ case DTRACEACT_MOD:
72
+ /* todo */
73
+ break;
74
+ default:
75
+ v = handle_bytedata((aggdata->dtada_data + rec->dtrd_offset), rec->dtrd_size);
76
+ }
77
+
78
+
79
+ } else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGVAL) {
80
+
81
+ normal = aggdata->dtada_normal;
82
+ addr = aggdata->dtada_data + rec->dtrd_offset;
83
+
84
+ if (act == DTRACEAGG_AVG) {
85
+ uint64_t *data = (uint64_t *)addr;
86
+ value = (data[0] ? (long long)(data[1] / normal / data[0]) : 0);
87
+ } else {
88
+ value = (*((int64_t *)addr)) / normal;
89
+ }
90
+
91
+ if (act == DTRACEAGG_QUANTIZE || act == DTRACEAGG_LQUANTIZE) {
92
+ v = Qnil; // dtj_new_distribution(data, rec, jc);
93
+ } else {
94
+ switch (act) {
95
+ case DTRACEAGG_COUNT:
96
+ if (value < 0)
97
+ rb_raise(eDtraceException, "count value is negative");
98
+ v = INT2FIX(value);
99
+ break;
100
+ case DTRACEAGG_AVG:
101
+ case DTRACEAGG_MIN:
102
+ case DTRACEAGG_MAX:
103
+ case DTRACEAGG_SUM:
104
+ v = INT2FIX(value);
105
+ break;
106
+ default:
107
+ v = Qnil;
108
+ rb_raise(eDtraceException, "unexpected aggregation action: %d", act);
109
+ }
110
+ }
111
+
112
+ } else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGVAL) {
113
+
114
+ v = Qnil;
115
+
116
+ }
117
+
118
+ return v;
119
+ }
120
+
121
+ VALUE dtraceaggdata_aggtype(VALUE self)
122
+ {
123
+ dtrace_bufdata_t *bufdata;
124
+ VALUE v;
125
+
126
+ Data_Get_Struct(self, dtrace_bufdata_t, bufdata);
127
+
128
+ if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGKEY)
129
+ v = rb_str_new2("tuple");
130
+ else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGVAL)
131
+ v = rb_str_new2("value");
132
+ else if (bufdata->dtbda_flags & DTRACE_BUFDATA_AGGLAST)
133
+ v = rb_str_new2("last");
134
+ else
135
+ v = rb_str_new2("unknown");
136
+
137
+ return v;
138
+ }
139
+
data/ext/dtrace_api.c CHANGED
@@ -10,6 +10,8 @@ VALUE cDtraceProgram;
10
10
  VALUE cDtraceProgramInfo;
11
11
  VALUE cDtraceAggData;
12
12
  VALUE cDtraceRecDesc;
13
+ VALUE cDtraceProbeData;
14
+ VALUE cDtraceBufData;
13
15
 
14
16
  VALUE eDtraceException;
15
17
 
@@ -28,6 +30,9 @@ void Init_dtrace_api() {
28
30
  rb_define_method(cDtrace, "aggregate_clear", dtrace_hdl_aggregate_clear, 0); // in dtrace_hdl.c
29
31
  rb_define_method(cDtrace, "error", dtrace_hdl_error, 0); // in dtrace_hdl.c
30
32
  rb_define_method(cDtrace, "setopt", dtrace_hdl_setopt, 2); // in dtrace_hdl.c
33
+ rb_define_method(cDtrace, "sleep", dtrace_hdl_sleep, 0); // in dtrace_hdl.c
34
+ rb_define_method(cDtrace, "work", dtrace_hdl_work, 2); // in dtrace_hdl.c
35
+ rb_define_method(cDtrace, "buf_consumer", dtrace_hdl_buf_consumer, 1); // in dtrace_hdl.c
31
36
  rb_define_alloc_func(cDtrace, dtrace_hdl_alloc);
32
37
 
33
38
  cDtraceProbe = rb_define_class("DtraceProbe", rb_cObject);
@@ -38,6 +43,15 @@ void Init_dtrace_api() {
38
43
  rb_define_method(cDtraceProbe, "func", dtraceprobe_func, 0); // in dtrace_probe.c
39
44
  rb_define_method(cDtraceProbe, "name", dtraceprobe_name, 0); // in dtrace_probe.c
40
45
 
46
+ cDtraceProbeData = rb_define_class("DtraceProbeData", rb_cObject);
47
+ rb_define_method(cDtraceProbeData, "initialize", dtraceprobedata_init, 0); // in dtrace_probedata.c
48
+ rb_define_method(cDtraceProbeData, "probedesc", dtraceprobedata_probedesc, 0); // in dtrace_probedata.c
49
+ rb_define_method(cDtraceProbeData, "each_record", dtraceprobedata_each_record, 0); // in dtrace_probedata.c
50
+
51
+ cDtraceBufData = rb_define_class("DtraceBufData", rb_cObject);
52
+ rb_define_method(cDtraceBufData, "initialize", dtracebufdata_init, 0); // in dtrace_bufdata.c
53
+ rb_define_method(cDtraceBufData, "record", dtracebufdata_record, 0); // in dtrace_bufdata.c
54
+
41
55
  cDtraceProgram = rb_define_class("DtraceProgram", rb_cObject);
42
56
  rb_define_method(cDtraceProgram, "initialize", dtraceprogram_init, 0); // in dtrace_program.c
43
57
  rb_define_method(cDtraceProgram, "execute", dtraceprogram_exec, 0); // in dtrace_program.c
@@ -51,18 +65,12 @@ void Init_dtrace_api() {
51
65
  rb_define_method(cDtraceProgramInfo, "speculations_count", dtraceprograminfo_speculations_count, 0); // in dtrace_programinfo.c
52
66
 
53
67
  cDtraceAggData = rb_define_class("DtraceAggData", rb_cObject);
54
- rb_define_method(cDtraceAggData, "initialize", dtraceaggdata_init, 0); // in dtrace_aggregate.c
55
- rb_define_method(cDtraceAggData, "desc", dtraceaggdata_desc, 0); // in dtrace_aggregate.c
56
- rb_define_method(cDtraceAggData, "value", dtraceaggdata_value, 0); // in dtrace_aggregate.c
57
- rb_define_method(cDtraceAggData, "size", dtraceaggdata_size, 0); // in dtrace_aggregate.c
58
- rb_define_method(cDtraceAggData, "each_record", dtraceaggdata_each_record, 0); // in dtrace_aggregate.c
59
- rb_define_method(cDtraceAggData, "num_records", dtraceaggdata_num_records, 0); // in dtrace_aggregate.c
60
- rb_define_method(cDtraceAggData, "[]", dtraceaggdata_record, 1); // in dtrace_aggregate.c
61
- rb_define_method(cDtraceAggData, "probe", dtraceaggdata_probe, 0); // in dtrace_aggregate.c
68
+ rb_define_method(cDtraceAggData, "initialize", dtraceaggdata_init, 0); // in dtrace_aggdata.c
69
+ rb_define_method(cDtraceAggData, "value", dtraceaggdata_value, 0); // in dtrace_aggdata.c
70
+ rb_define_method(cDtraceAggData, "aggtype", dtraceaggdata_aggtype, 0); // in dtrace_aggdata.c
62
71
 
63
72
  cDtraceRecDesc = rb_define_class("DtraceRecDesc", rb_cObject);
64
73
  rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init, 0); // in dtrace_recdesc.c
65
- rb_define_method(cDtraceRecDesc, "data", dtracerecdesc_data, 0); // in dtrace_recdesc.c
66
74
 
67
75
  eDtraceException = rb_define_class("DtraceException", rb_eStandardError);
68
76
  }
data/ext/dtrace_api.h CHANGED
@@ -8,14 +8,11 @@
8
8
  #include "/usr/include/dtrace.h"
9
9
  #include "ruby.h"
10
10
 
11
+ VALUE handle_bytedata(caddr_t addr, uint32_t nbytes);
12
+
11
13
  VALUE dtraceaggdata_init(VALUE self);
12
- VALUE dtraceaggdata_desc(VALUE self);
13
14
  VALUE dtraceaggdata_value(VALUE self);
14
- VALUE dtraceaggdata_size(VALUE self);
15
- VALUE dtraceaggdata_each_record(VALUE self);
16
- VALUE dtraceaggdata_num_records(VALUE self);
17
- VALUE dtraceaggdata_record(VALUE self, VALUE index);
18
- VALUE dtraceaggdata_probe(VALUE self);
15
+ VALUE dtraceaggdata_aggtype(VALUE self);
19
16
 
20
17
  void dtrace_hdl_free (void *handle);
21
18
  VALUE dtrace_hdl_alloc(VALUE klass);
@@ -31,6 +28,11 @@ VALUE dtrace_hdl_aggregate_print(VALUE self);
31
28
  VALUE dtrace_hdl_aggregate_snap(VALUE self);
32
29
  VALUE dtrace_hdl_aggregate_clear(VALUE self);
33
30
  VALUE dtrace_hdl_error(VALUE self);
31
+ VALUE dtrace_hdl_sleep(VALUE self);
32
+ VALUE dtrace_hdl_work(VALUE self,
33
+ VALUE probe_consumer_proc,
34
+ VALUE rec_consumer_proc);
35
+ VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer_proc);
34
36
 
35
37
  VALUE dtraceprobe_init(VALUE self);
36
38
  VALUE dtraceprobe_probe_id(VALUE self);
@@ -39,6 +41,13 @@ VALUE dtraceprobe_mod(VALUE self);
39
41
  VALUE dtraceprobe_func(VALUE self);
40
42
  VALUE dtraceprobe_name(VALUE self);
41
43
 
44
+ VALUE dtraceprobedata_init(VALUE self);
45
+ VALUE dtraceprobedata_probedesc(VALUE self);
46
+ VALUE dtraceprobedata_each_record(VALUE self);
47
+
48
+ VALUE dtracebufdata_init(VALUE self);
49
+ VALUE dtracebufdata_record(VALUE self);
50
+
42
51
  VALUE dtraceprogram_init(VALUE self);
43
52
  VALUE dtraceprogram_exec(VALUE self);
44
53
  VALUE dtraceprogram_info(VALUE self);
@@ -50,4 +59,3 @@ VALUE dtraceprograminfo_matches_count(VALUE self);
50
59
  VALUE dtraceprograminfo_speculations_count(VALUE self);
51
60
 
52
61
  VALUE dtracerecdesc_init(VALUE self);
53
- VALUE dtracerecdesc_data(VALUE self);
@@ -0,0 +1,91 @@
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 cDtraceAggData;
9
+ RUBY_EXTERN VALUE cDtraceRecDesc;
10
+
11
+ /* :nodoc: */
12
+ VALUE dtracebufdata_init(VALUE self)
13
+ {
14
+ dtrace_bufdata_t *data;
15
+
16
+ Data_Get_Struct(self, dtrace_bufdata_t, data);
17
+ return self;
18
+ }
19
+
20
+ VALUE dtracebufdata_record(VALUE self)
21
+ {
22
+ dtrace_bufdata_t *bufdata;
23
+ const dtrace_recdesc_t *rec;
24
+ dtrace_actkind_t act = DTRACEACT_NONE;
25
+ const char *s;
26
+ VALUE v = Qnil;
27
+ VALUE dtracerecord;
28
+ VALUE dtraceaggdata;
29
+ VALUE dtracerecdesc;
30
+
31
+ Data_Get_Struct(self, dtrace_bufdata_t, bufdata);
32
+
33
+ if (bufdata->dtbda_aggdata) {
34
+ dtraceaggdata = Data_Wrap_Struct(cDtraceAggData, 0, NULL, (dtrace_bufdata_t *)bufdata);
35
+ return dtraceaggdata;
36
+ }
37
+
38
+ s = bufdata->dtbda_buffered;
39
+ if (s == NULL) {
40
+ return Qnil;
41
+ }
42
+
43
+ rec = bufdata->dtbda_recdesc;
44
+ if (rec) {
45
+ act = rec->dtrd_action;
46
+ }
47
+
48
+ switch (act) {
49
+ case DTRACEACT_DIFEXPR:
50
+ /* trace() action */
51
+ break;
52
+ case DTRACEACT_PRINTF:
53
+ /*
54
+ * Only the formatted string was not available to dtj_chewrec(),
55
+ * so we attach that now.
56
+ */
57
+ v = rb_str_new2(s);
58
+ break;
59
+ case DTRACEACT_STACK:
60
+ case DTRACEACT_USTACK:
61
+ case DTRACEACT_JSTACK:
62
+ /* stand-alone stack(), ustack(), or jstack() action */
63
+ v = rb_str_new2(s);
64
+ break;
65
+ case DTRACEACT_USYM:
66
+ case DTRACEACT_UADDR:
67
+ case DTRACEACT_UMOD:
68
+ case DTRACEACT_SYM:
69
+ case DTRACEACT_MOD:
70
+ v = rb_str_new2(s);
71
+ break;
72
+ case DTRACEACT_PRINTA:
73
+ v = rb_str_new2(s);
74
+ break;
75
+ default:
76
+ /*
77
+ * The record handle defers nothing else to this
78
+ * bufhandler.
79
+ */
80
+ break;
81
+ }
82
+
83
+ if (!NIL_P(v)) {
84
+ dtracerecord = rb_class_new_instance(0, NULL, rb_path2class("DtraceRecord"));
85
+ rb_iv_set(dtracerecord, "@value", v);
86
+ return (dtracerecord);
87
+ }
88
+ else {
89
+ return Qnil;
90
+ }
91
+ }
data/ext/dtrace_hdl.c CHANGED
@@ -8,6 +8,9 @@ RUBY_EXTERN VALUE eDtraceException;
8
8
  RUBY_EXTERN VALUE cDtraceProbe;
9
9
  RUBY_EXTERN VALUE cDtraceProgram;
10
10
  RUBY_EXTERN VALUE cDtraceAggData;
11
+ RUBY_EXTERN VALUE cDtraceRecDesc;
12
+ RUBY_EXTERN VALUE cDtraceProbeData;
13
+ RUBY_EXTERN VALUE cDtraceBufData;
11
14
 
12
15
  void dtrace_hdl_free (void *handle)
13
16
  {
@@ -278,3 +281,101 @@ VALUE dtrace_hdl_error(VALUE self)
278
281
  return rb_str_new2(error_string);
279
282
  }
280
283
 
284
+ /*
285
+ * Sleep until we need to wake up to honour D options controlling
286
+ * consumption rates.
287
+ */
288
+ VALUE dtrace_hdl_sleep(VALUE self)
289
+ {
290
+ dtrace_hdl_t *handle;
291
+
292
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
293
+ dtrace_sleep(handle);
294
+ return Qnil;
295
+ }
296
+
297
+ typedef struct dtrace_work_handlers {
298
+ VALUE probe;
299
+ VALUE rec;
300
+ } dtrace_work_handlers_t;
301
+
302
+ static int _probe_consumer(const dtrace_probedata_t *data, void *arg)
303
+ {
304
+ VALUE proc;
305
+ dtrace_work_handlers_t handlers;
306
+ VALUE probedata;
307
+
308
+ handlers = *(dtrace_work_handlers_t *) arg;
309
+ proc = handlers.probe;
310
+
311
+ probedata = Data_Wrap_Struct(cDtraceProbeData, 0, NULL, (dtrace_probedata_t *)data);
312
+ rb_funcall(proc, rb_intern("call"), 1, probedata);
313
+
314
+ return (DTRACE_CONSUME_THIS);
315
+ }
316
+
317
+ static int _rec_consumer(const dtrace_probedata_t *data, const dtrace_recdesc_t *rec, void *arg)
318
+ {
319
+ VALUE proc;
320
+ dtrace_work_handlers_t handlers;
321
+ VALUE recdesc;
322
+
323
+ handlers = *(dtrace_work_handlers_t *) arg;
324
+ proc = handlers.rec;
325
+
326
+ recdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, (dtrace_recdesc_t *)rec);
327
+ rb_funcall(proc, rb_intern("call"), 1, recdesc);
328
+
329
+ return (DTRACE_CONSUME_THIS);
330
+ }
331
+
332
+ static int _buf_consumer(const dtrace_bufdata_t *bufdata, void *arg)
333
+ {
334
+ VALUE proc;
335
+ VALUE dtracebufdata;
336
+
337
+ proc = (VALUE)arg;
338
+
339
+ dtracebufdata = Data_Wrap_Struct(cDtraceBufData, 0, NULL, (dtrace_bufdata_t *)bufdata);
340
+ rb_funcall(proc, rb_intern("call"), 1, dtracebufdata);
341
+
342
+ return (DTRACE_HANDLE_OK);
343
+ }
344
+
345
+ /*
346
+ * Process any data waiting from the D program.
347
+ */
348
+ VALUE dtrace_hdl_work(VALUE self,
349
+ VALUE probe_consumer_proc,
350
+ VALUE rec_consumer_proc)
351
+ {
352
+ dtrace_hdl_t *handle;
353
+ dtrace_workstatus_t status;
354
+ dtrace_work_handlers_t handlers;
355
+
356
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
357
+
358
+ /* fill out the handlers struct */
359
+ handlers.probe = probe_consumer_proc;
360
+ handlers.rec = rec_consumer_proc;
361
+
362
+ status = dtrace_work(handle, NULL, _probe_consumer, _rec_consumer, &handlers);
363
+
364
+ return INT2FIX(status);
365
+ }
366
+
367
+ /*
368
+ * Set up the buffered output handler for this handle.
369
+ */
370
+ VALUE dtrace_hdl_buf_consumer(VALUE self, VALUE buf_consumer)
371
+ {
372
+ dtrace_hdl_t *handle;
373
+ Data_Get_Struct(self, dtrace_hdl_t, handle);
374
+
375
+ /* attach the buffered output handler */
376
+ if (dtrace_handle_buffered(handle, &_buf_consumer, (void *)buf_consumer) == -1) {
377
+ rb_raise(eDtraceException, "failed to establish buffered handler");
378
+ }
379
+
380
+ return Qnil;
381
+ }