ruby-dtrace 0.0.2 → 0.0.3
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 +9 -0
- data/Manifest.txt +11 -1
- data/README.txt +10 -11
- data/examples/scsi.rb +442 -0
- data/ext/dtrace_aggdata.c +4 -1
- data/ext/dtrace_api.c +18 -7
- data/ext/dtrace_api.h +48 -9
- data/ext/dtrace_bufdata.c +52 -4
- data/ext/dtrace_hdl.c +137 -86
- data/ext/dtrace_probedata.c +188 -50
- data/ext/dtrace_process.c +37 -0
- data/ext/dtrace_recdesc.c +31 -0
- data/lib/dtrace.rb +53 -1
- data/lib/dtraceaggregate.rb +25 -1
- data/lib/dtraceaggregateset.rb +17 -0
- data/lib/dtraceconsumer.rb +91 -67
- data/lib/dtracedata.rb +73 -0
- data/lib/dtraceprintfrecord.rb +8 -0
- data/lib/dtraceprobedata.rb +5 -0
- data/lib/dtracerecord.rb +2 -1
- data/lib/dtracestackrecord.rb +29 -0
- data/plugin/dtrace/lib/dtracer.rb +42 -2
- data/plugin/dtrace/views/dtrace/_report.rhtml +48 -3
- data/test/test_dtrace.rb +2 -0
- data/test/test_dtrace_aggregates.rb +56 -0
- data/test/test_dtrace_processes.rb +83 -0
- data/test/test_dtrace_profile.rb +232 -0
- data/test/test_dtrace_repeat.rb +51 -0
- data/test/test_dtrace_rubyprobe.rb +52 -0
- metadata +19 -5
- data/test/test_dtrace_workapi.rb +0 -142
data/test/test_dtrace.rb
CHANGED
@@ -0,0 +1,56 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
# Tests using the DTrace profile provider.
|
10
|
+
|
11
|
+
class TestDtraceAggregates < Test::Unit::TestCase
|
12
|
+
def test_aggregate_group
|
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
|
+
printa(@a);
|
27
|
+
printa(@b);
|
28
|
+
}
|
29
|
+
EOD
|
30
|
+
|
31
|
+
prog = t.compile progtext
|
32
|
+
prog.execute
|
33
|
+
t.go
|
34
|
+
|
35
|
+
sleep 1
|
36
|
+
|
37
|
+
c = DtraceConsumer.new(t)
|
38
|
+
assert c
|
39
|
+
|
40
|
+
data = []
|
41
|
+
c.consume_once do |d|
|
42
|
+
data << d
|
43
|
+
end
|
44
|
+
|
45
|
+
assert data.length > 0
|
46
|
+
data.each do |d|
|
47
|
+
assert d
|
48
|
+
assert_equal DtraceData, d.class
|
49
|
+
d.data.each do |agg|
|
50
|
+
assert_equal DtraceAggregateSet, agg.class
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
@@ -0,0 +1,83 @@
|
|
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 creating and grabbing processes.
|
10
|
+
|
11
|
+
class TestDtraceProcesses < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_createprocess
|
14
|
+
|
15
|
+
t = Dtrace.new
|
16
|
+
t.setopt("bufsize", "8m")
|
17
|
+
t.setopt("aggsize", "4m")
|
18
|
+
t.setopt("stackframes", "5")
|
19
|
+
t.setopt("strsize", "131072")
|
20
|
+
|
21
|
+
progtext = <<EOD
|
22
|
+
pid$target:*::entry,
|
23
|
+
pid$target:*::return
|
24
|
+
{
|
25
|
+
trace(pid);
|
26
|
+
}
|
27
|
+
EOD
|
28
|
+
|
29
|
+
p = t.createprocess([ '/usr/bin/true' ])
|
30
|
+
prog = t.compile(progtext)
|
31
|
+
prog.execute
|
32
|
+
t.go
|
33
|
+
p.continue
|
34
|
+
|
35
|
+
i = 0
|
36
|
+
c = DtraceConsumer.new(t)
|
37
|
+
c.consume do |d|
|
38
|
+
assert d
|
39
|
+
assert_equal "pid#{d.data[0].value}", d.probe.provider
|
40
|
+
i = i + 1
|
41
|
+
if i > 10
|
42
|
+
c.finish
|
43
|
+
end
|
44
|
+
end
|
45
|
+
assert i > 0
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_grabprocess
|
49
|
+
|
50
|
+
t = Dtrace.new
|
51
|
+
t.setopt("bufsize", "8m")
|
52
|
+
t.setopt("aggsize", "4m")
|
53
|
+
t.setopt("stackframes", "5")
|
54
|
+
t.setopt("strsize", "131072")
|
55
|
+
|
56
|
+
progtext = <<EOD
|
57
|
+
pid$target:*::entry,
|
58
|
+
pid$target:*::return
|
59
|
+
{
|
60
|
+
|
61
|
+
}
|
62
|
+
EOD
|
63
|
+
|
64
|
+
pid = Kernel.fork { (0..9).each do sleep 1 end }
|
65
|
+
p = t.grabprocess(pid)
|
66
|
+
prog = t.compile(progtext)
|
67
|
+
prog.execute
|
68
|
+
|
69
|
+
t.go
|
70
|
+
p.continue
|
71
|
+
|
72
|
+
sleep 3
|
73
|
+
|
74
|
+
i = 0
|
75
|
+
c = DtraceConsumer.new(t)
|
76
|
+
c.consume_once do |d|
|
77
|
+
assert d
|
78
|
+
assert_equal "pid#{pid}", d.probe.provider
|
79
|
+
i = i + 1
|
80
|
+
end
|
81
|
+
assert i > 0
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,232 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
# Tests using the DTrace profile provider.
|
10
|
+
|
11
|
+
class TestDtraceProfile < Test::Unit::TestCase
|
12
|
+
|
13
|
+
def test_dprogram_run
|
14
|
+
t = Dtrace.new
|
15
|
+
t.setopt("bufsize", "4m")
|
16
|
+
t.setopt("aggsize", "4m")
|
17
|
+
|
18
|
+
progtext = 'profile:::profile-1 { trace("foo"); }'
|
19
|
+
|
20
|
+
prog = t.compile progtext
|
21
|
+
prog.execute
|
22
|
+
t.go
|
23
|
+
sleep 2
|
24
|
+
|
25
|
+
c = DtraceConsumer.new(t)
|
26
|
+
assert c
|
27
|
+
|
28
|
+
i = 0
|
29
|
+
c.consume do |d|
|
30
|
+
assert d
|
31
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
32
|
+
assert_not_nil d.cpu
|
33
|
+
|
34
|
+
d.data.each do |r|
|
35
|
+
assert_equal r.value, "foo"
|
36
|
+
end
|
37
|
+
|
38
|
+
i = i + 1
|
39
|
+
if i > 10
|
40
|
+
c.finish
|
41
|
+
end
|
42
|
+
end
|
43
|
+
assert i > 0
|
44
|
+
end
|
45
|
+
|
46
|
+
def test_dprogram_aggregate
|
47
|
+
t = Dtrace.new
|
48
|
+
t.setopt("bufsize", "4m")
|
49
|
+
t.setopt("aggsize", "4m")
|
50
|
+
|
51
|
+
progtext = <<EOD
|
52
|
+
profile-1000
|
53
|
+
{
|
54
|
+
@a[execname] = count();
|
55
|
+
}
|
56
|
+
|
57
|
+
profile-10
|
58
|
+
{
|
59
|
+
printa(@a)
|
60
|
+
}
|
61
|
+
EOD
|
62
|
+
|
63
|
+
prog = t.compile progtext
|
64
|
+
prog.execute
|
65
|
+
t.go
|
66
|
+
sleep 2
|
67
|
+
|
68
|
+
c = DtraceConsumer.new(t)
|
69
|
+
|
70
|
+
i = 0
|
71
|
+
c.consume do |d|
|
72
|
+
assert d
|
73
|
+
assert_not_nil d.cpu
|
74
|
+
assert_equal "profile:::profile-10", d.probe.to_s
|
75
|
+
|
76
|
+
d.data.each do |r|
|
77
|
+
assert_equal DtraceAggregateSet, r.class
|
78
|
+
r.data.each do |a|
|
79
|
+
assert_not_nil a.value
|
80
|
+
assert_not_nil a.tuple
|
81
|
+
assert_equal 1, a.tuple.length
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
i = i + 1
|
86
|
+
if i >= 10
|
87
|
+
c.finish
|
88
|
+
end
|
89
|
+
end
|
90
|
+
assert i > 0
|
91
|
+
end
|
92
|
+
|
93
|
+
def test_dprogram_printf
|
94
|
+
t = Dtrace.new
|
95
|
+
t.setopt("bufsize", "4m")
|
96
|
+
t.setopt("aggsize", "4m")
|
97
|
+
|
98
|
+
progtext = <<EOD
|
99
|
+
profile-1
|
100
|
+
{
|
101
|
+
printf("execname: %s %s", execname, "foo")
|
102
|
+
}
|
103
|
+
EOD
|
104
|
+
|
105
|
+
prog = t.compile progtext
|
106
|
+
prog.execute
|
107
|
+
t.go
|
108
|
+
sleep 2
|
109
|
+
|
110
|
+
c = DtraceConsumer.new(t)
|
111
|
+
|
112
|
+
i = 0
|
113
|
+
c.consume do |d|
|
114
|
+
assert d
|
115
|
+
assert_not_nil d.cpu
|
116
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
117
|
+
|
118
|
+
i = i + 1
|
119
|
+
if i >= 10
|
120
|
+
c.finish
|
121
|
+
end
|
122
|
+
end
|
123
|
+
assert i > 0
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_dprogram_aggregate_once
|
127
|
+
t = Dtrace.new
|
128
|
+
t.setopt("bufsize", "4m")
|
129
|
+
t.setopt("aggsize", "4m")
|
130
|
+
|
131
|
+
progtext = <<EOD
|
132
|
+
profile-1000hz
|
133
|
+
{
|
134
|
+
@a[execname] = count();
|
135
|
+
}
|
136
|
+
|
137
|
+
END
|
138
|
+
{
|
139
|
+
printa(@a)
|
140
|
+
}
|
141
|
+
EOD
|
142
|
+
|
143
|
+
prog = t.compile progtext
|
144
|
+
prog.execute
|
145
|
+
t.go
|
146
|
+
sleep 2
|
147
|
+
|
148
|
+
i = 0
|
149
|
+
c = DtraceConsumer.new(t)
|
150
|
+
c.consume_once do |d|
|
151
|
+
i = i + 1
|
152
|
+
assert d
|
153
|
+
assert_not_nil d.cpu
|
154
|
+
assert_equal "dtrace:::END", d.probe.to_s
|
155
|
+
|
156
|
+
d.data.each do |r|
|
157
|
+
assert_equal DtraceAggregateSet, r.class
|
158
|
+
r.data.each do |a|
|
159
|
+
assert_not_nil a.value
|
160
|
+
assert_not_nil a.tuple
|
161
|
+
assert_equal 1, a.tuple.length
|
162
|
+
end
|
163
|
+
end
|
164
|
+
end
|
165
|
+
assert i > 0
|
166
|
+
end
|
167
|
+
|
168
|
+
def test_stack
|
169
|
+
t = Dtrace.new
|
170
|
+
t.setopt("bufsize", "8m")
|
171
|
+
t.setopt("aggsize", "4m")
|
172
|
+
t.setopt("stackframes", "5")
|
173
|
+
t.setopt("strsize", "131072")
|
174
|
+
|
175
|
+
progtext = "profile-1 { trace(execname); stack(); }"
|
176
|
+
prog = t.compile progtext
|
177
|
+
prog.execute
|
178
|
+
t.go
|
179
|
+
sleep 2
|
180
|
+
|
181
|
+
c = DtraceConsumer.new(t)
|
182
|
+
i = 0
|
183
|
+
c.consume do |d|
|
184
|
+
assert d
|
185
|
+
assert_not_nil d.cpu
|
186
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
187
|
+
|
188
|
+
assert_equal 2, d.data.length
|
189
|
+
assert_equal DtraceRecord, d.data[0].class
|
190
|
+
assert_equal DtraceStackRecord, d.data[1].class
|
191
|
+
|
192
|
+
i = i + 1
|
193
|
+
if i > 10
|
194
|
+
c.finish
|
195
|
+
end
|
196
|
+
end
|
197
|
+
assert i > 0
|
198
|
+
end
|
199
|
+
|
200
|
+
def test_ustack
|
201
|
+
t = Dtrace.new
|
202
|
+
t.setopt("bufsize", "8m")
|
203
|
+
t.setopt("aggsize", "4m")
|
204
|
+
t.setopt("stackframes", "5")
|
205
|
+
t.setopt("strsize", "131072")
|
206
|
+
|
207
|
+
progtext = "profile-1 { trace(execname); ustack(); }"
|
208
|
+
prog = t.compile progtext
|
209
|
+
prog.execute
|
210
|
+
t.go
|
211
|
+
sleep 2
|
212
|
+
|
213
|
+
c = DtraceConsumer.new(t)
|
214
|
+
i = 0
|
215
|
+
c.consume do |d|
|
216
|
+
assert d
|
217
|
+
assert_not_nil d.cpu
|
218
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
219
|
+
|
220
|
+
assert_equal 2, d.data.length
|
221
|
+
assert_equal DtraceRecord, d.data[0].class
|
222
|
+
assert_equal DtraceStackRecord, d.data[1].class
|
223
|
+
|
224
|
+
i = i + 1
|
225
|
+
if i > 10
|
226
|
+
c.finish
|
227
|
+
end
|
228
|
+
end
|
229
|
+
assert i > 0
|
230
|
+
end
|
231
|
+
|
232
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
# Test repeatedly using DTrace in the same process. Show that we can
|
10
|
+
# reopen the DTrace handle multiple times, without explictly closing
|
11
|
+
# it (that happens in GC, so in this script that's probably right at
|
12
|
+
# the end).
|
13
|
+
|
14
|
+
class TestDtraceRepeat < Test::Unit::TestCase
|
15
|
+
|
16
|
+
def test_repeats
|
17
|
+
(0..9).each do |i|
|
18
|
+
t = Dtrace.new
|
19
|
+
t.setopt("bufsize", "4m")
|
20
|
+
t.setopt("aggsize", "4m")
|
21
|
+
|
22
|
+
progtext = 'syscall:::entry { trace("foo"); }'
|
23
|
+
|
24
|
+
prog = t.compile progtext
|
25
|
+
prog.execute
|
26
|
+
t.go
|
27
|
+
|
28
|
+
# Let some activity happen.
|
29
|
+
sleep 1
|
30
|
+
|
31
|
+
c = DtraceConsumer.new(t)
|
32
|
+
assert c
|
33
|
+
|
34
|
+
i = 0
|
35
|
+
c.consume do |d|
|
36
|
+
assert d
|
37
|
+
assert_not_nil d.cpu
|
38
|
+
assert_equal 'syscall', d.probe.provider
|
39
|
+
assert_not_nil d.probe.func
|
40
|
+
assert_equal 'entry', d.probe.name
|
41
|
+
|
42
|
+
d.data.each do |r|
|
43
|
+
assert_equal 'foo', r.value
|
44
|
+
end
|
45
|
+
c.finish
|
46
|
+
i = i + 1
|
47
|
+
end
|
48
|
+
assert i > 0
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace'
|
7
|
+
require 'test/unit'
|
8
|
+
|
9
|
+
class TestDtrace < Test::Unit::TestCase
|
10
|
+
def test_rubyprobe
|
11
|
+
t = Dtrace.new
|
12
|
+
t.setopt("bufsize", "4m")
|
13
|
+
|
14
|
+
progtext = <<EOD
|
15
|
+
ruby*:::ruby-probe
|
16
|
+
{
|
17
|
+
trace(copyinstr(arg0));
|
18
|
+
trace(copyinstr(arg1));
|
19
|
+
}
|
20
|
+
EOD
|
21
|
+
|
22
|
+
prog = t.compile progtext
|
23
|
+
prog.execute
|
24
|
+
t.go
|
25
|
+
|
26
|
+
c = DtraceConsumer.new(t)
|
27
|
+
|
28
|
+
# Leopard's ruby-probe is DTracer, Solaris's is Tracer.
|
29
|
+
begin
|
30
|
+
trace_module = DTracer
|
31
|
+
rescue NameError
|
32
|
+
trace_module = Tracer
|
33
|
+
end
|
34
|
+
|
35
|
+
(0..9).each do |i|
|
36
|
+
trace_module.fire("foo", i.to_s)
|
37
|
+
end
|
38
|
+
|
39
|
+
data = []
|
40
|
+
c.consume_once do |d|
|
41
|
+
data << d
|
42
|
+
end
|
43
|
+
|
44
|
+
(0..9).each do |i|
|
45
|
+
d = data.shift
|
46
|
+
assert_equal("foo", d.data[0].value)
|
47
|
+
assert_equal(i.to_s, d.data[1].value)
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|