ruby-dtrace 0.0.6 → 0.2.8

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 (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