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/test/test_dtrace.rb
ADDED
@@ -0,0 +1,155 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests for the DTrace handle class
|
4
|
+
|
5
|
+
class TestDTrace < DTraceTest
|
6
|
+
|
7
|
+
def test_dtrace
|
8
|
+
assert_equal Object, DTrace.superclass
|
9
|
+
assert_equal DTrace, @dtp.class
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_list_probes
|
13
|
+
probe_count = 0
|
14
|
+
@dtp.each_probe do |probe|
|
15
|
+
assert probe.provider
|
16
|
+
assert probe.mod
|
17
|
+
assert probe.func
|
18
|
+
assert probe.name
|
19
|
+
probe_count += 1
|
20
|
+
end
|
21
|
+
assert probe_count
|
22
|
+
end
|
23
|
+
|
24
|
+
def test_list_probes_match
|
25
|
+
probe_count = 0
|
26
|
+
@dtp.each_probe('syscall:::') do |probe|
|
27
|
+
assert probe.provider
|
28
|
+
assert probe.mod
|
29
|
+
assert probe.func
|
30
|
+
assert probe.name
|
31
|
+
probe_count += 1
|
32
|
+
end
|
33
|
+
assert probe_count
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_list_probes_match_usdt
|
37
|
+
probe_count = 0
|
38
|
+
@dtp.each_probe("pid#{$$}:::return") do |probe|
|
39
|
+
puts probe
|
40
|
+
assert probe.provider
|
41
|
+
assert probe.mod
|
42
|
+
assert probe.func
|
43
|
+
assert probe.name
|
44
|
+
probe_count += 1
|
45
|
+
end
|
46
|
+
assert probe_count
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_list_probes_match_prog
|
50
|
+
progtext = "syscall:::return
|
51
|
+
{
|
52
|
+
@calls[execname] = count();
|
53
|
+
@fcalls[probefunc] = count();
|
54
|
+
}
|
55
|
+
|
56
|
+
syscall:::entry
|
57
|
+
/pid == $1/
|
58
|
+
{
|
59
|
+
@calls[execname] = count();
|
60
|
+
@fcalls[probefunc] = count();
|
61
|
+
}"
|
62
|
+
prog = @dtp.compile(progtext, $$.to_s)
|
63
|
+
prog.execute
|
64
|
+
|
65
|
+
probe_count = 0
|
66
|
+
@dtp.each_probe_prog(prog) do |probe|
|
67
|
+
assert probe.provider
|
68
|
+
assert probe.mod
|
69
|
+
assert probe.func
|
70
|
+
assert probe.name
|
71
|
+
probe_count += 1
|
72
|
+
end
|
73
|
+
assert probe_count
|
74
|
+
end
|
75
|
+
|
76
|
+
def test_list_probes_match_badpattern
|
77
|
+
probe_count = 0
|
78
|
+
assert_raises DTrace::Exception do
|
79
|
+
@dtp.each_probe('syscall') do |probe|
|
80
|
+
nil
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_compile
|
86
|
+
progtext = "syscall:::entry
|
87
|
+
{
|
88
|
+
@calls[execname] = count();
|
89
|
+
@fcalls[probefunc] = count();
|
90
|
+
}"
|
91
|
+
|
92
|
+
prog = @dtp.compile progtext
|
93
|
+
assert prog
|
94
|
+
prog.execute
|
95
|
+
|
96
|
+
info = prog.info
|
97
|
+
assert info
|
98
|
+
assert info.aggregates_count
|
99
|
+
assert_equal 0, info.speculations_count
|
100
|
+
assert info.recgens_count
|
101
|
+
assert info.matches_count
|
102
|
+
end
|
103
|
+
|
104
|
+
def test_compile_with_args
|
105
|
+
progtext = "syscall:::entry
|
106
|
+
/pid == $1/
|
107
|
+
{
|
108
|
+
@calls[execname] = count();
|
109
|
+
@fcalls[probefunc] = count();
|
110
|
+
}"
|
111
|
+
|
112
|
+
prog = @dtp.compile(progtext, $$.to_s)
|
113
|
+
assert prog
|
114
|
+
prog.execute
|
115
|
+
|
116
|
+
info = prog.info
|
117
|
+
assert info
|
118
|
+
assert_equal 2, info.aggregates_count
|
119
|
+
assert_equal 0, info.speculations_count
|
120
|
+
assert_equal 4, info.recgens_count
|
121
|
+
|
122
|
+
# matches_count is platform dependent
|
123
|
+
assert info.matches_count
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_run
|
127
|
+
progtext = "syscall:::entry
|
128
|
+
{
|
129
|
+
@calls[execname] = count();
|
130
|
+
@fcalls[probefunc] = count();
|
131
|
+
}"
|
132
|
+
|
133
|
+
prog = @dtp.compile progtext
|
134
|
+
assert prog
|
135
|
+
prog.execute
|
136
|
+
assert_equal 0, @dtp.status # none
|
137
|
+
|
138
|
+
@dtp.go
|
139
|
+
|
140
|
+
assert_equal 1, @dtp.status # ok
|
141
|
+
sleep 1
|
142
|
+
assert_equal 1, @dtp.status # ok
|
143
|
+
@dtp.stop
|
144
|
+
assert_equal 4, @dtp.status # stopped
|
145
|
+
end
|
146
|
+
|
147
|
+
def test_bad_program
|
148
|
+
progtext = "blah blahb albhacasfas"
|
149
|
+
e = assert_raise DTrace::Exception do
|
150
|
+
prog = @dtp.compile progtext
|
151
|
+
end
|
152
|
+
assert_equal "probe description :::blah does not match any probes", e.message
|
153
|
+
end
|
154
|
+
|
155
|
+
end
|
data/test/test_gc.rb
ADDED
data/test/test_helper.rb
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'dtrace'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class DTraceTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@dtp = DTrace.new
|
8
|
+
@dtp.setopt("bufsize", "4m")
|
9
|
+
@dtp.setopt("aggsize", "4m")
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
@dtp.close unless @dtp.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_nothing
|
17
|
+
assert(1)
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'dtrace'
|
2
|
+
require 'test/unit'
|
3
|
+
|
4
|
+
class DTraceTest < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def setup
|
7
|
+
@dtp = DTrace.new
|
8
|
+
@dtp.setopt("bufsize", "4m")
|
9
|
+
@dtp.setopt("aggsize", "4m")
|
10
|
+
end
|
11
|
+
|
12
|
+
def teardown
|
13
|
+
@dtp.close unless @dtp.nil?
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests using the DTrace profile provider.
|
4
|
+
|
5
|
+
class TestLegacyConsumer < DTraceTest
|
6
|
+
|
7
|
+
def test_aggregate_group
|
8
|
+
progtext =<<EOD
|
9
|
+
profile-1000
|
10
|
+
{
|
11
|
+
@a[execname] = count();
|
12
|
+
@b[execname] = count();
|
13
|
+
}
|
14
|
+
|
15
|
+
profile-1
|
16
|
+
{
|
17
|
+
printa(@a);
|
18
|
+
printa(@b);
|
19
|
+
}
|
20
|
+
EOD
|
21
|
+
|
22
|
+
prog = @dtp.compile progtext
|
23
|
+
prog.execute
|
24
|
+
@dtp.go
|
25
|
+
|
26
|
+
sleep 3
|
27
|
+
|
28
|
+
c = DTraceConsumer.new(@dtp)
|
29
|
+
assert c
|
30
|
+
|
31
|
+
data = []
|
32
|
+
c.consume_once do |d|
|
33
|
+
data << d
|
34
|
+
end
|
35
|
+
|
36
|
+
assert data.length > 0
|
37
|
+
data.each do |d|
|
38
|
+
assert d
|
39
|
+
assert_equal DTrace::Data, d.class
|
40
|
+
d.data.each do |agg|
|
41
|
+
assert_equal DTrace::AggregateSet, agg.class
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
|
47
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests for trace()d data.
|
4
|
+
|
5
|
+
class TestProbedata < DTraceTest
|
6
|
+
|
7
|
+
def test_longlongs
|
8
|
+
code = <<D
|
9
|
+
profile-100
|
10
|
+
{
|
11
|
+
trace(walltimestamp);
|
12
|
+
}
|
13
|
+
D
|
14
|
+
@dtp.compile(code).execute
|
15
|
+
@dtp.go
|
16
|
+
|
17
|
+
c = DTrace::Consumer.new(@dtp)
|
18
|
+
assert c
|
19
|
+
|
20
|
+
i = 0
|
21
|
+
c.consume do |d|
|
22
|
+
wallts = d.data[0].value
|
23
|
+
assert wallts > 2**32
|
24
|
+
i = i + 1
|
25
|
+
if i > 10
|
26
|
+
c.finish
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests for creating and grabbing processes.
|
4
|
+
|
5
|
+
class TestDTraceProcesses < DTraceTest
|
6
|
+
|
7
|
+
def test_createprocess
|
8
|
+
progtext = <<EOD
|
9
|
+
pid$target:*::entry,
|
10
|
+
pid$target:*::return
|
11
|
+
{
|
12
|
+
trace(pid);
|
13
|
+
}
|
14
|
+
EOD
|
15
|
+
|
16
|
+
p = @dtp.createprocess([ '/usr/bin/true' ])
|
17
|
+
prog = @dtp.compile(progtext)
|
18
|
+
prog.execute
|
19
|
+
@dtp.go
|
20
|
+
p.continue
|
21
|
+
|
22
|
+
i = 0
|
23
|
+
c = DTrace::Consumer.new(@dtp)
|
24
|
+
c.consume do |d|
|
25
|
+
assert d
|
26
|
+
assert_equal "pid#{d.data[0].value}", d.probe.provider
|
27
|
+
i = i + 1
|
28
|
+
|
29
|
+
if i > 10
|
30
|
+
c.finish
|
31
|
+
end
|
32
|
+
end
|
33
|
+
assert i > 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_grabprocess
|
37
|
+
pid = Kernel.fork { exec '/bin/sleep', '2' }
|
38
|
+
|
39
|
+
progtext = <<EOD
|
40
|
+
pid$target:::entry,
|
41
|
+
pid$target:::return
|
42
|
+
{
|
43
|
+
trace(execname);
|
44
|
+
}
|
45
|
+
EOD
|
46
|
+
|
47
|
+
p = @dtp.grabprocess(pid)
|
48
|
+
prog = @dtp.compile(progtext)
|
49
|
+
prog.execute
|
50
|
+
|
51
|
+
@dtp.go
|
52
|
+
p.continue
|
53
|
+
|
54
|
+
records = 0
|
55
|
+
c = DTrace::Consumer.new(@dtp)
|
56
|
+
c.consume do |d|
|
57
|
+
assert d
|
58
|
+
assert_equal "pid#{pid}", d.probe.provider
|
59
|
+
records = records + 1
|
60
|
+
c.finish
|
61
|
+
end
|
62
|
+
assert records > 0
|
63
|
+
|
64
|
+
Process.waitpid(pid, 0)
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,198 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
# Tests using the DTrace profile provider.
|
4
|
+
|
5
|
+
class TestProfile < DTraceTest
|
6
|
+
|
7
|
+
def test_dprogram_run
|
8
|
+
progtext = 'profile:::profile-1 { trace("foo"); }'
|
9
|
+
|
10
|
+
prog = @dtp.compile progtext
|
11
|
+
prog.execute
|
12
|
+
@dtp.go
|
13
|
+
sleep 2
|
14
|
+
|
15
|
+
c = DTrace::Consumer.new(@dtp)
|
16
|
+
assert c
|
17
|
+
|
18
|
+
i = 0
|
19
|
+
c.consume do |d|
|
20
|
+
assert d
|
21
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
22
|
+
assert_not_nil d.cpu
|
23
|
+
|
24
|
+
d.data.each do |r|
|
25
|
+
assert_equal r.value, "foo"
|
26
|
+
end
|
27
|
+
|
28
|
+
i = i + 1
|
29
|
+
if i > 10
|
30
|
+
c.finish
|
31
|
+
end
|
32
|
+
end
|
33
|
+
assert i > 0
|
34
|
+
end
|
35
|
+
|
36
|
+
def test_dprogram_aggregate
|
37
|
+
progtext = <<EOD
|
38
|
+
profile-1000
|
39
|
+
{
|
40
|
+
@a[execname] = count();
|
41
|
+
}
|
42
|
+
|
43
|
+
profile-10
|
44
|
+
{
|
45
|
+
printa(@a)
|
46
|
+
}
|
47
|
+
EOD
|
48
|
+
|
49
|
+
prog = @dtp.compile progtext
|
50
|
+
prog.execute
|
51
|
+
@dtp.go
|
52
|
+
sleep 2
|
53
|
+
|
54
|
+
c = DTrace::Consumer.new(@dtp)
|
55
|
+
|
56
|
+
i = 0
|
57
|
+
c.consume do |d|
|
58
|
+
assert d
|
59
|
+
assert_not_nil d.cpu
|
60
|
+
assert_equal "profile:::profile-10", d.probe.to_s
|
61
|
+
|
62
|
+
d.data.each do |r|
|
63
|
+
assert_equal DTrace::AggregateSet, r.class
|
64
|
+
r.data.each do |a|
|
65
|
+
assert_not_nil a.value
|
66
|
+
assert_not_nil a.tuple
|
67
|
+
assert_equal 1, a.tuple.length
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
i = i + 1
|
72
|
+
if i >= 10
|
73
|
+
c.finish
|
74
|
+
end
|
75
|
+
end
|
76
|
+
assert i > 0
|
77
|
+
end
|
78
|
+
|
79
|
+
def test_dprogram_printf
|
80
|
+
progtext = <<EOD
|
81
|
+
profile-1
|
82
|
+
{
|
83
|
+
printf("execname: %s %s", execname, "foo")
|
84
|
+
}
|
85
|
+
EOD
|
86
|
+
|
87
|
+
prog = @dtp.compile progtext
|
88
|
+
prog.execute
|
89
|
+
@dtp.go
|
90
|
+
sleep 2
|
91
|
+
|
92
|
+
c = DTrace::Consumer.new(@dtp)
|
93
|
+
|
94
|
+
i = 0
|
95
|
+
c.consume do |d|
|
96
|
+
assert d
|
97
|
+
assert_not_nil d.cpu
|
98
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
99
|
+
|
100
|
+
i = i + 1
|
101
|
+
if i >= 10
|
102
|
+
c.finish
|
103
|
+
end
|
104
|
+
end
|
105
|
+
assert i > 0
|
106
|
+
end
|
107
|
+
|
108
|
+
def test_dprogram_aggregate_once
|
109
|
+
progtext = <<EOD
|
110
|
+
profile-1000hz
|
111
|
+
{
|
112
|
+
@a[execname] = count();
|
113
|
+
}
|
114
|
+
|
115
|
+
END
|
116
|
+
{
|
117
|
+
printa(@a)
|
118
|
+
}
|
119
|
+
EOD
|
120
|
+
|
121
|
+
prog = @dtp.compile progtext
|
122
|
+
prog.execute
|
123
|
+
@dtp.go
|
124
|
+
sleep 2
|
125
|
+
|
126
|
+
i = 0
|
127
|
+
c = DTrace::Consumer.new(@dtp)
|
128
|
+
c.consume_once do |d|
|
129
|
+
i = i + 1
|
130
|
+
assert d
|
131
|
+
assert_not_nil d.cpu
|
132
|
+
assert_equal "dtrace:::END", d.probe.to_s
|
133
|
+
|
134
|
+
d.data.each do |r|
|
135
|
+
assert_equal DTrace::AggregateSet, r.class
|
136
|
+
r.data.each do |a|
|
137
|
+
assert_not_nil a.value
|
138
|
+
assert_not_nil a.tuple
|
139
|
+
assert_equal 1, a.tuple.length
|
140
|
+
end
|
141
|
+
end
|
142
|
+
end
|
143
|
+
assert i > 0
|
144
|
+
end
|
145
|
+
|
146
|
+
def test_stack
|
147
|
+
progtext = "profile-1 { trace(execname); stack(); }"
|
148
|
+
prog = @dtp.compile progtext
|
149
|
+
prog.execute
|
150
|
+
@dtp.go
|
151
|
+
sleep 2
|
152
|
+
|
153
|
+
c = DTrace::Consumer.new(@dtp)
|
154
|
+
i = 0
|
155
|
+
c.consume do |d|
|
156
|
+
assert d
|
157
|
+
assert_not_nil d.cpu
|
158
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
159
|
+
|
160
|
+
assert_equal 2, d.data.length
|
161
|
+
assert_equal DTrace::Record, d.data[0].class
|
162
|
+
assert_equal DTrace::StackRecord, d.data[1].class
|
163
|
+
|
164
|
+
i = i + 1
|
165
|
+
if i > 10
|
166
|
+
c.finish
|
167
|
+
end
|
168
|
+
end
|
169
|
+
assert i > 0
|
170
|
+
end
|
171
|
+
|
172
|
+
def test_ustack
|
173
|
+
progtext = "profile-1 { trace(execname); ustack(); }"
|
174
|
+
prog = @dtp.compile progtext
|
175
|
+
prog.execute
|
176
|
+
@dtp.go
|
177
|
+
sleep 2
|
178
|
+
|
179
|
+
c = DTrace::Consumer.new(@dtp)
|
180
|
+
i = 0
|
181
|
+
c.consume do |d|
|
182
|
+
assert d
|
183
|
+
assert_not_nil d.cpu
|
184
|
+
assert_equal "profile:::profile-1", d.probe.to_s
|
185
|
+
|
186
|
+
assert_equal 2, d.data.length
|
187
|
+
assert_equal DTrace::Record, d.data[0].class
|
188
|
+
assert_equal DTrace::StackRecord, d.data[1].class
|
189
|
+
|
190
|
+
i = i + 1
|
191
|
+
if i > 10
|
192
|
+
c.finish
|
193
|
+
end
|
194
|
+
end
|
195
|
+
assert i > 0
|
196
|
+
end
|
197
|
+
|
198
|
+
end
|