ruby-dtrace 0.0.4 → 0.0.5

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.
@@ -202,17 +202,17 @@ VALUE dtraceprobedata_each_record(VALUE self)
202
202
  dtrace_probedata_t *data;
203
203
  dtrace_eprobedesc_t *eprobe;
204
204
  dtrace_recdesc_t *rec;
205
- dtrace_hdl_t *handle;
205
+ dtrace_handle_t *handle;
206
206
  dtrace_actkind_t act;
207
207
  int i;
208
208
  caddr_t addr;
209
209
  VALUE dtracerecord;
210
- VALUE dtracehandle;
210
+ VALUE dtrace;
211
211
  VALUE v;
212
212
 
213
213
  Data_Get_Struct(self, dtrace_probedata_t, data);
214
- dtracehandle = rb_iv_get(self, "@handle");
215
- Data_Get_Struct(dtracehandle, dtrace_hdl_t, handle);
214
+ dtrace = rb_iv_get(self, "@handle");
215
+ Data_Get_Struct(dtrace, dtrace_handle_t, handle);
216
216
 
217
217
  eprobe = data->dtpda_edesc;
218
218
 
@@ -228,8 +228,8 @@ VALUE dtraceprobedata_each_record(VALUE self)
228
228
  case DTRACEACT_USTACK:
229
229
  case DTRACEACT_JSTACK:
230
230
  /* Stack records come from bufdata */
231
- /* v = _handle_stack_record(handle, addr, rec); */
232
- /* v = _handle_ustack_record(handle, addr, rec); */
231
+ /* v = _handle_stack_record(handle->hdl, addr, rec); */
232
+ /* v = _handle_ustack_record(handle->hdl, addr, rec); */
233
233
  break;
234
234
  case DTRACEACT_PRINTA:
235
235
  /* don't want the probedata record for a printa() action */
data/ext/dtrace_program.c CHANGED
@@ -24,17 +24,22 @@ VALUE dtraceprogram_exec(VALUE self)
24
24
  {
25
25
  dtrace_prog_t *prog;
26
26
  dtrace_proginfo_t *proginfo;
27
- dtrace_hdl_t *handle;
27
+ dtrace_handle_t *handle;
28
28
  VALUE dtrace;
29
29
  VALUE dtraceprograminfo;
30
30
  int ret;
31
31
 
32
32
  Data_Get_Struct(self, dtrace_prog_t, prog);
33
- dtrace = rb_iv_get(self, "@dtrace");
34
- Data_Get_Struct(dtrace, dtrace_hdl_t, handle);
33
+ dtrace = rb_iv_get(self, "@handle");
34
+ Data_Get_Struct(dtrace, dtrace_handle_t, handle);
35
35
 
36
36
  proginfo = ALLOC(dtrace_proginfo_t);
37
- ret = dtrace_program_exec(handle, prog, proginfo);
37
+ if (!proginfo) {
38
+ rb_raise(eDtraceException, "alloc failed");
39
+ return Qnil;
40
+ }
41
+
42
+ ret = dtrace_program_exec(handle->hdl, prog, proginfo);
38
43
 
39
44
  if (ret == 0) {
40
45
  dtraceprograminfo = Data_Wrap_Struct(cDtraceProgramInfo, 0, NULL, proginfo);
@@ -42,7 +47,7 @@ VALUE dtraceprogram_exec(VALUE self)
42
47
  }
43
48
 
44
49
  if (ret < 0)
45
- rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
50
+ rb_raise(eDtraceException, dtrace_errmsg(handle->hdl, dtrace_errno(handle->hdl)));
46
51
 
47
52
  return Qnil;
48
53
  }
data/lib/dtrace.rb CHANGED
@@ -63,7 +63,7 @@ require 'dtracedata'
63
63
  # end
64
64
 
65
65
  class Dtrace
66
- VERSION = '0.0.4'
66
+ VERSION = '0.0.5'
67
67
 
68
68
  STATUS_NONE = 0
69
69
  STATUS_OKAY = 1
@@ -41,8 +41,11 @@ class DtraceConsumer
41
41
 
42
42
  def initialize(t)
43
43
  @t = t
44
- @curr = DtraceData.new
45
44
  @done = false
