chrisa-ruby-dtrace 0.2.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.
Files changed (88) hide show
  1. data/History.txt +34 -0
  2. data/Manifest.txt +58 -0
  3. data/README.txt +88 -0
  4. data/Rakefile +73 -0
  5. data/examples/scsi.rb +442 -0
  6. data/ext/dof/constants.c +49 -0
  7. data/ext/dof/dof.h +55 -0
  8. data/ext/dof/dof_api.c +57 -0
  9. data/ext/dof/dof_helper.c +82 -0
  10. data/ext/dof/extconf.rb +4 -0
  11. data/ext/dof/file.c +56 -0
  12. data/ext/dof/generator.c +9 -0
  13. data/ext/dof/header.c +80 -0
  14. data/ext/dof/parser.c +415 -0
  15. data/ext/dof/parser.h +10 -0
  16. data/ext/dof/section.c +302 -0
  17. data/ext/dtrace_aggdata.c +142 -0
  18. data/ext/dtrace_api.c +119 -0
  19. data/ext/dtrace_api.h +150 -0
  20. data/ext/dtrace_bufdata.c +139 -0
  21. data/ext/dtrace_dropdata.c +131 -0
  22. data/ext/dtrace_errdata.c +110 -0
  23. data/ext/dtrace_hdl.c +577 -0
  24. data/ext/dtrace_probedata.c +267 -0
  25. data/ext/dtrace_probedesc.c +78 -0
  26. data/ext/dtrace_process.c +37 -0
  27. data/ext/dtrace_program.c +62 -0
  28. data/ext/dtrace_programinfo.c +60 -0
  29. data/ext/dtrace_recdesc.c +46 -0
  30. data/ext/dtrace_util.c +92 -0
  31. data/ext/extconf.rb +28 -0
  32. data/ext/stubs.txt +78 -0
  33. data/lib/dtrace/aggregate.rb +40 -0
  34. data/lib/dtrace/aggregateset.rb +19 -0
  35. data/lib/dtrace/consumer.rb +174 -0
  36. data/lib/dtrace/data.rb +82 -0
  37. data/lib/dtrace/dof/file.rb +63 -0
  38. data/lib/dtrace/dof/section/strtab.rb +21 -0
  39. data/lib/dtrace/dof/section.rb +69 -0
  40. data/lib/dtrace/dof.rb +8 -0
  41. data/lib/dtrace/printfrecord.rb +10 -0
  42. data/lib/dtrace/probe.rb +46 -0
  43. data/lib/dtrace/probedata.rb +23 -0
  44. data/lib/dtrace/probedesc.rb +15 -0
  45. data/lib/dtrace/provider/probedef.rb +24 -0
  46. data/lib/dtrace/provider.rb +231 -0
  47. data/lib/dtrace/record.rb +11 -0
  48. data/lib/dtrace/stackrecord.rb +31 -0
  49. data/lib/dtrace/tracer.rb +35 -0
  50. data/lib/dtrace.rb +74 -0
  51. data/lib/dtraceconsumer.rb +9 -0
  52. data/plugin/dtrace/README +81 -0
  53. data/plugin/dtrace/Rakefile +22 -0
  54. data/plugin/dtrace/bin/dtracer.rb +29 -0
  55. data/plugin/dtrace/init.rb +7 -0
  56. data/plugin/dtrace/lib/dtrace_helper.rb +2 -0
  57. data/plugin/dtrace/lib/dtrace_report.rb +67 -0
  58. data/plugin/dtrace/lib/dtracer.rb +52 -0
  59. data/plugin/dtrace/lib/dtracer_client.rb +26 -0
  60. data/plugin/dtrace/public/stylesheets/dtrace.css +48 -0
  61. data/plugin/dtrace/scripts/default.d +11 -0
  62. data/plugin/dtrace/scripts/rails_mysql.d +29 -0
  63. data/plugin/dtrace/tasks/dtrace.rake +52 -0
  64. data/plugin/dtrace/test/dtrace_test.rb +8 -0
  65. data/plugin/dtrace/views/dtrace/_report.rhtml +26 -0
  66. data/test/apple-dof +0 -0
  67. data/test/disabled_probe_effect.txt +19 -0
  68. data/test/dof +0 -0
  69. data/test/dof2 +0 -0
  70. data/test/test_disabled_probe_effect.rb +60 -0
  71. data/test/test_dof_generator.rb +142 -0
  72. data/test/test_dof_helper.rb +106 -0
  73. data/test/test_dof_parser.rb +25 -0
  74. data/test/test_dof_providers.rb +282 -0
  75. data/test/test_dof_strtabs.rb +92 -0
  76. data/test/test_dtrace.rb +111 -0
  77. data/test/test_dtrace_aggregates.rb +56 -0
  78. data/test/test_dtrace_drops_errors.rb +183 -0
  79. data/test/test_dtrace_probe.rb +383 -0
  80. data/test/test_dtrace_probes.rb +400 -0
  81. data/test/test_dtrace_processes.rb +83 -0
  82. data/test/test_dtrace_profile.rb +232 -0
  83. data/test/test_dtrace_provider.rb +153 -0
  84. data/test/test_dtrace_repeat.rb +51 -0
  85. data/test/test_dtrace_rubyprobe.rb +52 -0
  86. data/test/test_dtrace_typefilter.rb +108 -0
  87. data/test/test_legacy_consumer.rb +56 -0
  88. metadata +165 -0
