ruby-dtrace 0.0.6 → 0.2.8

Sign up to get free protection for your applications and to get access to all the features.
Files changed (81) hide show
  1. data/History.txt +21 -0
  2. data/Manifest.txt +86 -19
  3. data/README.txt +48 -6
  4. data/Rakefile +61 -20
  5. data/examples/scsi.rb +1 -1
  6. data/ext/dof/Makefile +154 -0
  7. data/ext/dof/constants.c +57 -0
  8. data/ext/dof/dof.h +56 -0
  9. data/ext/dof/dof_api.c +58 -0
  10. data/ext/dof/dof_helper.c +82 -0
  11. data/ext/dof/extconf.rb +4 -0
  12. data/ext/dof/file.c +90 -0
  13. data/ext/dof/generator.c +9 -0
  14. data/ext/dof/header.c +79 -0
  15. data/ext/dof/mkmf.log +10 -0
  16. data/ext/dof/parser.c +415 -0
  17. data/ext/dof/parser.h +10 -0
  18. data/ext/dof/section.c +312 -0
  19. data/ext/dtrace_aggdata.c +2 -2
  20. data/ext/dtrace_api.c +46 -34
  21. data/ext/dtrace_api.h +31 -7
  22. data/ext/dtrace_bufdata.c +3 -3
  23. data/ext/dtrace_hdl.c +66 -3
  24. data/ext/dtrace_probedata.c +4 -4
  25. data/ext/{dtrace_probe.c → dtrace_probedesc.c} +7 -7
  26. data/ext/extconf.rb +25 -0
  27. data/ext/i386-darwin/dtrace_probe.c +278 -0
  28. data/ext/i386-solaris/dtrace_probe.c +225 -0
  29. data/ext/stubs.txt +78 -0
  30. data/lib/dtrace.rb +34 -13
  31. data/lib/dtrace/aggregate.rb +40 -0
  32. data/lib/dtrace/aggregateset.rb +19 -0
  33. data/lib/dtrace/consumer.rb +174 -0
  34. data/lib/dtrace/data.rb +82 -0
  35. data/lib/dtrace/dof.rb +8 -0
  36. data/lib/dtrace/dof/file.rb +64 -0
  37. data/lib/dtrace/dof/section.rb +75 -0
  38. data/lib/dtrace/dof/section/strtab.rb +28 -0
  39. data/lib/{dtraceprintfrecord.rb → dtrace/printfrecord.rb} +4 -2
  40. data/lib/dtrace/probe.rb +3 -6
  41. data/lib/dtrace/probedata.rb +23 -0
  42. data/lib/dtrace/probedesc.rb +15 -0
  43. data/lib/dtrace/provider.rb +190 -169
  44. data/lib/dtrace/provider/klass.rb +33 -0
  45. data/lib/dtrace/provider/probedef.rb +24 -0
  46. data/lib/{dtracerecord.rb → dtrace/record.rb} +4 -2
  47. data/lib/{dtracestackrecord.rb → dtrace/stackrecord.rb} +10 -8
  48. data/lib/dtrace/version.rb +9 -0
  49. data/lib/dtraceconsumer.rb +3 -167
  50. data/plugin/dtrace/lib/dtracer.rb +4 -4
  51. data/test/apple-dof +0 -0
  52. data/test/disabled_probe_effect.txt +19 -0
  53. data/test/dof +0 -0
  54. data/test/dof2 +0 -0
  55. data/test/test_disabled_probe_effect.rb +56 -0
  56. data/test/test_dof_generator.rb +142 -0
  57. data/test/test_dof_helper.rb +106 -0
  58. data/test/test_dof_parser.rb +27 -0
  59. data/test/test_dof_providers.rb +278 -0
  60. data/test/test_dof_strtabs.rb +98 -0
  61. data/test/test_dtrace.rb +67 -1
  62. data/test/test_dtrace_aggregates.rb +5 -5
  63. data/test/test_dtrace_drops_errors.rb +5 -5
  64. data/test/test_dtrace_probe.rb +385 -0
  65. data/test/test_dtrace_probes.rb +414 -0
  66. data/test/test_dtrace_processes.rb +2 -2
  67. data/test/test_dtrace_profile.rb +12 -12
  68. data/test/test_dtrace_provider.rb +138 -0
  69. data/test/test_dtrace_repeat.rb +1 -1
  70. data/test/test_dtrace_rubyprobe.rb +3 -1
  71. data/test/test_dtrace_typefilter.rb +9 -9
  72. data/test/test_legacy_consumer.rb +56 -0
  73. metadata +112 -71
  74. data/lib/dtrace/provider/osx.rb +0 -25
  75. data/lib/dtrace/provider/solaris.rb +0 -29
  76. data/lib/dtraceaggregate.rb +0 -37
  77. data/lib/dtraceaggregateset.rb +0 -17
  78. data/lib/dtracedata.rb +0 -80
  79. data/lib/dtraceprobe.rb +0 -13
  80. data/lib/dtraceprobedata.rb +0 -21
  81. data/test/test_dynusdt.rb +0 -135