45
+ @types = []
46
+
47
+ @drophandler = nil
48
+ @errhandler = nil
46
49
  end
47
50
 
48
51
  private
@@ -69,7 +72,7 @@ class DtraceConsumer
69
72
  else
70
73
  @curr.finish
71
74
  block.call(@curr)
72
- @curr = DtraceData.new
75
+ @curr = DtraceData.new(@types)
73
76
  end
74
77
  end
75
78
  end
@@ -85,9 +88,36 @@ class DtraceConsumer
85
88
  @curr.add_bufdata(buf)
86
89
  end
87
90
  end
91
+
92
+ def filter_types(types)
93
+ @types = types
94
+ @curr = DtraceData.new(types)
95
+ end
88
96
 
89
97
  public
90
98
 
99
+ # Provide a proc which will be executed when a drop record is
100
+ # received.
101
+ def drophandler(&block)
102
+ @drophandler = block
103
+ @t.drop_consumer(proc do |drop|
104
+ if @drophandler
105
+ @drophandler.call(drop)
106
+ end
107
+ end)
108
+ end
109
+
110
+ # Provide a proc which will be executed when an error record is
111
+ # received.
112
+ def errhandler(&block)
113
+ @errhandler = block
114
+ @t.err_consumer(proc do |err|
115
+ if @errhandler
116
+ @errhandler.call(err)
117
+ end
118
+ end)
119
+ end
120
+
91
121
  # Signals that the client wishes to stop consuming trace data.
92
122
  def finish
93
123
  @t.stop
@@ -96,7 +126,17 @@ class DtraceConsumer
96
126
 
97
127
  # Waits for data from the D program, and yields the records returned
98
128
  # to the block given. Returns when the D program exits.
99
- def consume(&block)
129
+ #
130
+ # Pass a list of classes to restrict the types of data returned,
131
+ # from:
132
+ #
133
+ # * DtraceRecord
134
+ # * DtracePrintfRecord
135
+ # * DtraceAggregateSet
136
+ # * DtraceStackRecord
137
+ #
138
+ def consume(*types, &block)
139
+ filter_types(types)
100
140
  @t.buf_consumer(buf_consumer)
101
141
  begin
102
142
  while(true) do
@@ -113,7 +153,17 @@ class DtraceConsumer
113
153
  end
114
154
 
115
155
  # Yields the data waiting from the current program, then returns.
116
- def consume_once(&block)
156
+ #
157
+ # Pass a list of classes to restrict the types of data returned,
158
+ # from:
159
+ #
160
+ # * DtraceRecord
161
+ # * DtracePrintfRecord
162
+ # * DtraceAggregateSet
163
+ # * DtraceStackRecord
164
+ #
165
+ def consume_once(*types, &block)
166
+ filter_types(types)
117
167
  @t.buf_consumer(buf_consumer)
118
168
  @t.stop
119
169
  @t.work(probe_consumer, rec_consumer(block))
data/lib/dtracedata.rb CHANGED
@@ -9,22 +9,29 @@ class DtraceData
9
9
  attr_reader :probe
10
10
  attr_reader :cpu, :indent, :prefix, :flow
11
11
 
12
- def initialize
12
+ def initialize(types)
13
+ @types = types
13
14
  @data = []
14
15
  @curraggset = nil
15
16
  @curragg = nil
16
17
  end
17
18
 
19
+ def add_data(d)
20
+ if @types.length == 0 || @types.include?(d.class)
21
+ @data << d
22
+ end
23
+ end
24
+
18
25
  def finish
19
26
  if @curraggset
20
- @data << @curraggset
27
+ add_data(@curraggset)
21
28
  @curraggset = nil
22
29
  end
23
30
  end
24
31
 
25
32
  def add_recdata(rec)
26
33
  if @curraggset
27
- @data << @curraggset
34
+ add_data(@curraggset)
28
35
  @curraggset = nil
29
36
  end
30
37
  if rec.action == "printa"
@@ -34,7 +41,7 @@ class DtraceData
34
41
 
35
42
  def add_probedata(probedata)
36
43
  probedata.each_record do |p|
37
- @data << p
44
+ add_data(p)
38
45
  end
39
46
 
40
47
  # Record the probe that fired, and CPU/indent/prefix/flow
@@ -51,11 +58,11 @@ class DtraceData
51
58
  if r
