ruby-dtrace 0.0.5 → 0.0.6
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 +6 -1
- data/Manifest.txt +6 -0
- data/ext/dtrace_util.c +1 -0
- data/lib/dtrace.rb +1 -1
- data/lib/dtrace/probe.rb +49 -0
- data/lib/dtrace/provider.rb +236 -0
- data/lib/dtrace/provider/osx.rb +25 -0
- data/lib/dtrace/provider/solaris.rb +29 -0
- data/lib/dtrace/tracer.rb +35 -0
- data/plugin/dtrace/lib/dtrace_report.rb +15 -10
- data/test/test_dynusdt.rb +135 -0
- metadata +9 -2
data/History.txt
CHANGED
@@ -1,4 +1,9 @@
|
|
1
|
-
== 0.0.
|
1
|
+
== 0.0.6 / 2008-02-17
|
2
|
+
|
3
|
+
* Add Dtrace::Provider, which allows creation of USDT providers from
|
4
|
+
Ruby, without the need to patch the interpreter.
|
5
|
+
|
6
|
+
== 0.0.5 / 2008-01-24
|
2
7
|
|
3
8
|
* Add DtraceErrData and DtraceDropData for access to error
|
4
9
|
and drop information
|
data/Manifest.txt
CHANGED
@@ -19,6 +19,11 @@ ext/dtrace_recdesc.c
|
|
19
19
|
ext/dtrace_util.c
|
20
20
|
ext/extconf.rb
|
21
21
|
lib/dtrace.rb
|
22
|
+
lib/dtrace/probe.rb
|
23
|
+
lib/dtrace/provider.rb
|
24
|
+
lib/dtrace/provider/osx.rb
|
25
|
+
lib/dtrace/provider/solaris.rb
|
26
|
+
lib/dtrace/tracer.rb
|
22
27
|
lib/dtraceaggregate.rb
|
23
28
|
lib/dtraceaggregateset.rb
|
24
29
|
lib/dtraceconsumer.rb
|
@@ -50,3 +55,4 @@ test/test_dtrace_profile.rb
|
|
50
55
|
test/test_dtrace_repeat.rb
|
51
56
|
test/test_dtrace_rubyprobe.rb
|
52
57
|
test/test_dtrace_typefilter.rb
|
58
|
+
test/test_dynusdt.rb
|
data/ext/dtrace_util.c
CHANGED
data/lib/dtrace.rb
CHANGED
data/lib/dtrace/probe.rb
ADDED
@@ -0,0 +1,49 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
class Dtrace
|
7
|
+
# DTrace::Probe - Using dynamically created USDT probes in Ruby
|
8
|
+
# programs:
|
9
|
+
#
|
10
|
+
# Having created the following probes with Dtrace::Provider:
|
11
|
+
#
|
12
|
+
# 74777 action_controller12297 action_controller.so process_finish process-finish
|
13
|
+
# 74778 action_controller12297 action_controller.so process_start process-start
|
14
|
+
#
|
15
|
+
# you can fire them with the following Ruby statements:
|
16
|
+
#
|
17
|
+
# Dtrace::Probe::ActionController.process_start do |p|
|
18
|
+
# p.fire(request.url)
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# Note that the generated class corresponding to the provider is
|
22
|
+
# simply the provider class, camelized.
|
23
|
+
#
|
24
|
+
# The generated method corresponding to the probe name (with -
|
25
|
+
# replaced by _) yields a probe object, on which you can call fire(),
|
26
|
+
# passing arguments of the appropriate types -- you are responsible
|
27
|
+
# for any type conversions necessary.
|
28
|
+
#
|
29
|
+
# fire() takes as many arguments as you defined for the probe: if
|
30
|
+
# you have generated a list of arguments to pass to fire(), use the
|
31
|
+
# splat operator to expand the list:
|
32
|
+
#
|
33
|
+
# Dtrace::Probe::MyProvider.my_probe do |p|
|
34
|
+
# args_list = [ some operation to get a list ]
|
35
|
+
# p.fire(*args_list)
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# This yield/fire() syntax exposes the is-enabled feature of the
|
39
|
+
# generated USDT probes: if the probe is not enabled, then the yield
|
40
|
+
# does not happen: this allows you to put relatively expensive work
|
41
|
+
# in the block, and know it is only called if the probe is enabled.
|
42
|
+
# This way, the probe-disabled overhead of these providers is
|
43
|
+
# reduced to a single method call, to a C-implemented method which
|
44
|
+
# simply wraps the DTrace IS_ENABLED() macro for the probe.
|
45
|
+
#
|
46
|
+
class Probe
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
@@ -0,0 +1,236 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace/probe'
|
7
|
+
require 'dtrace/provider/solaris'
|
8
|
+
require 'dtrace/provider/osx'
|
9
|
+
require 'pathname'
|
10
|
+
require 'tempfile'
|
11
|
+
|
12
|
+
DTRACE = '/usr/sbin/dtrace'
|
13
|
+
|
14
|
+
class Dtrace
|
15
|
+
|
16
|
+
# A DTrace provider. Allows creation of USDT probes on a running
|
17
|
+
# Ruby program, by dynamically creating an extension module
|
18
|
+
# implementing the probes, and compiling and loading it. You can use
|
19
|
+
# this with a Ruby interpreter compiled with the core DTrace probes,
|
20
|
+
# but you don't have to.
|
21
|
+
#
|
22
|
+
# This requires the DTrace and Ruby toolchains to be available:
|
23
|
+
# dtrace(1M), and the compiler and linker used to build Ruby. The
|
24
|
+
# process is similar to RubyInline, but the actual RubyInline
|
25
|
+
# library is not required (the build process for DTrace USDT probes
|
26
|
+
# is sufficiently differnent to a standard Ruby extension that it's
|
27
|
+
# not worth using it).
|
28
|
+
#
|
29
|
+
# Both Solaris and OSX 10.5 are supported. Other DTrace-supporting
|
30
|
+
# platforms can be added by creating a new class under
|
31
|
+
# Dtrace::Provider and implementing or overriding the required steps
|
32
|
+
# in the build process.
|
33
|
+
#
|
34
|
+
# Firing probes is explained in Dtrace::Probe.
|
35
|
+
#
|
36
|
+
# There are some limitations:
|
37
|
+
#
|
38
|
+
# You cannot choose all the components of the probe name: you can
|
39
|
+
# choose the provider and probe name, but the module and function
|
40
|
+
# components will be derived by DTrace, and won't be meaningful
|
41
|
+
# (they'll refer to the shim extension that gets created, not to
|
42
|
+
# anything in your Ruby program). It seems unlikely it's possible to
|
43
|
+
# change this.
|
44
|
+
#
|
45
|
+
# You cannot currently set D attributes: they're hardcoded to a
|
46
|
+
# default set. This will change.
|
47
|
+
#
|
48
|
+
# The extension will currently be rebuilt every time the provider is
|
49
|
+
# created, as there's not yet any support for packaging the provider
|
50
|
+
# in some way. This will change, to something along the lines of
|
51
|
+
# what RubyInline does to allow a pre-built extension to be used.
|
52
|
+
#
|
53
|
+
class Provider
|
54
|
+
|
55
|
+
class BuildError < StandardError; end
|
56
|
+
|
57
|
+
# Creates a DTrace provider. Causes a shim extension to be built
|
58
|
+
# and loaded, implementing the probes.
|
59
|
+
#
|
60
|
+
# Example:
|
61
|
+
#
|
62
|
+
# Dtrace::Provider.create :action_controller do |p|
|
63
|
+
# p.probe :process_start, :string
|
64
|
+
# p.probe :process_finish, :string, :integer
|
65
|
+
# end
|
66
|
+
#
|
67
|
+
# The symbol passed to create becomes the name of the provider,
|
68
|
+
# and the class exposed under Dtrace::Probe in Ruby (camelized, so
|
69
|
+
# the above statement creates Dtrace::Probe::ActionController).
|
70
|
+
#
|
71
|
+
# create yields a Provider for the current platform, on which you
|
72
|
+
# can call probe, to create the individual probes.
|
73
|
+
#
|
74
|
+
def self.create(name)
|
75
|
+
if RUBY_PLATFORM =~ /darwin/
|
76
|
+
provider = Dtrace::Provider::OSX.new(name)
|
77
|
+
else
|
78
|
+
provider = Dtrace::Provider::Solaris.new(name)
|
79
|
+
end
|
80
|
+
yield provider
|
81
|
+
provider.enable
|
82
|
+
end
|
83
|
+
|
84
|
+
# Creates a DTrace USDT probe. Arguments are the probe name, and
|
85
|
+
# then the argument types it will accept. The following argument
|
86
|
+
# types are supported:
|
87
|
+
#
|
88
|
+
# :string (char *)
|
89
|
+
# :integer (int)
|
90
|
+
#
|
91
|
+
# The probe will be named based on the provider name and the
|
92
|
+
# probe's name:
|
93
|
+
#
|
94
|
+
# provider_name:provider_name.so:probe_name:probe-name
|
95
|
+
#
|
96
|
+
# See the limitations explained elsewhere for an explanation of
|
97
|
+
# this redundancy in probe names.
|
98
|
+
#
|
99
|
+
def probe(name, *types)
|
100
|
+
typemap = { :string => 'char *', :integer => 'int' }
|
101
|
+
@probes[name] = types.map {|t| typemap[t]}
|
102
|
+
end
|
103
|
+
|
104
|
+
def initialize(name)
|
105
|
+
@name = name.to_s
|
106
|
+
@class = camelize(name)
|
107
|
+
@probes = {}
|
108
|
+
end
|
109
|
+
|
110
|
+
def enable
|
111
|
+
Tempfile.open("dtrace_probe_#{@name}") do |f|
|
112
|
+
p = Pathname.new(f.path)
|
113
|
+
@tempdir = "#{p.dirname}/#{@name}"
|
114
|
+
begin
|
115
|
+
Dir.mkdir @tempdir
|
116
|
+
rescue Errno::EEXIST
|
117
|
+
nil
|
118
|
+
end
|
119
|
+
|
120
|
+
# Probe setup is split up for easy overriding
|
121
|
+
definition
|
122
|
+
header
|
123
|
+
source
|
124
|
+
ruby_object
|
125
|
+
dtrace_object
|
126
|
+
link
|
127
|
+
load
|
128
|
+
end
|
129
|
+
end
|
130
|
+
|
131
|
+
protected
|
132
|
+
|
133
|
+
def run(cmd)
|
134
|
+
result = `#{cmd}`
|
135
|
+
if $? != 0
|
136
|
+
raise BuildError.new("Error running:\n#{cmd}\n\n#{result}")
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def hdrdir
|
141
|
+
%w(srcdir archdir).map { |name|
|
142
|
+
dir = Config::CONFIG[name]
|
143
|
+
}.find { |dir|
|
144
|
+
dir and File.exist? File.join(dir, "/ruby.h")
|
145
|
+
} or abort "ERROR: Can't find header dir for ruby. Exiting..."
|
146
|
+
end
|
147
|
+
|
148
|
+
private
|
149
|
+
|
150
|
+
def camelize(lower_case_and_underscored_word)
|
151
|
+
# Pinched from ActiveSupport's Inflector
|
152
|
+
lower_case_and_underscored_word.to_s.gsub(/\/(.?)/) { "::" + $1.upcase }.gsub(/(^|_)(.)/) { $2.upcase }
|
153
|
+
end
|
154
|
+
|
155
|
+
# compose provider definition .d file
|
156
|
+
def definition
|
157
|
+
stability = <<EOS
|
158
|
+
#pragma D attributes Evolving/Evolving/Common provider #{@name} provider
|
159
|
+
#pragma D attributes Private/Private/Common provider #{@name} module
|
160
|
+
#pragma D attributes Private/Private/Common provider #{@name} function
|
161
|
+
#pragma D attributes Evolving/Evolving/Common provider #{@name} name
|
162
|
+
#pragma D attributes Evolving/Evolving/Common provider #{@name} args
|
163
|
+
EOS
|
164
|
+
File.open("#{@tempdir}/probes.d", 'w') do |io|
|
165
|
+
io << "provider #{@name} {\n"
|
166
|
+
@probes.each_pair do |name, types|
|
167
|
+
probename = name.to_s.gsub(/_/, '__')
|
168
|
+
typesdesc = types.join(', ')
|
169
|
+
probedesc = " probe #{probename}(#{typesdesc});\n"
|
170
|
+
io << probedesc
|
171
|
+
end
|
172
|
+
io << "\n};\n\n#{stability}"
|
173
|
+
end
|
174
|
+
end
|
175
|
+
|
176
|
+
def header
|
177
|
+
run "#{DTRACE} -h -s #{@tempdir}/probes.d -o #{@tempdir}/probes.h"
|
178
|
+
end
|
179
|
+
|
180
|
+
# Generate the C source for the provider class
|
181
|
+
def source
|
182
|
+
rb2c = { 'char *' => 'STR2CSTR', 'int' => 'FIX2INT' }
|
183
|
+
|
184
|
+
File.open("#{@tempdir}/probes.c", 'w') do |io|
|
185
|
+
io.puts '#include "ruby.h"'
|
186
|
+
io.puts "#include \"#{@tempdir}/probes.h\""
|
187
|
+
|
188
|
+
@probes.each_pair do |name, types|
|
189
|
+
defn_args = []
|
190
|
+
call_args = []
|
191
|
+
types.each_with_index { |type, i| defn_args << "#{type} arg#{i}" }
|
192
|
+
types.each_with_index { |type, i| call_args << "#{rb2c[type]}(rb_ary_entry(args, #{i}))" }
|
193
|
+
|
194
|
+
io.puts <<EOC
|
195
|
+
static VALUE #{name}(VALUE self) {
|
196
|
+
if (#{@name.upcase}_#{name.to_s.upcase}_ENABLED()) {
|
197
|
+
VALUE args = rb_yield(self);
|
198
|
+
#{@name.upcase}_#{name.to_s.upcase}(#{call_args.join(', ')});
|
199
|
+
}
|
200
|
+
return Qnil;
|
201
|
+
}
|
202
|
+
EOC
|
203
|
+
end
|
204
|
+
io.puts <<EOC
|
205
|
+
static VALUE fire(VALUE self, VALUE args) {
|
206
|
+
return args;
|
207
|
+
}
|
208
|
+
|
209
|
+
void Init_#{@name}() {
|
210
|
+
VALUE c = rb_cObject;
|
211
|
+
rb_define_method(c, "fire", (VALUE(*)(ANYARGS))fire, -2);
|
212
|
+
EOC
|
213
|
+
|
214
|
+
@probes.each_pair do |name, types|
|
215
|
+
io.puts " rb_define_singleton_method(c, \"#{name}\", (VALUE(*)(ANYARGS))#{name}, 0);"
|
216
|
+
end
|
217
|
+
|
218
|
+
io.puts '}'
|
219
|
+
end
|
220
|
+
end
|
221
|
+
|
222
|
+
def load
|
223
|
+
# Load the generated extension with a full path (saves adjusting
|
224
|
+
# $:) Done in the context of an anonymous class, since the
|
225
|
+
# module does not itself define a class. TODO: find a way of
|
226
|
+
# doing this without string eval...
|
227
|
+
lib = "#{@tempdir}/#{@name}"
|
228
|
+
c = Class.new
|
229
|
+
c.module_eval do
|
230
|
+
require lib
|
231
|
+
end
|
232
|
+
eval "Dtrace::Probe::#{@class} = c"
|
233
|
+
end
|
234
|
+
|
235
|
+
end
|
236
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
class Dtrace
|
7
|
+
class Provider
|
8
|
+
class OSX < Provider
|
9
|
+
|
10
|
+
# build the .bundle
|
11
|
+
def ruby_object
|
12
|
+
run "#{Config::CONFIG['LDSHARED']} -I #{hdrdir} -o #{@tempdir}/#{@name}.bundle #{@tempdir}/probes.c"
|
13
|
+
end
|
14
|
+
|
15
|
+
def dtrace_object
|
16
|
+
# no-op on OSX
|
17
|
+
end
|
18
|
+
|
19
|
+
def link
|
20
|
+
# no-op on OSX
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'rbconfig'
|
7
|
+
|
8
|
+
class Dtrace
|
9
|
+
class Provider
|
10
|
+
class Solaris < Provider
|
11
|
+
|
12
|
+
# build the .o
|
13
|
+
def ruby_object
|
14
|
+
run "#{Config::CONFIG['CC']} -I#{hdrdir} -o #{@tempdir}/#{@name}.o -c #{@tempdir}/probes.c"
|
15
|
+
end
|
16
|
+
|
17
|
+
# build the dtrace.o (dtrace -G)
|
18
|
+
def dtrace_object
|
19
|
+
run "/usr/sbin/dtrace -G -s #{@tempdir}/probes.d -o #{@tempdir}/probes.o #{@tempdir}/#{@name}.o"
|
20
|
+
end
|
21
|
+
|
22
|
+
# build the .so
|
23
|
+
def link
|
24
|
+
run "#{Config::CONFIG['CC']} -shared -o #{@tempdir}/#{@name}.so #{@tempdir}/#{@name}.o #{@tempdir}/probes.o"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
# Leopard's ruby-probe is DTracer, Solaris's is Tracer.
|
7
|
+
|
8
|
+
class Dtrace
|
9
|
+
class Tracer
|
10
|
+
|
11
|
+
class NullTracer
|
12
|
+
def self.fire(arg0, arg1)
|
13
|
+
puts "NullTracer: #{arg0} #{arg1}"
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
@@tracer = nil
|
18
|
+
def self.fire(*args)
|
19
|
+
if @@tracer == nil
|
20
|
+
begin
|
21
|
+
# Avoid getting ourselves here:
|
22
|
+
@@tracer = Module.const_get('Tracer')
|
23
|
+
rescue NameError
|
24
|
+
begin
|
25
|
+
@@tracer = DTracer
|
26
|
+
rescue NameError
|
27
|
+
@@tracer = Dtrace::Tracer::NullTracer
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
@@tracer.fire(*args)
|
32
|
+
end
|
33
|
+
|
34
|
+
end
|
35
|
+
end
|
@@ -5,6 +5,7 @@ module DtraceReport
|
|
5
5
|
|
6
6
|
def self.included(base)
|
7
7
|
base.extend DtraceMacro
|
8
|
+
@@tracer = nil
|
8
9
|
end
|
9
10
|
|
10
11
|
module DtraceMacro
|
@@ -43,19 +44,23 @@ module DtraceReport
|
|
43
44
|
end
|
44
45
|
|
45
46
|
def enable_dtrace
|
46
|
-
@@tracer
|
47
|
+
if @@tracer
|
48
|
+
@@tracer.start_dtrace($$)
|
49
|
+
end
|
47
50
|
end
|
48
51
|
|
49
52
|
def append_dtrace_report
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
53
|
+
if @@tracer
|
54
|
+
@dtrace_script = @@tracer.script
|
55
|
+
@dtrace_report = @@tracer.end_dtrace
|
56
|
+
# yuck!
|
57
|
+
old_template_root = @template.base_path
|
58
|
+
begin
|
59
|
+
@template.view_paths = File.expand_path(File.dirname(__FILE__) + '/../views')
|
60
|
+
response.body.gsub!(/<\/body/, @template.render(:partial => 'dtrace/report') + '</body')
|
61
|
+
ensure
|
62
|
+
@template.view_paths = old_template_root
|
63
|
+
end
|
59
64
|
end
|
60
65
|
end
|
61
66
|
|
@@ -0,0 +1,135 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
require 'dtrace'
|
7
|
+
require 'dtrace/provider'
|
8
|
+
require 'test/unit'
|
9
|
+
require 'rbconfig'
|
10
|
+
|
11
|
+
# Tests for the Dtrace "dynamic USDT" library
|
12
|
+
|
13
|
+
class TestDynUsdt < Test::Unit::TestCase
|
14
|
+
|
15
|
+
def test_create_usdt
|
16
|
+
Dtrace::Provider.create :test_provider_create_usdt do |p|
|
17
|
+
p.probe :test_probe, :string
|
18
|
+
end
|
19
|
+
|
20
|
+
t = Dtrace.new
|
21
|
+
t.setopt("bufsize", "4m")
|
22
|
+
|
23
|
+
progtext = 'test_provider_create_usdt*:::test-probe { trace(copyinstr(arg0)); }'
|
24
|
+
|
25
|
+
prog = t.compile progtext
|
26
|
+
prog.execute
|
27
|
+
t.go
|
28
|
+
|
29
|
+
c = DtraceConsumer.new(t)
|
30
|
+
|
31
|
+
Dtrace::Probe::TestProviderCreateUsdt.test_probe do |p|
|
32
|
+
p.fire "test_argument"
|
33
|
+
end
|
34
|
+
|
35
|
+
i = 0
|
36
|
+
c.consume_once do |d|
|
37
|
+
i = i + 1
|
38
|
+
assert d
|
39
|
+
assert_not_nil d.probe
|
40
|
+
assert_equal "test_provider_create_usdt#{$$.to_s}:test_provider_create_usdt.#{Config::CONFIG['DLEXT']}:test_probe:test-probe", d.probe.to_s
|
41
|
+
assert_equal 1, d.data.length
|
42
|
+
assert_equal "test_argument", d.data[0].value
|
43
|
+
end
|
44
|
+
assert_equal 1, i
|
45
|
+
end
|
46
|
+
|
47
|
+
def test_create_usdt_argtypes
|
48
|
+
Dtrace::Provider.create :test_provider_create_usdt_argtypes do |p|
|
49
|
+
p.probe :test_probe_string, :string
|
50
|
+
p.probe :test_probe_int, :integer
|
51
|
+
end
|
52
|
+
|
53
|
+
t = Dtrace.new
|
54
|
+
t.setopt("bufsize", "4m")
|
55
|
+
|
56
|
+
progtext = <<EOD
|
57
|
+
test_provider_create_usdt_argtypes*:::test-probe-string { trace(copyinstr(arg0)); }
|
58
|
+
test_provider_create_usdt_argtypes*:::test-probe-int { trace(arg0); }
|
59
|
+
EOD
|
60
|
+
|
61
|
+
prog = t.compile progtext
|
62
|
+
prog.execute
|
63
|
+
t.go
|
64
|
+
|
65
|
+
c = DtraceConsumer.new(t)
|
66
|
+
|
67
|
+
Dtrace::Probe::TestProviderCreateUsdtArgtypes.test_probe_string do |p|
|
68
|
+
p.fire "test_argument"
|
69
|
+
end
|
70
|
+
|
71
|
+
Dtrace::Probe::TestProviderCreateUsdtArgtypes.test_probe_int do |p|
|
72
|
+
p.fire 42
|
73
|
+
end
|
74
|
+
|
75
|
+
i = 0
|
76
|
+
c.consume_once do |d|
|
77
|
+
assert d
|
78
|
+
assert_not_nil d.probe
|
79
|
+
if d.probe.name == 'test-probe-string'
|
80
|
+
assert_equal "test_argument", d.data[0].value
|
81
|
+
i = i + 1
|
82
|
+
elsif d.probe.name == 'test-probe-int'
|
83
|
+
assert_equal 42, d.data[0].value
|
84
|
+
i = i + 1
|
85
|
+
end
|
86
|
+
end
|
87
|
+
assert_equal 2, i
|
88
|
+
end
|
89
|
+
|
90
|
+
def test_create_usdt_manyargs
|
91
|
+
Dtrace::Provider.create :test_provider_create_usdt_manyargs do |p|
|
92
|
+
p.probe :test_probe, :string, :string, :string, :string, :string, :string, :string, :string
|
93
|
+
end
|
94
|
+
|
95
|
+
t = Dtrace.new
|
96
|
+
t.setopt("bufsize", "4m")
|
97
|
+
|
98
|
+
progtext = <<EOD
|
99
|
+
test_provider_create_usdt_manyargs*:::test-probe
|
100
|
+
{
|
101
|
+
trace(copyinstr(arg0));
|
102
|
+
trace(copyinstr(arg1));
|
103
|
+
trace(copyinstr(arg2));
|
104
|
+
trace(copyinstr(arg3));
|
105
|
+
trace(copyinstr(arg4));
|
106
|
+
trace(copyinstr(arg5));
|
107
|
+
trace(copyinstr(arg6));
|
108
|
+
trace(copyinstr(arg7));
|
109
|
+
}
|
110
|
+
EOD
|
111
|
+
|
112
|
+
prog = t.compile progtext
|
113
|
+
prog.execute
|
114
|
+
t.go
|
115
|
+
|
116
|
+
c = DtraceConsumer.new(t)
|
117
|
+
|
118
|
+
Dtrace::Probe::TestProviderCreateUsdtManyargs.test_probe do |p|
|
119
|
+
values_list = (0..7).map {|i| "value #{i.to_s}" }
|
120
|
+
p.fire(*values_list)
|
121
|
+
end
|
122
|
+
|
123
|
+
i = 0
|
124
|
+
c.consume_once do |d|
|
125
|
+
i = i + 1
|
126
|
+
assert_equal 8, d.data.length
|
127
|
+
(0..7).each do |j|
|
128
|
+
assert_equal "value #{j.to_s}", d.data[j].value
|
129
|
+
end
|
130
|
+
end
|
131
|
+
assert_equal 1, i
|
132
|
+
end
|
133
|
+
|
134
|
+
end
|
135
|
+
|
metadata
CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.9.4
|
|
3
3
|
specification_version: 1
|
4
4
|
name: ruby-dtrace
|
5
5
|
version: !ruby/object:Gem::Version
|
6
|
-
version: 0.0.
|
7
|
-
date: 2008-
|
6
|
+
version: 0.0.6
|
7
|
+
date: 2008-02-17 00:00:00 +00:00
|
8
8
|
summary: Ruby bindings for libdtrace
|
9
9
|
require_paths:
|
10
10
|
- lib
|
@@ -51,6 +51,11 @@ files:
|
|
51
51
|
- ext/dtrace_util.c
|
52
52
|
- ext/extconf.rb
|
53
53
|
- lib/dtrace.rb
|
54
|
+
- lib/dtrace/probe.rb
|
55
|
+
- lib/dtrace/provider.rb
|
56
|
+
- lib/dtrace/provider/osx.rb
|
57
|
+
- lib/dtrace/provider/solaris.rb
|
58
|
+
- lib/dtrace/tracer.rb
|
54
59
|
- lib/dtraceaggregate.rb
|
55
60
|
- lib/dtraceaggregateset.rb
|
56
61
|
- lib/dtraceconsumer.rb
|
@@ -82,6 +87,7 @@ files:
|
|
82
87
|
- test/test_dtrace_repeat.rb
|
83
88
|
- test/test_dtrace_rubyprobe.rb
|
84
89
|
- test/test_dtrace_typefilter.rb
|
90
|
+
- test/test_dynusdt.rb
|
85
91
|
test_files:
|
86
92
|
- test/test_dtrace.rb
|
87
93
|
- test/test_dtrace_aggregates.rb
|
@@ -91,6 +97,7 @@ test_files:
|
|
91
97
|
- test/test_dtrace_repeat.rb
|
92
98
|
- test/test_dtrace_rubyprobe.rb
|
93
99
|
- test/test_dtrace_typefilter.rb
|
100
|
+
- test/test_dynusdt.rb
|
94
101
|
rdoc_options:
|
95
102
|
- --main
|
96
103
|
- README.txt
|