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.
- data/LICENCE +20 -0
- data/README.md +51 -0
- data/ext/Makefile +187 -0
- data/ext/dtrace_aggdata.c +132 -0
- data/ext/dtrace_aggdata.c~ +141 -0
- data/ext/dtrace_aggdata.o +0 -0
- data/ext/dtrace_api.bundle +0 -0
- data/ext/dtrace_api.c +102 -0
- data/ext/dtrace_api.c~ +113 -0
- data/ext/dtrace_api.h +138 -0
- data/ext/dtrace_api.h~ +155 -0
- data/ext/dtrace_api.o +0 -0
- data/ext/dtrace_bufdata.c +130 -0
- data/ext/dtrace_bufdata.c~ +139 -0
- data/ext/dtrace_bufdata.o +0 -0
- data/ext/dtrace_dropdata.c +121 -0
- data/ext/dtrace_dropdata.c~ +131 -0
- data/ext/dtrace_dropdata.o +0 -0
- data/ext/dtrace_errdata.c +100 -0
- data/ext/dtrace_errdata.c~ +110 -0
- data/ext/dtrace_errdata.o +0 -0
- data/ext/dtrace_hdl.c +677 -0
- data/ext/dtrace_hdl.c~ +689 -0
- data/ext/dtrace_hdl.o +0 -0
- data/ext/dtrace_probedata.c +273 -0
- data/ext/dtrace_probedata.c~ +283 -0
- data/ext/dtrace_probedata.o +0 -0
- data/ext/dtrace_probedesc.c +93 -0
- data/ext/dtrace_probedesc.c~ +78 -0
- data/ext/dtrace_probedesc.o +0 -0
- data/ext/dtrace_process.c +44 -0
- data/ext/dtrace_process.c~ +56 -0
- data/ext/dtrace_process.o +0 -0
- data/ext/dtrace_program.c +52 -0
- data/ext/dtrace_program.c~ +62 -0
- data/ext/dtrace_program.o +0 -0
- data/ext/dtrace_programinfo.c +70 -0
- data/ext/dtrace_programinfo.c~ +60 -0
- data/ext/dtrace_programinfo.o +0 -0
- data/ext/dtrace_recdesc.c +37 -0
- data/ext/dtrace_recdesc.c~ +46 -0
- data/ext/dtrace_recdesc.o +0 -0
- data/ext/dtrace_util.c +92 -0
- data/ext/dtrace_util.o +0 -0
- data/ext/extconf.rb +7 -0
- data/lib/dtrace.rb +95 -0
- data/lib/dtrace/aggregate.rb +40 -0
- data/lib/dtrace/aggregateset.rb +19 -0
- data/lib/dtrace/consumer.rb +174 -0
- data/lib/dtrace/data.rb +85 -0
- data/lib/dtrace/dof.rb +8 -0
- data/lib/dtrace/printfrecord.rb +10 -0
- data/lib/dtrace/probedata.rb +23 -0
- data/lib/dtrace/probedesc.rb +15 -0
- data/lib/dtrace/record.rb +11 -0
- data/lib/dtrace/stackrecord.rb +31 -0
- data/lib/dtrace/tracer.rb +35 -0
- data/lib/dtrace/version.rb +8 -0
- data/lib/dtrace/version.rb~ +8 -0
- data/lib/dtraceconsumer.rb +9 -0
- data/test/test_aggregates.rb +45 -0
- data/test/test_drops_errors.rb +166 -0
- data/test/test_dtrace.rb +155 -0
- data/test/test_gc.rb +11 -0
- data/test/test_helper.rb +20 -0
- data/test/test_helper.rb~ +16 -0
- data/test/test_legacy_consumer.rb +47 -0
- data/test/test_probedata.rb +30 -0
- data/test/test_processes.rb +66 -0
- data/test/test_profile.rb +198 -0
- data/test/test_repeat.rb +50 -0
- data/test/test_rubyprobe.rb +52 -0
- data/test/test_rubyprobe.rb~ +52 -0
- data/test/test_typefilter.rb +94 -0
- metadata +121 -0
data/lib/dtrace/data.rb
ADDED
@@ -0,0 +1,85 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-DTrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
# The object returned from a consumer when a probe fires. Accumulates
|
6
|
+
# records from the callbacks, and is yielded when the data is complete.
|
7
|
+
class DTrace
|
8
|
+
class Data
|
9
|
+
attr_reader :data
|
10
|
+
attr_reader :probe
|
11
|
+
attr_reader :cpu, :indent, :prefix, :flow
|
12
|
+
|
13
|
+
def initialize(types)
|
14
|
+
@types = types
|
15
|
+
@data = []
|
16
|
+
@curraggset = nil
|
17
|
+
@curragg = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_data(d)
|
21
|
+
if @types.length == 0 || @types.include?(d.class)
|
22
|
+
@data << d
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finish
|
27
|
+
if @curraggset
|
28
|
+
add_data(@curraggset)
|
29
|
+
@curraggset = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_recdata(rec)
|
34
|
+
if @curraggset
|
35
|
+
add_data(@curraggset)
|
36
|
+
@curraggset = nil
|
37
|
+
end
|
38
|
+
if rec.action == "printa"
|
39
|
+
@curraggset = DTrace::AggregateSet.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_probedata(probedata)
|
44
|
+
probedata.each_record do |p|
|
45
|
+
add_data(p)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Record the probe that fired, and CPU/indent/prefix/flow
|
49
|
+
@probe = probedata.probe
|
50
|
+
@cpu = probedata.cpu
|
51
|
+
@indent = probedata.indent
|
52
|
+
@prefix = probedata.prefix
|
53
|
+
@flow = probedata.flow
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_bufdata(buf)
|
57
|
+
r = buf.record
|
58
|
+
|
59
|
+
p r
|
60
|
+
|
61
|
+
# buf records can be empty (trace();)
|
62
|
+
if r
|
63
|
+
case r.class.to_s
|
64
|
+
when DTrace::StackRecord.to_s
|
65
|
+
add_data(r)
|
66
|
+
when DTrace::Record.to_s
|
67
|
+
add_data(r)
|
68
|
+
when DTrace::PrintfRecord.to_s
|
69
|
+
add_data(r)
|
70
|
+
when DTrace::AggData.to_s
|
71
|
+
if @curragg == nil
|
72
|
+
@curragg = DTrace::Aggregate.new
|
73
|
+
end
|
74
|
+
if agg = @curragg.add_record(r)
|
75
|
+
if @curraggset
|
76
|
+
@curraggset.add_aggregate(@curragg)
|
77
|
+
end
|
78
|
+
@curragg = nil
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
end
|
85
|
+
end
|
data/lib/dtrace/dof.rb
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-DTrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
class DTrace
|
7
|
+
class ProbeData
|
8
|
+
|
9
|
+
def records
|
10
|
+
records = Array.new
|
11
|
+
self.each_record do |rec|
|
12
|
+
records << rec
|
13
|
+
end
|
14
|
+
records
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
rs = self.records
|
19
|
+
rs.map {|r| r.value }.join ', '
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,31 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-DTrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
# A record representing the result of a stack() or ustack()
|
7
|
+
# action. Its value is a list of symbolic stack frames:
|
8
|
+
#
|
9
|
+
# #<DTraceStackRecord:0x14e24 @value=
|
10
|
+
# ["libSystem.B.dylib`__sysctl+0xa",
|
11
|
+
# "libdtrace.dylib`dt_aggregate_go+0x9a",
|
12
|
+
# "dtrace_api.bundle`dtrace_hdl_go+0x30",
|
13
|
+
# "libruby.1.dylib`rb_eval_string_wrap+0x40fd",
|
14
|
+
# "libruby.1.dylib`rb_eval_string_wrap+0x4cdb",
|
15
|
+
# ...
|
16
|
+
# "libruby.1.dylib`rb_apply+0x392",
|
17
|
+
# "libruby.1.dylib`rb_eval_string_wrap+0xe82"]>
|
18
|
+
#
|
19
|
+
class DTrace
|
20
|
+
class StackRecord
|
21
|
+
attr_reader :value
|
22
|
+
|
23
|
+
# Given a stack as a string returned from DTrace, set the value of
|
24
|
+
# this record to a list of stack frames.
|
25
|
+
def parse(raw)
|
26
|
+
frames = raw.split(/\n/)
|
27
|
+
@value = frames.map {|f| f.lstrip }.select {|f| f.length > 0 }
|
28
|
+
end
|
29
|
+
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-DTrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
# Leopard's ruby-probe is DTracer, Solaris's is Tracer.
|
7
|
+
|
8
|
+
class DTrace
|
9
|
+
class Tracer
|
10
|
+
|
11
|
+
class NullTracer
|
12
|
+
def self.fire(arg0, arg1)
|
13
|
+
puts "NullTracer: #{arg0} #{arg1}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
@@tracer = nil
|
18
|
+
def self.fire(*args)
|
19
|
+
if @@tracer == nil
|
20
|
+
begin
|
21
|
+
# Avoid getting ourselves here:
|
22
|
+
@@tracer = Module.const_get('Tracer')
|
23
|
+
rescue NameError
|
24
|
+
begin
|
25
|
+
@@tracer = DTracer
|
26
|
+
rescue NameError
|
27
|
+
@@tracer = DTrace::Tracer::NullTracer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
@@tracer.fire(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
class TestAggregates < DTraceTest
|
4
|
+
|
5
|
+
def test_aggregate_group
|
6
|
+
progtext =<<EOD
|
7
|
+
profile-1000
|
8
|
+
{
|
9
|
+
@a[execname] = count();
|
10
|
+
@b[execname] = count();
|
11
|
+
}
|
12
|
+
|
13
|
+
profile-1
|
14
|
+
{
|
15
|
+
printa(@a);
|
16
|
+
printa(@b);
|
17
|
+
}
|
18
|
+
EOD
|
19
|
+
|
20
|
+
prog = @dtp.compile progtext
|
21
|
+
prog.execute
|
22
|
+
@dtp.go
|
23
|
+
|
24
|
+
sleep 3
|
25
|
+
|
26
|
+
c = DTrace::Consumer.new(@dtp)
|
27
|
+
assert c
|
28
|
+
|
29
|
+
data = []
|
30
|
+
c.consume_once do |d|
|
31
|
+
data << d
|
32
|
+
end
|
33
|
+
|
34
|
+
assert data.length > 0
|
35
|
+
data.each do |d|
|
36
|
+
assert d
|
37
|
+
assert_equal DTrace::Data, d.class
|
38
|
+
d.data.each do |agg|
|
39
|
+
assert_equal DTrace::AggregateSet, agg.class
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,166 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests for the DropData record.
|
4
|
+
|
5
|
+
class TestDropsErrors < DTraceTest
|
6
|
+
|
7
|
+
def test_drops
|
8
|
+
@dtp.setopt("bufsize", "512")
|
9
|
+
@dtp.setopt("strsize", "1024")
|
10
|
+
|
11
|
+
# drp.DTRACEDROP_PRINCIPAL.d
|
12
|
+
progtext = <<EOD
|
13
|
+
BEGIN
|
14
|
+
{
|
15
|
+
trace("Harding");
|
16
|
+
trace("Hoover");
|
17
|
+
trace("Nixon");
|
18
|
+
trace("Bush");
|
19
|
+
}
|
20
|
+
|
21
|
+
BEGIN
|
22
|
+
{
|
23
|
+
exit(0);
|
24
|
+
}
|
25
|
+
EOD
|
26
|
+
|
27
|
+
prog = @dtp.compile progtext
|
28
|
+
prog.execute
|
29
|
+
|
30
|
+
c = DTrace::Consumer.new(@dtp)
|
31
|
+
assert c
|
32
|
+
|
33
|
+
i = 0
|
34
|
+
c.drophandler do |d|
|
35
|
+
assert_match(/1 drop on CPU [0-9]+/, d.msg)
|
36
|
+
assert_equal "drop to principal buffer", d.kind
|
37
|
+
assert_not_nil d.cpu
|
38
|
+
assert_equal 1, d.drops
|
39
|
+
assert_not_nil d.total
|
40
|
+
i = 1
|
41
|
+
end
|
42
|
+
|
43
|
+
@dtp.go
|
44
|
+
c.consume do |d|
|
45
|
+
end
|
46
|
+
|
47
|
+
assert_equal 1, i
|
48
|
+
end
|
49
|
+
|
50
|
+
def test_error_handler_too_late
|
51
|
+
progtext = <<EOD
|
52
|
+
BEGIN
|
53
|
+
{
|
54
|
+
*(char *)NULL;
|
55
|
+
}
|
56
|
+
EOD
|
57
|
+
|
58
|
+
prog = @dtp.compile progtext
|
59
|
+
prog.execute
|
60
|
+
@dtp.go
|
61
|
+
|
62
|
+
c = DTrace::Consumer.new(@dtp)
|
63
|
+
assert c
|
64
|
+
|
65
|
+
# since we've already said "go", we now can't apply an error
|
66
|
+
# handler (DTrace will let us, but won't call it).
|
67
|
+
assert_raise(DTrace::Exception) do
|
68
|
+
c.errhandler do |d|
|
69
|
+
# nothing
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
end
|
74
|
+
|
75
|
+
def test_errors
|
76
|
+
progtext = <<EOD
|
77
|
+
BEGIN
|
78
|
+
{
|
79
|
+
*(char *)NULL;
|
80
|
+
}
|
81
|
+
EOD
|
82
|
+
|
83
|
+
prog = @dtp.compile progtext
|
84
|
+
prog.execute
|
85
|
+
|
86
|
+
c = DTrace::Consumer.new(@dtp)
|
87
|
+
assert c
|
88
|
+
|
89
|
+
i = 0
|
90
|
+
c.errhandler do |d|
|
91
|
+
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)
|
92
|
+
assert_not_nil d.cpu
|
93
|
+
assert d.action
|
94
|
+
assert d.offset
|
95
|
+
assert d.fault
|
96
|
+
assert_not_nil d.addr
|
97
|
+
i = 1
|
98
|
+
end
|
99
|
+
|
100
|
+
@dtp.go
|
101
|
+
c.consume_once do |d|
|
102
|
+
end
|
103
|
+
|
104
|
+
assert_equal 1, i
|
105
|
+
end
|
106
|
+
|
107
|
+
def test_error_and_drop_handler
|
108
|
+
@dtp.setopt("bufsize", "512")
|
109
|
+
@dtp.setopt("strsize", "1024")
|
110
|
+
|
111
|
+
progtext = <<EOD
|
112
|
+
BEGIN
|
113
|
+
{
|
114
|
+
trace("Harding");
|
115
|
+
trace("Hoover");
|
116
|
+
trace("Nixon");
|
117
|
+
trace("Bush");
|
118
|
+
}
|
119
|
+
|
120
|
+
BEGIN
|
121
|
+
{
|
122
|
+
*(char *)NULL;
|
123
|
+
}
|
124
|
+
|
125
|
+
ERROR
|
126
|
+
{
|
127
|
+
exit(0);
|
128
|
+
}
|
129
|
+
EOD
|
130
|
+
|
131
|
+
prog = @dtp.compile progtext
|
132
|
+
prog.execute
|
133
|
+
|
134
|
+
c = DTrace::Consumer.new(@dtp)
|
135
|
+
assert c
|
136
|
+
|
137
|
+
errors = 0
|
138
|
+
c.errhandler do |d|
|
139
|
+
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)
|
140
|
+
assert_not_nil d.cpu
|
141
|
+
assert d.action
|
142
|
+
assert d.offset
|
143
|
+
assert d.fault
|
144
|
+
assert_not_nil d.addr
|
145
|
+
errors = 1
|
146
|
+
end
|
147
|
+
|
148
|
+
drops = 0
|
149
|
+
c.drophandler do |d|
|
150
|
+
assert_match(/1 drop on CPU [0-9]+/, d.msg)
|
151
|
+
assert_equal "drop to principal buffer", d.kind
|
152
|
+
assert_not_nil d.cpu
|
153
|
+
assert_equal 1, d.drops
|
154
|
+
assert_not_nil d.total
|
155
|
+
drops = 1
|
156
|
+
end
|
157
|
+
|
158
|
+
@dtp.go
|
159
|
+
c.consume do |d|
|
160
|
+
end
|
161
|
+
|
162
|
+
assert_equal 1, errors
|
163
|
+
assert_equal 1, drops
|
164
|
+
end
|
165
|
+
|
166
|
+
end
|