@@ -0,0 +1,33 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2009 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ class Dtrace
7
+ class Provider
8
+
9
+ # A dynamically-created DTrace provider class.
10
+ #
11
+ class Klass
12
+
13
+ def initialize(dof, probes)
14
+ # must stash a reference to the DOF in the provider:
15
+ # on OSX at least, freeing the generated DOF removes
16
+ # the probes from the kernel.
17
+ @dof = dof
18
+ @probes = probes
19
+ end
20
+
21
+ def method_missing(probe, *args, &block)
22
+ if @probes[probe].nil?
23
+ raise Dtrace::Exception.new("no such probe in #{self.to_s}: #{probe.to_s}")
24
+ else
25
+ if @probes[probe].is_enabled?
26
+ block.call @probes[probe]
27
+ end
28
+ end
29
+ end
30
+
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,24 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2008 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ class Dtrace
7
+ class Provider
8
+ class ProbeDef
9
+ attr_reader :name, :function
10
+ attr_accessor :args
11
+
12
+ def initialize(name, function)
13
+ @name = name.to_sym
14
+ @function = function.to_s
15
+ @args = []
16
+ end
17
+
18
+ def argc
19
+ @args.length
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -4,6 +4,8 @@
4
4
  #
5
5
  # A scalar DTrace record. Its value is as set by the DTrace action
6
6
  # which triggered it.
7
- class DtraceRecord
8
- attr_accessor :value
7
+ class Dtrace
8
+ class Record
9
+ attr_accessor :value
10
+ end
9
11
  end
@@ -16,14 +16,16 @@
16
16
  # "libruby.1.dylib`rb_apply+0x392",
17
17
  # "libruby.1.dylib`rb_eval_string_wrap+0xe82"]>
18
18
  #
19
- class DtraceStackRecord
20
- attr_reader :value
19
+ class Dtrace
20
+ class StackRecord
21
+ attr_reader :value
21
22
 
22
- # Given a stack as a string returned from DTrace, set the value of
23
- # this record to a list of stack frames.
24
- def parse(raw)
25
- frames = raw.split(/\n/)
26
- @value = frames.map {|f| f.lstrip }.select {|f| f.length > 0 }
27
- end
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
28
29
 
30
+ end
29
31
  end
@@ -0,0 +1,9 @@
1
+ #
2
+ # Ruby-Dtrace
3
+ # (c) 2007 Chris Andrews <chris@nodnol.org>
4
+ #
5
+
6
+ class Dtrace
7
+ VERSION = '0.2.8'
8
+ end
9
+
@@ -3,171 +3,7 @@
3
3
  # (c) 2007 Chris Andrews <chris@nodnol.org>
4
4
  #
5
5
 