@@ -0,0 +1,48 @@
1
+ body {
2
+ margin-bottom:25px;
3
+ }
4
+
5
+ #dtrace {
6
+ width:100%;
7
+ }
8
+
9
+ #dtrace td, #dtrace th, #dtrace div, #dtrace p {
10
+ text-align:left;
11
+ }
12
+
13
+ #dtrace a,
14
+ #dtrace a:visited {
15
+ color:#005;
16
+ text-decoration:none;
17
+ }
18
+
19
+ #dtrace a:hover,
20
+ #dtrace a:active {
21
+ text-decoration:underline;
22
+ }
23
+
24
+ #dtrace .dtrace-tab {
25
+ background-color:#fff;
26
+ padding:1em;
27
+ margin:0;
28
+ }
29
+
30
+ #dtrace-tabs {
31
+ width:100%;
32
+ height:25px;
33
+ margin:0; padding:0;
34
+ list-style-type:none;
35
+ background:#000;
36
+ }
37
+
38
+ #dtrace-tabs li {
39
+ float:left;
40
+ }
41
+
42
+ #dtrace-tabs li a,
43
+ #dtrace-tabs li a:visited {
44
+ display:block;
45
+ line-height:25px;
46
+ margin:0 1em;
47
+ color:#fff;
48
+ }
@@ -0,0 +1,11 @@
1
+ syscall:::entry
2
+ /pid == $1/
3
+ {
4
+ @syscalls[probefunc] = count();
5
+ }
6
+
7
+ END
8
+ {
9
+ printf("System Calls");
10
+ printa(@syscalls);
11
+ }
@@ -0,0 +1,29 @@
1
+ pid$1::mysql_real_query:entry
2
+ {
3
+ @queries[copyinstr(arg1)] = count();
4
+ }
5
+
6
+ ruby$1:::function-entry
7
+ {
8
+ @rbclasses[this->class = copyinstr(arg0)] = count();
9
+ this->sep = strjoin(this->class, "#");
10
+ @rbmethods[strjoin(this->sep, copyinstr(arg1))] = count();
11
+ }
12
+
13
+ syscall:::entry
14
+ /pid == $1/
15
+ {
16
+ @syscalls[probefunc] = count();
17
+ }
18
+
19
+ END
20
+ {
21
+ printf("MySQL Queries");
22
+ printa(@queries);
23
+ printf("System Calls");
24
+ printa(@syscalls);
25
+ printf("Ruby Classes");
26
+ printa(@rbclasses);
27
+ printf("Ruby Methods");
28
+ printa(@rbmethods);
29
+ }
@@ -0,0 +1,52 @@
1
+ namespace :dtrace do
2
+
3
+ desc 'Set up dtrace in your rails application'
4
+ task :setup do
5
+ ['dtracer'].each do |script|
6
+ script_dest = "#{RAILS_ROOT}/script/#{script}"
7
+ script_src = File.dirname(__FILE__) + "/../bin/#{script}.rb"
8
+
9
+ FileUtils.chmod 0774, script_src
10
+
11
+ unless File.exists?(script_dest)
12
+ puts "Copying acts_as_encrypted script #{script}.rb to #{script_dest}"
13
+ FileUtils.cp_r(script_src, script_dest)
14
+ end
15
+ end
16
+
17
+ ['stylesheets/dtrace.css'].each do |asset|
18
+ asset_dest = "#{RAILS_ROOT}/public/#{asset}"
19
+ asset_src = File.dirname(__FILE__) + "/../public/#{asset}"
20
+
21
+ FileUtils.chmod 0774, asset_src
22
+
23
+ unless File.exists?(asset_dest)
24
+ puts "Copying acts_as_encrypted asset #{asset} to #{asset_dest}"
25
+ FileUtils.cp_r(asset_src, asset_dest)
26
+ end
27
+ end
28
+ end
29
+
30
+ desc 'Remove dtrace from your rails application'
31
+ task :remove do
32
+ ['dtracer'].each do |script|
33
+ script_dest = "#{RAILS_ROOT}/script/#{script}"
34
+
35
+ if File.exists?(script_dest)
36
+ puts "Removing #{script_dest} ..."
37
+ FileUtils.rm(script_dest, :force => true)
38
+ end
39
+ end
40
+
41
+ ['stylesheets/dtrace.css'].each do |asset|
42
+ asset_dest = "#{RAILS_ROOT}/public/#{asset}"
43
+
44
+ if File.exists?(asset_dest)
45
+ puts "Removing #{asset_dest} ..."
46
+ FileUtils.rm(asset_dest, :force => true)
47
+ end
48
+ end
49
+ end
50
+
51
+ end
52
+
@@ -0,0 +1,8 @@
1
+ require 'test/unit'
2
+
3
+ class DtraceTest < Test::Unit::TestCase
4
+ # Replace this with your real tests.
5
+ def test_this_plugin
6
+ flunk
7
+ end
8
+ end
@@ -0,0 +1,26 @@
1
+ <style type="text/css">
2
+ div#dtrace-report { background-color: #ddd; padding: 1em; margin: 1em; }
3
+ table.dtrace-report { background-color: #eee }
4
+ </style>
5
+
6
+ <% if controller.dtrace_report.length > 0 %>
7
+ <div id="dtrace-report">
8
+ <h2>DTrace Report: <%=h controller.dtrace_script %></h2>
9
+ <% controller.dtrace_report.each do |r| %>
10
+ <table class="dtrace-report">
11
+ <% if r.respond_to? :data %>
12
+ <% r.data.sort {|a,b| b.value <=> a.value }.each do |agg| %>
13
+ <tr>
14
+ <td><%=h agg.tuple %></td>
15
+ <td><%=h agg.value %></td>
16
+ </tr>
17
+ <% end %>
18
+ <% else %>
19
+ <% if r.value != 0 %>
20
+ <h3><%=h r.value %></h3>
21
+ <% end %>
22
+ <% end %>
23
+ </table>
24
+ <% end %>
25
+ </div>
26
+ <% end %>
data/test/apple-dof ADDED
Binary file
@@ -0,0 +1,19 @@
1
+ solaris-devx:~/ruby-dtrace-dof/ruby-dtrace chris$ ruby -Iext:lib test/test_disabled_probe_effect.rb
2
+ Loaded suite test/test_disabled_probe_effect
3
+ Started
4
+ user system total real
5
+ noprobes: 0.020000 0.020000 0.040000 ( 0.042108)
6
+ disabled: 0.120000 0.110000 0.230000 ( 0.231237)
7
+ enabled: 2.670000 0.260000 2.930000 ( 2.940411)
8
+ .
9
+ Finished in 3.220336 seconds.
10
+
11
+ 1 tests, 1 assertions, 0 failures, 0 errors
12
+
13
+ merge Dtrace::Probe and Dtrace::Stub:
14
+
15
+ Started
16
+ user system total real
17
+ noprobes: 0.000000 0.010000 0.010000 ( 0.020863)
18
+ disabled: 0.090000 0.090000 0.180000 ( 0.170912)
19
+ enabled: 2.690000 0.330000 3.020000 ( 3.027719)
data/test/dof ADDED
Binary file
data/test/dof2 ADDED
Binary file
@@ -0,0 +1,60 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2008 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace'
7
+ require 'dtrace/provider'
8
+ require 'test/unit'
9
+ require 'benchmark'
10
+
11
+ class TestDisabledProbeEffect < Test::Unit::TestCase
12
+
13
+ def test_probe_no_args
14
+
15
+ n = 20000
16
+ Benchmark.bm do |x|
17
+
18
+ x.report "noprobes:" do
19
+ # First time a loop with no probes created
20
+ (1..n).each do |i|
21
+ # no op
22
+ end
23
+ end
24
+
25
+ x.report "disabled:" do
26
+ # Second time a loop with probes created but not enabled.
27
+ Dtrace::Provider.create :dpe do |p|
28
+ p.probe :p1
29
+ end
30
+
31
+ (1..n).each do |i|
32
+ Dtrace::Probe::Dpe.p1 { |p| p.fire }
33
+ end
34
+ end
35
+
36
+ x.report "enabled: " do
37
+ # Third time a loop with probes enabled
38
+ t = Dtrace.new
39
+ t.setopt("bufsize", "4m")
40
+
41
+ progtext = <<EOD
42
+ dpe*:ruby:test_probe_no_args:p1
43
+ {
44
+ }
45
+ EOD
46
+
47
+ prog = t.compile progtext
48
+ prog.execute
49
+ t.go
50
+
51
+ (1..n).each do |i|
52
+ Dtrace::Probe::Dpe.p1 { |p| p.fire }
53
+ end
54
+ end
55
+ end
56
+
57
+ assert 1
58
+
59
+ end
60
+ end
@@ -0,0 +1,142 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2008 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace'
7
+ require 'dtrace/dof'
8
+ require 'test/unit'
9
+ require 'pp'
10
+
11
+ $dof_dir = File.dirname(__FILE__)
12
+
13
+ # Tests for the Dtrace DOF generator
14
+
15
+ class TestDofGenerator < Test::Unit::TestCase
16
+ include Dtrace::Dof::Constants
17
+
18
+ def test_generate_section_comments
19
+ s = Dtrace::Dof::Section.new(DOF_SECT_COMMENTS, 1)
20
+ s.data = "Ruby-Dtrace D 0.12"
21
+ dof = s.generate
22
+ assert dof
23
+ end
24
+
25
+ def test_generate_section_utsname
26
+ s = Dtrace::Dof::Section.new(DOF_SECT_UTSNAME, 2)
27
+ dof = s.generate
28
+ assert dof
29
+ end
30
+
31
+ def test_generate_section_probes
32
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROBES, 3)
33
+ s.data = [
34
+ {:enoffidx=>14,
35
+ :argidx=>16,
36
+ :nenoffs=>1,
37
+ :offidx=>14,
38
+ :name=>1,
39
+ :addr=>0x8082a78,
40
+ :nargc=>1,
41
+ :func=>5,
42
+ :xargc=>1,
43
+ :nargv=>3,
44
+ :noffs=>1,
45
+ :xargv=>3},
46
+ {:enoffidx=>15,
47
+ :argidx=>17,
48
+ :nenoffs=>1,
49
+ :offidx=>15,
50
+ :name=>4,
51
+ :addr=>0x807429c,
52
+ :nargc=>3,
53
+ :func=>9,
54
+ :xargc=>3,
55
+ :nargv=>6,
56
+ :noffs=>1,
57
+ :xargv=>7},
58
+ ]
59
+
60
+ dof = s.generate
61
+ assert dof
62
+ end
63
+
64
+ def test_generate_section_strtab
65
+ s = Dtrace::Dof::Section.new(DOF_SECT_STRTAB, 1)
66
+ s.data = ['foo', 'bar', 'baz']
67
+ dof = s.generate
68
+ assert dof
69
+ end
70
+
71
+ def test_generate_section_prargs
72
+ s = Dtrace::Dof::Section.new(DOF_SECT_PRARGS, 1)
73
+ s.data = [ 1, 2 ]
74
+ dof = s.generate
75
+ assert dof
76
+ end
77
+
78
+ def test_generate_section_proffs
79
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROFFS, 1)
80
+ s.data = [ 3, 4 ]
81
+ dof = s.generate
82
+ assert dof
83
+ end
84
+
85
+ def test_generate_section_prenoffs
86
+ s = Dtrace::Dof::Section.new(DOF_SECT_PRENOFFS, 1)
87
+ s.data = [ 5, 6 ]
88
+ dof = s.generate
89
+ assert dof
90
+ end
91
+
92
+ def test_generate_section_provider
93
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROVIDER, 1)
94
+ data = {
95
+ :strtab => 1,
96
+ :probes => 2,
97
+ :prargs => 3,
98
+ :proffs => 4,
99
+ :prenoffs => 5,
100
+ :name => 1,
101
+ :provattr => { :name => 1, :data => 1, :class => 1 },
102
+ :modattr => { :name => 1, :data => 1, :class => 1 },
103
+ :funcattr => { :name => 1, :data => 1, :class => 1 },
104
+ :nameattr => { :name => 1, :data => 1, :class => 1 },
105
+ :argsattr => { :name => 1, :data => 1, :class => 1 }
106
+ }
107
+ s.data = data
108
+ dof = s.generate
109
+ assert dof
110
+ end
111
+
112
+ def test_dof_generate_section_reltab
113
+ s = Dtrace::Dof::Section.new(DOF_SECT_RELTAB, 5)
114
+ data = [
115
+ { :name => 20, # main
116
+ :type => 1, # setx?
117
+ :offset => 0,
118
+ :data => 0,
119
+ }
120
+ ]
121
+ s.data = data
122
+ dof = s.generate
123
+ assert dof
124
+ end
125
+
126
+ def test_dof_generate_section_urelhdr
127
+ s = Dtrace::Dof::Section.new(DOF_SECT_URELHDR, 6)
128
+ data = {
129
+ :strtab => 0,
130
+ :relsec => 5,
131
+ :tgtsec => 1,
132
+ }
133
+ s.data = data
134
+ dof = s.generate
135
+ assert dof
136
+ end
137
+
138
+ def test_const
139
+ assert Dtrace::Dof::Constants::DOF_SECT_UTSNAME
140
+ assert DOF_SECT_UTSNAME
141
+ end
142
+ end
@@ -0,0 +1,106 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2008 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace'
7
+ require 'dtrace/dof'
8
+ require 'test/unit'
9
+
10
+ $dof_dir = File.dirname(__FILE__)
11
+
12
+ class TestDofHelper < Test::Unit::TestCase
13
+ include Dtrace::Dof::Constants
14
+
15
+ def test_sun_dof
16
+ dof = File.read("#{$dof_dir}/dof")
17
+ f = Dtrace::Dof::File.new
18
+ f << dof
19
+ Dtrace::Dof.loaddof(f, 'testmodule')
20
+
21
+ t = Dtrace.new
22
+ matches = 0
23
+ t.each_probe do |p|
24
+ if p.to_s == "test#{$$}:testmodule:main:test"
25
+ matches += 1
26
+ end
27
+ end
28
+ assert_equal 1, matches
29
+ end
30
+
31
+ def test_file
32
+ f = Dtrace::Dof::File.new
33
+
34
+ s = Dtrace::Dof::Section.new(DOF_SECT_STRTAB, 0)
35
+ s.data = ['test', 'char *', 'char *', 'main', 'test']
36
+ f.sections << s
37
+
38
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROBES, 1)
39
+ s.data = [
40
+ {:nargv=>6,
41
+ :noffs=>1,
42
+ :xargv=>13,
43
+ :enoffidx=>0,
44
+ :argidx=>0,
45
+ :name=>1,
46
+ :nenoffs=>0,
47
+ :offidx=>0,
48
+ :addr=>0,
49
+ :nargc=>1,
50
+ :func=>20,
51
+ :xargc=>1}
52
+ ]
53
+ f.sections << s
54
+
55
+ s = Dtrace::Dof::Section.new(DOF_SECT_PRARGS, 2)
56
+ s.data = [ 0 ]
57
+ f.sections << s
58
+
59
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROFFS, 3)
60
+ s.data = [ 36 ]
61
+ f.sections << s
62
+
63
+ s = Dtrace::Dof::Section.new(DOF_SECT_PRENOFFS, 4)
64
+ s.data = [ 0 ]
65
+ f.sections << s
66
+
67
+ s = Dtrace::Dof::Section.new(DOF_SECT_PROVIDER, 5)
68
+ s.data = {
69
+ :strtab => 0,
70
+ :probes => 1,
71
+ :prargs => 2,
72
+ :proffs => 3,
73
+ :prenoffs => 4,
74
+ :name => 25,
75
+ :provattr => { :name => 5, :data => 5, :class => 5 },
76
+ :modattr => { :name => 1, :data => 1, :class => 5 },
77
+ :funcattr => { :name => 1, :data => 1, :class => 5 },
78
+ :nameattr => { :name => 5, :data => 5, :class => 5 },
79
+ :argsattr => { :name => 5, :data => 5, :class => 5 }
80
+ }
81
+ f.sections << s
82
+
83
+ s = Dtrace::Dof::Section.new(DOF_SECT_COMMENTS, 7)
84
+ s.flags = 0 # no load
85
+ s.data = "Ruby-Dtrace 0.12"
86
+ f.sections << s
87
+
88
+ s = Dtrace::Dof::Section.new(DOF_SECT_UTSNAME, 8)
89
+ s.flags = 0 # no load
90
+ f.sections << s
91
+
92
+ f.generate
93
+ Dtrace::Dof.loaddof(f, 'testmodule')
94
+
95
+ t = Dtrace.new
96
+ matches = 0
97
+ t.each_probe do |p|
98
+ if p.to_s == "test#{$$}:testmodule:main:test"
99
+ matches += 1
100
+ end
101
+ end
102
+ assert_equal 1, matches
103
+
104
+ end
105
+
106
+ end
@@ -0,0 +1,25 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2008 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ require 'dtrace/dof'
7
+ require 'test/unit'
8
+
9
+ $dof_dir = File.dirname(__FILE__)
10
+
11
+ # Tests for the Dtrace DOF parser
12
+
13
+ class TestDofParser < Test::Unit::TestCase
14
+
15
+ def test_parse
16
+ assert File.exists?("#{$dof_dir}/dof")
17
+ dof = Dtrace::Dof::Parser.parse(IO.read("#{$dof_dir}/dof"))
18
+ end
19
+
20
+ def test_parse_apple_dof
21
+ assert File.exists?("#{$dof_dir}/apple-dof")
22
+ dof = Dtrace::Dof::Parser.parse(IO.read("#{$dof_dir}/apple-dof"))
23
+ end
24
+
25
+ end