52
59
  case r.class.to_s
53
60
  when DtraceStackRecord.to_s
54
- @data << r
61
+ add_data(r)
55
62
  when DtraceRecord.to_s
56
- @data << r
63
+ add_data(r)
57
64
  when DtracePrintfRecord.to_s
58
- @data << r
65
+ add_data(r)
59
66
  when DtraceAggData.to_s
60
67
  if @curragg == nil
61
68
  @curragg = DtraceAggregate.new
@@ -0,0 +1,183 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2007 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace'
7
+ require 'test/unit'
8
+
9
+ # Tests for the DropData record.
10
+
11
+ class TestDtraceDropsErrors < Test::Unit::TestCase
12
+
13
+ def test_drops
14
+ t = Dtrace.new
15
+ t.setopt("bufsize", "512")
16
+ t.setopt("strsize", "1024")
17
+
18
+ # drp.DTRACEDROP_PRINCIPAL.d
19
+ progtext = <<EOD
20
+ BEGIN
21
+ {
22
+ trace("Harding");
23
+ trace("Hoover");
24
+ trace("Nixon");
25
+ trace("Bush");
26
+ }
27
+
28
+ BEGIN
29
+ {
30
+ exit(0);
31
+ }
32
+ EOD
33
+
34
+ prog = t.compile progtext
35
+ prog.execute
36
+
37
+ c = DtraceConsumer.new(t)
38
+ assert c
39
+
40
+ i = 0
41
+ c.drophandler do |d|
42
+ assert_match(/1 drop on CPU [0-9]+/, d.msg)
43
+ assert_equal "drop to principal buffer", d.kind
44
+ assert_not_nil d.cpu
45
+ assert_equal 1, d.drops
46
+ assert_not_nil d.total
47
+ i = 1
48
+ end
49
+
50
+ t.go
51
+ c.consume do |d|
52
+ end
53
+
54
+ assert_equal 1, i
55
+ end
56
+
57
+ def test_error_handler_too_late
58
+ t = Dtrace.new
59
+ t.setopt("bufsize", "512")
60
+ t.setopt("strsize", "1024")
61
+
62
+ progtext = <<EOD
63
+ BEGIN
64
+ {
65
+ *(char *)NULL;
66
+ }
67
+ EOD
68
+
69
+ prog = t.compile progtext
70
+ prog.execute
71
+ t.go
72
+
73
+ c = DtraceConsumer.new(t)
74
+ assert c
75
+
76
+ # since we've already said "go", we now can't apply an error
77
+ # handler (DTrace will let us, but won't call it).
78
+ assert_raise(DtraceException) do
79
+ c.errhandler do |d|
80
+ # nothing
81
+ end
82
+ end
83
+
84
+ end
85
+
86
+ def test_errors
87
+ t = Dtrace.new
88
+ t.setopt("bufsize", "512")
89
+ t.setopt("strsize", "1024")
90
+
91
+ progtext = <<EOD
92
+ BEGIN
93
+ {
94
+ *(char *)NULL;
95
+ }
96
+ EOD
97
+
98
+ prog = t.compile progtext
99
+ prog.execute
100
+
101
+ c = DtraceConsumer.new(t)
102
+ assert c
103
+
104
+ i = 0
105
+ c.errhandler do |d|
106
+ assert_match(/error on enabled probe ID [0-9]+ \(ID [0-9]+: dtrace:::BEGIN\): invalid address \(0x0\) in action #1 at DIF offset 16/, d.msg)
107
+ assert_not_nil d.cpu
108
+ assert d.action
109
+ assert d.offset
110
+ assert d.fault
111
+ assert_not_nil d.addr
112
+ i = 1
113
+ end
114
+
115
+ t.go
116
+ c.consume_once do |d|
117
+ end
118
+
119
+ assert_equal 1, i
120
+ end
121
+
122
+ def test_error_and_drop_handler
123
+
124
+ t = Dtrace.new
125
+ t.setopt("bufsize", "512")
126
+ t.setopt("strsize", "1024")
127
+
128
+ progtext = <<EOD
129
+ BEGIN
130
+ {
131
+ trace("Harding");
132
+ trace("Hoover");
133
+ trace("Nixon");
134
+ trace("Bush");
135
+ }
136
+
137
+ BEGIN
138
+ {
139
+ *(char *)NULL;
140
+ }
141
+
142
+ ERROR
143
+ {
144
+ exit(0);
145
+ }
146
+ EOD
147
+
148
+ prog = t.compile progtext
149
+ prog.execute
150
+
151
+ c = DtraceConsumer.new(t)
152
+ assert c
153
+
154
+ errors = 0
155
+ c.errhandler do |d|
156
+ assert_match(/error on enabled probe ID [0-9]+ \(ID [0-9]+: dtrace:::BEGIN\): invalid address \(0x0\) in action #1 at DIF offset 16/, d.msg)
157
+ assert_not_nil d.cpu
158
+ assert d.action
159
+ assert d.offset
160
+ assert d.fault
161
+ assert_not_nil d.addr
162
+ errors = 1
163
+ end
164
+
165
+ drops = 0
166
+ c.drophandler do |d|
167
+ assert_match(/1 drop on CPU [0-9]+/, d.msg)
168
+ assert_equal "drop to principal buffer", d.kind
169
+ assert_not_nil d.cpu
170
+ assert_equal 1, d.drops
171
+ assert_not_nil d.total
172
+ drops = 1
173
+ end
174
+
175
+ t.go
176
+ c.consume do |d|
177
+ end
178
+
179
+ assert_equal 1, errors
180
+ assert_equal 1, drops
181
+ end
182
+
183
+ end
@@ -0,0 +1,108 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2007 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace'
7
+ require 'test/unit'
8
+
9
+ # Tests for the feature allowing you to filter DtraceData types
10
+
11
+ class TestDtraceTypefilter < Test::Unit::TestCase
12
+ def test_filter
13
+ t = Dtrace.new
14
+ t.setopt("bufsize", "4m")
15
+ t.setopt("aggsize", "4m")
16
+
17
+ progtext =<<EOD
18
+ profile-1000
19
+ {
20
+ @a[execname] = count();
21
+ @b[execname] = count();
22
+ }
23
+
24
+ profile-10
25
+ {
26
+ trace("foo");
27
+ printa(@a);
28
+ printf("bar");
29
+ printa(@b);
30
+ }
31
+ EOD
32
+
33
+ prog = t.compile progtext
34
+ prog.execute
35
+ t.go
36
+
37
+ sleep 1
38
+
39
+ c = DtraceConsumer.new(t)
40
+ assert c
41
+
42
+ data = []
43
+ c.consume_once(DtraceAggregateSet) do |d|
44
+ data << d
45
+ end
46
+
47
+ assert data.length > 0
48
+ data.each do |d|
49
+ assert d
50
+ assert_equal DtraceData, d.class
51
+ d.data.each do |agg|
52
+ assert_equal DtraceAggregateSet, agg.class
53
+ end
54
+ end
55
+
56
+ end
57
+
58
+ def test_filter_two_classes
59
+ t = Dtrace.new
60
+ t.setopt("bufsize", "4m")
61
+ t.setopt("aggsize", "4m")
62
+
63
+ progtext =<<EOD
64
+ profile-1000
65
+ {
66
+ @a[execname] = count();
67
+ @b[execname] = count();
68
+ }
69
+
70
+ profile-10
71
+ {
72
+ trace("foo");
73
+ printa(@a);
74
+ printf("bar");
75
+ printa(@b);
76
+ }
77
+ EOD
78
+
79
+ prog = t.compile progtext
80
+ prog.execute
81
+ t.go
82
+
83
+ sleep 1
84
+
85
+ c = DtraceConsumer.new(t)
86
+ assert c
87
+
88
+ data = []
89
+ c.consume_once(DtraceAggregateSet, DtracePrintfRecord) do |d|
90
+ data << d
91
+ end
92
+
93
+ assert data.length > 0
94
+ data.each do |d|
95
+ assert d
96
+ assert_equal DtraceData, d.class
97
+ d.data.each do |r|
98
+ if r.respond_to?(:add_aggregate)
99
+ assert_equal DtraceAggregateSet, r.class
100
+ else
101
+ assert_equal DtracePrintfRecord, r.class
102
+ end
103
+ end
104
+ end
105
+
106
+ end
107
+
108
+ end