6
- # A DtraceConsumer provides access to the data produced by the running
7
- # D program. Having compiled and executed a D program, you typically
8
- # create a DtraceConsumer, and wait for data.
9
- #
10
- # You can either wait indefinitely for data, or consume all the data
11
- # waiting and then stop: if your D program consists of only of
12
- # aggregations, returned by printa() actions in the END block, this
13
- # will be the best approach. If you have a mix of trace() and printf()
14
- # actions elsewhere, you'll probably want to wait until interrupted,
15
- # the D program itself exits, or your program decides it has collected
16
- # enough data.
17
- #
18
- # The two approaches are implemented by the +consume+ and
19
- # +consume_once+ methods.
20
- #
21
- # The +consume+ and +consume_once+ methods accept a block to which is
22
- # yielded complete DtraceData objects, one for each probe which fires.
23
- #
24
- # You must have already started tracing when you call +consume+ or
25
- # +consume_once+, so the general structure will look like:
26
- #
27
- # t = Dtrace.new
28
- # progtext = "..."
29
- # prog = t.compile progtext
30
- # prog.execute
31
- # t.go
32
- # c = DtraceConsumer.new(t)
33
- # c.consume_once do |d|
34
- # # handle DtraceData objects
35
- # # ...
36
- # # get bored:
37
- # c.finish
38
- # end
39
-
40
- class DtraceConsumer
41
-
42
- def initialize(t)
43
- @t = t
44
- @done = false
45
- @types = []
46
-
47
- @drophandler = nil
48
- @errhandler = nil
49
- end
50
-
51
- private
52
-
53
- # The consumer callbacks:
54
- #
55
- # DtraceRecDesc -> rec_consumer
56
- # DtraceProbeData -> probe_consumer
57
- # DtraceBufData -> buf_consumer
58
- #
59
- # We expect a sequence of calls to these procs, and we accumulate
60
- # data in the @curr DtraceData based on this:
61
- #
62
- # DtraceProbeData (initial callback for a probe firing)
63
- # DtraceRecDesc
64
- # ...
65
- # DtraceRecDesc = nil (end of data)
66
- #
67
-
68
- def rec_consumer(block)
69
- proc do |rec|
70
- if rec
71
- @curr.add_recdata(rec)
72
- else
73
- @curr.finish
74
- block.call(@curr)
75
- @curr = DtraceData.new(@types)
76
- end
77
- end
78
- end
79
-
80
- def probe_consumer
81
- proc do |probe|
82
- @curr.add_probedata(probe)
83
- end
84
- end
85
-
86
- def buf_consumer
87
- proc do |buf|
88
- @curr.add_bufdata(buf)
89
- end
90
- end
91
-
92
- def filter_types(types)
93
- @types = types
94
- @curr = DtraceData.new(types)
95
- end
96
-
97
- public
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
-
121
- # Signals that the client wishes to stop consuming trace data.
122
- def finish
123
- @t.stop
124
- @done = true
125
- end
126
-
127
- # Waits for data from the D program, and yields the records returned
128
- # to the block given. Returns when the D program exits.
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)
140
- @t.buf_consumer(buf_consumer)
141
- begin
142
- while(true) do
143
- @t.sleep
144
- work = @t.work(probe_consumer, rec_consumer(block))
145
- if (@done || work > 0)
146
- break
147
- end
148
- end
149
- ensure
150
- @t.stop
151
- @t.work(probe_consumer)
152
- end
153
- end
154
-
155
- # Yields the data waiting from the current program, then returns.
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)
167
- @t.buf_consumer(buf_consumer)
168
- @t.stop
169
- @t.work(probe_consumer, rec_consumer(block))
170
- end
171
-
172
- end
6
+ require 'dtrace/consumer'
173
7
 
8
+ # Interface preservation - see Dtrace::Consumer.
9
+ class DtraceConsumer < Dtrace::Consumer; end
@@ -15,7 +15,7 @@ class Dtracer
15
15
  @d = Dtrace.new
16
16
  @d.setopt("aggsize", "4m")
17
17
  @d.setopt("bufsize", "4m")
18
- rescue DtraceException => e
18
+ rescue Dtrace::Exception => e
19
19
  @logger.warn("DTrace start setup: #{e.message}")
20
20
  return
21
21
  end
@@ -24,7 +24,7 @@ class Dtracer
24
24
  prog = @d.compile(@dprogram, pid.to_s)
25
25
  prog.execute
26
26
  @d.go
27
- rescue DtraceException => e
27
+ rescue Dtrace::Exception => e
28
28
  @logger.warn("DTrace start compile: #{e.message}")
29
29
  end
30
30
  end
@@ -35,11 +35,11 @@ class Dtracer
35
35
 
36
36
  dtrace_data = nil
37
37
  begin
38
- c = DtraceConsumer.new(@d)
38
+ c = Dtrace::Consumer.new(@d)
39
39
  c.consume_once do |d|
40
40
  dtrace_data = d
41
41
  end
42
- rescue DtraceException => e
42
+ rescue Dtrace::Exception => e
43
43
  @logger.warn("DTrace end: #{e.message}")
44
44
  end
45
45
 
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)
Binary file
Binary file
@@ -0,0 +1,56 @@
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
+ Dtrace::Provider.create :dpe do |p|
26
+ p.probe :p1
27
+ end
28
+
29
+ x.report "disabled:" do
30
+ # Second time a loop with probes created but not enabled.
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 = "dpe#{$$}:::p1 { }"
42
+
43
+ prog = t.compile progtext
44
+ prog.execute
45
+ t.go
46
+
47
+ (1..n).each do |i|
48
+ Dtrace::Probe::Dpe.p1 { |p| p.fire }
49
+ end
50
+ end
51
+ end
52
+
53
+ assert 1
54
+
55
+ end
56
+ 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