ruby-dtrace 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/History.txt +3 -0
- data/Manifest.txt +28 -0
- data/README.txt +60 -0
- data/Rakefile +30 -0
- data/ext/dtrace_aggregate.c +150 -0
- data/ext/dtrace_api.c +69 -0
- data/ext/dtrace_api.h +53 -0
- data/ext/dtrace_hdl.c +280 -0
- data/ext/dtrace_probe.c +78 -0
- data/ext/dtrace_program.c +57 -0
- data/ext/dtrace_programinfo.c +60 -0
- data/ext/dtrace_recdesc.c +38 -0
- data/ext/extconf.rb +4 -0
- data/lib/dtrace.rb +11 -0
- data/plugin/dtrace/README +4 -0
- data/plugin/dtrace/Rakefile +22 -0
- data/plugin/dtrace/bin/dtracer.rb +24 -0
- data/plugin/dtrace/init.rb +7 -0
- data/plugin/dtrace/lib/dtrace_helper.rb +2 -0
- data/plugin/dtrace/lib/dtrace_report.rb +47 -0
- data/plugin/dtrace/lib/dtrace_tracer.rb +34 -0
- data/plugin/dtrace/lib/dtracer.rb +43 -0
- data/plugin/dtrace/lib/dtracer_client.rb +18 -0
- data/plugin/dtrace/public/stylesheets/dtrace.css +48 -0
- data/plugin/dtrace/tasks/dtrace.rake +52 -0
- data/plugin/dtrace/test/dtrace_test.rb +8 -0
- data/plugin/dtrace/views/dtrace/_report.rhtml +11 -0
- data/test/test_dtrace.rb +415 -0
- metadata +85 -0
data/History.txt
ADDED
data/Manifest.txt
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
History.txt
|
2
|
+
Manifest.txt
|
3
|
+
README.txt
|
4
|
+
Rakefile
|
5
|
+
ext/dtrace_aggregate.c
|
6
|
+
ext/dtrace_api.c
|
7
|
+
ext/dtrace_api.h
|
8
|
+
ext/dtrace_hdl.c
|
9
|
+
ext/dtrace_probe.c
|
10
|
+
ext/dtrace_program.c
|
11
|
+
ext/dtrace_programinfo.c
|
12
|
+
ext/dtrace_recdesc.c
|
13
|
+
ext/extconf.rb
|
14
|
+
lib/dtrace.rb
|
15
|
+
plugin/dtrace/README
|
16
|
+
plugin/dtrace/Rakefile
|
17
|
+
plugin/dtrace/bin/dtracer.rb
|
18
|
+
plugin/dtrace/init.rb
|
19
|
+
plugin/dtrace/lib/dtrace_helper.rb
|
20
|
+
plugin/dtrace/lib/dtrace_report.rb
|
21
|
+
plugin/dtrace/lib/dtrace_tracer.rb
|
22
|
+
plugin/dtrace/lib/dtracer.rb
|
23
|
+
plugin/dtrace/lib/dtracer_client.rb
|
24
|
+
plugin/dtrace/public/stylesheets/dtrace.css
|
25
|
+
plugin/dtrace/tasks/dtrace.rake
|
26
|
+
plugin/dtrace/test/dtrace_test.rb
|
27
|
+
plugin/dtrace/views/dtrace/_report.rhtml
|
28
|
+
test/test_dtrace.rb
|
data/README.txt
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
ruby-dtrace is Ruby bindings for Dtrace, which lets you write D-based
|
2
|
+
programs in Ruby. It doesn't provide D probes for Ruby, but you can
|
3
|
+
use it with the probes found in the Joyent and Apple builds of Ruby.
|
4
|
+
|
5
|
+
== FEATURES
|
6
|
+
|
7
|
+
* Access to the D API
|
8
|
+
* Probe metadata
|
9
|
+
* Run D programs
|
10
|
+
* Access aggregates
|
11
|
+
|
12
|
+
== SYNOPSIS
|
13
|
+
|
14
|
+
t = Dtrace.new
|
15
|
+
dprog = "ruby*:::function-entry{ @[copyinstr(arg1)] = count(); }"
|
16
|
+
prog = t.compile dprog
|
17
|
+
prog.execute
|
18
|
+
t.go
|
19
|
+
|
20
|
+
[...]
|
21
|
+
|
22
|
+
t.stop
|
23
|
+
t.aggregate_snap
|
24
|
+
t.each_aggregate do |agg|
|
25
|
+
(0..(agg.num_records - 1)).each do |i|
|
26
|
+
rec = agg[i]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
== REQUIREMENTS
|
31
|
+
|
32
|
+
* A platform with Dtrace support (OpenSolaris, Mac OS X 10.5 Leopard tested, possibly also FreeBSD).
|
33
|
+
* root, or some/all of the dtrace privileges on Solaris: dtrace_user, dtrace_proc and dtrace_kernel.
|
34
|
+
|
35
|
+
== INSTALL
|
36
|
+
|
37
|
+
$ sudo gem install ruby-dtrace
|
38
|
+
|
39
|
+
== LICENSE
|
40
|
+
|
41
|
+
Copyright (c) 2007 Chris Andrews <chris@nodnol.org>
|
42
|
+
|
43
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
44
|
+
a copy of this software and associated documentation files (the
|
45
|
+
'Software'), to deal in the Software without restriction, including
|
46
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
47
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
48
|
+
permit persons to whom the Software is furnished to do so, subject to
|
49
|
+
the following conditions:
|
50
|
+
|
51
|
+
The above copyright notice and this permission notice shall be
|
52
|
+
included in all copies or substantial portions of the Software.
|
53
|
+
|
54
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
55
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
56
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
57
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
58
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
59
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
60
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
# -*- ruby -*-
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'hoe'
|
5
|
+
require './lib/dtrace'
|
6
|
+
|
7
|
+
Hoe.new('ruby-dtrace', Dtrace::VERSION) do |p|
|
8
|
+
p.rubyforge_name = 'ruby-dtrace'
|
9
|
+
p.author = 'Chris Andrews'
|
10
|
+
p.email = 'chris@nodnol.org'
|
11
|
+
p.summary = 'Ruby bindings for libdtrace'
|
12
|
+
p.description = <<EOD
|
13
|
+
ruby-dtrace is Ruby bindings for Dtrace, which lets you write D-based
|
14
|
+
programs in Ruby. It doesn't provide D probes for Ruby, but you can
|
15
|
+
use it with the probes found in the Joyent and Apple builds of Ruby.
|
16
|
+
EOD
|
17
|
+
p.spec_extras = {:extensions => ['ext/extconf.rb']}
|
18
|
+
p.url = "http://ruby-dtrace.rubyforge.org/"
|
19
|
+
p.changes = p.paragraphs_of('History.txt', 0..1).join("\n\n")
|
20
|
+
end
|
21
|
+
|
22
|
+
desc "Uses extconf.rb and make to build the extension"
|
23
|
+
task :extensions do
|
24
|
+
Dir.chdir('ext')
|
25
|
+
system("ruby extconf.rb")
|
26
|
+
system("make")
|
27
|
+
Dir.chdir('..')
|
28
|
+
end
|
29
|
+
|
30
|
+
# vim: syntax=Ruby
|
@@ -0,0 +1,150 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE cDtraceProbe;
|
8
|
+
RUBY_EXTERN VALUE cDtraceRecDesc;
|
9
|
+
|
10
|
+
/* :nodoc: */
|
11
|
+
VALUE dtraceaggdata_init(VALUE self)
|
12
|
+
{
|
13
|
+
dtrace_aggdata_t *aggdata;
|
14
|
+
|
15
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
16
|
+
return self;
|
17
|
+
}
|
18
|
+
|
19
|
+
/*
|
20
|
+
* Returns the description of this aggregate.
|
21
|
+
*/
|
22
|
+
VALUE dtraceaggdata_desc(VALUE self)
|
23
|
+
{
|
24
|
+
VALUE string;
|
25
|
+
dtrace_aggdata_t *aggdata;
|
26
|
+
dtrace_aggdesc_t *aggdesc;
|
27
|
+
dtrace_recdesc_t *nrec, *irec;
|
28
|
+
char *name, c[256];
|
29
|
+
|
30
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
31
|
+
|
32
|
+
aggdesc = aggdata->dtada_desc;
|
33
|
+
nrec = &aggdesc->dtagd_rec[1];
|
34
|
+
irec = &aggdesc->dtagd_rec[2];
|
35
|
+
|
36
|
+
name = aggdata->dtada_data + nrec->dtrd_offset;
|
37
|
+
string = rb_str_new2(name);
|
38
|
+
return string;
|
39
|
+
}
|
40
|
+
|
41
|
+
/*
|
42
|
+
* Returns the value of this aggregate.
|
43
|
+
*/
|
44
|
+
VALUE dtraceaggdata_value(VALUE self)
|
45
|
+
{
|
46
|
+
dtrace_aggdata_t *aggdata;
|
47
|
+
dtrace_aggdesc_t *aggdesc;
|
48
|
+
dtrace_recdesc_t *nrec, *irec;
|
49
|
+
|
50
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
51
|
+
|
52
|
+
aggdesc = aggdata->dtada_desc;
|
53
|
+
nrec = &aggdesc->dtagd_rec[1];
|
54
|
+
irec = &aggdesc->dtagd_rec[2];
|
55
|
+
|
56
|
+
uint64_t n = *((uint64_t *)(aggdata->dtada_data + irec->dtrd_offset));
|
57
|
+
|
58
|
+
return INT2FIX(n);
|
59
|
+
}
|
60
|
+
|
61
|
+
/*
|
62
|
+
* Returns the size of this aggregate.
|
63
|
+
*/
|
64
|
+
VALUE dtraceaggdata_size(VALUE self)
|
65
|
+
{
|
66
|
+
dtrace_aggdata_t *aggdata;
|
67
|
+
|
68
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
69
|
+
|
70
|
+
return INT2FIX(aggdata->dtada_size);
|
71
|
+
}
|
72
|
+
|
73
|
+
/*
|
74
|
+
* Yields each record for this aggregate.
|
75
|
+
*/
|
76
|
+
VALUE dtraceaggdata_each_record(VALUE self)
|
77
|
+
{
|
78
|
+
VALUE dtracerecdesc;
|
79
|
+
dtrace_aggdata_t *aggdata;
|
80
|
+
dtrace_aggdesc_t *aggdesc;
|
81
|
+
dtrace_recdesc_t *rec;
|
82
|
+
int i;
|
83
|
+
caddr_t data;
|
84
|
+
|
85
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
86
|
+
aggdesc = aggdata->dtada_desc;
|
87
|
+
|
88
|
+
for (i = 0; i < aggdesc->dtagd_nrecs; i++) {
|
89
|
+
rec = &aggdesc->dtagd_rec[i];
|
90
|
+
dtracerecdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, rec);
|
91
|
+
rb_iv_set(dtracerecdesc, "@aggdata", self);
|
92
|
+
rb_yield(dtracerecdesc);
|
93
|
+
}
|
94
|
+
|
95
|
+
return Qnil;
|
96
|
+
}
|
97
|
+
|
98
|
+
/*
|
99
|
+
* Return the number of records in this aggregate.
|
100
|
+
*/
|
101
|
+
VALUE dtraceaggdata_num_records(VALUE self)
|
102
|
+
{
|
103
|
+
VALUE dtracerecdesc;
|
104
|
+
dtrace_aggdata_t *aggdata;
|
105
|
+
dtrace_aggdesc_t *aggdesc;
|
106
|
+
|
107
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
108
|
+
aggdesc = aggdata->dtada_desc;
|
109
|
+
|
110
|
+
return INT2FIX(aggdesc->dtagd_nrecs);
|
111
|
+
}
|
112
|
+
|
113
|
+
/*
|
114
|
+
* Access the array of records in this aggregate.
|
115
|
+
*/
|
116
|
+
VALUE dtraceaggdata_record(VALUE self, VALUE index)
|
117
|
+
{
|
118
|
+
VALUE dtracerecdesc;
|
119
|
+
dtrace_aggdata_t *aggdata;
|
120
|
+
dtrace_aggdesc_t *aggdesc;
|
121
|
+
dtrace_recdesc_t *rec;
|
122
|
+
int i;
|
123
|
+
|
124
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
125
|
+
aggdesc = aggdata->dtada_desc;
|
126
|
+
|
127
|
+
i = FIX2INT(index);
|
128
|
+
if (i >= aggdesc->dtagd_nrecs)
|
129
|
+
return Qnil;
|
130
|
+
else {
|
131
|
+
rec = &aggdesc->dtagd_rec[i];
|
132
|
+
dtracerecdesc = Data_Wrap_Struct(cDtraceRecDesc, 0, NULL, rec);
|
133
|
+
rb_iv_set(dtracerecdesc, "@aggdata", self);
|
134
|
+
return dtracerecdesc;
|
135
|
+
}
|
136
|
+
}
|
137
|
+
|
138
|
+
/*
|
139
|
+
* Return the probe associated with this aggregate.
|
140
|
+
*/
|
141
|
+
VALUE dtraceaggdata_probe(VALUE self)
|
142
|
+
{
|
143
|
+
VALUE probe;
|
144
|
+
dtrace_aggdata_t *aggdata;
|
145
|
+
|
146
|
+
Data_Get_Struct(self, dtrace_aggdata_t, aggdata);
|
147
|
+
probe = Data_Wrap_Struct(cDtraceProbe, 0, NULL, (dtrace_probedesc_t *)aggdata->dtada_pdesc);
|
148
|
+
|
149
|
+
return probe;
|
150
|
+
}
|
data/ext/dtrace_api.c
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
VALUE cDtrace;
|
8
|
+
VALUE cDtraceProbe;
|
9
|
+
VALUE cDtraceProgram;
|
10
|
+
VALUE cDtraceProgramInfo;
|
11
|
+
VALUE cDtraceAggData;
|
12
|
+
VALUE cDtraceRecDesc;
|
13
|
+
|
14
|
+
VALUE eDtraceException;
|
15
|
+
|
16
|
+
void Init_dtrace_api() {
|
17
|
+
|
18
|
+
cDtrace = rb_define_class("Dtrace", rb_cObject);
|
19
|
+
rb_define_method(cDtrace, "initialize", dtrace_init, 0); // in dtrace_hdl.c
|
20
|
+
rb_define_method(cDtrace, "each_probe", dtrace_each_probe, 0); // in dtrace_hdl.c
|
21
|
+
rb_define_method(cDtrace, "compile", dtrace_strcompile, -1); // in dtrace_hdl.c
|
22
|
+
rb_define_method(cDtrace, "stop", dtrace_hdl_stop, 0); // in dtrace_hdl.c
|
23
|
+
rb_define_method(cDtrace, "status", dtrace_hdl_status, 0); // in dtrace_hdl.c
|
24
|
+
rb_define_method(cDtrace, "go", dtrace_hdl_go, 0); // in dtrace_hdl.c
|
25
|
+
rb_define_method(cDtrace, "each_aggregate", dtrace_hdl_each_aggregate, 0); // in dtrace_hdl.c
|
26
|
+
rb_define_method(cDtrace, "aggregate_print", dtrace_hdl_aggregate_print, 0); // in dtrace_hdl.c
|
27
|
+
rb_define_method(cDtrace, "aggregate_snap", dtrace_hdl_aggregate_snap, 0); // in dtrace_hdl.c
|
28
|
+
rb_define_method(cDtrace, "aggregate_clear", dtrace_hdl_aggregate_clear, 0); // in dtrace_hdl.c
|
29
|
+
rb_define_method(cDtrace, "error", dtrace_hdl_error, 0); // in dtrace_hdl.c
|
30
|
+
rb_define_method(cDtrace, "setopt", dtrace_hdl_setopt, 2); // in dtrace_hdl.c
|
31
|
+
rb_define_alloc_func(cDtrace, dtrace_hdl_alloc);
|
32
|
+
|
33
|
+
cDtraceProbe = rb_define_class("DtraceProbe", rb_cObject);
|
34
|
+
rb_define_method(cDtraceProbe, "initialize", dtraceprobe_init, 0); // in dtrace_probe.c
|
35
|
+
rb_define_method(cDtraceProbe, "probe_id", dtraceprobe_probe_id, 0); // in dtrace_probe.c
|
36
|
+
rb_define_method(cDtraceProbe, "provider", dtraceprobe_provider, 0); // in dtrace_probe.c
|
37
|
+
rb_define_method(cDtraceProbe, "mod", dtraceprobe_mod, 0); // in dtrace_probe.c
|
38
|
+
rb_define_method(cDtraceProbe, "func", dtraceprobe_func, 0); // in dtrace_probe.c
|
39
|
+
rb_define_method(cDtraceProbe, "name", dtraceprobe_name, 0); // in dtrace_probe.c
|
40
|
+
|
41
|
+
cDtraceProgram = rb_define_class("DtraceProgram", rb_cObject);
|
42
|
+
rb_define_method(cDtraceProgram, "initialize", dtraceprogram_init, 0); // in dtrace_program.c
|
43
|
+
rb_define_method(cDtraceProgram, "execute", dtraceprogram_exec, 0); // in dtrace_program.c
|
44
|
+
rb_define_method(cDtraceProgram, "info", dtraceprogram_info, 0); // in dtrace_program.c
|
45
|
+
|
46
|
+
cDtraceProgramInfo = rb_define_class("DtraceProgramInfo", rb_cObject);
|
47
|
+
rb_define_method(cDtraceProgramInfo, "initialize", dtraceprograminfo_init, 0); // in dtrace_programinfo.c
|
48
|
+
rb_define_method(cDtraceProgramInfo, "aggregates_count", dtraceprograminfo_aggregates_count, 0); // in dtrace_programinfo.c
|
49
|
+
rb_define_method(cDtraceProgramInfo, "recgens_count", dtraceprograminfo_recgens_count, 0); // in dtrace_programinfo.c
|
50
|
+
rb_define_method(cDtraceProgramInfo, "matches_count", dtraceprograminfo_matches_count, 0); // in dtrace_programinfo.c
|
51
|
+
rb_define_method(cDtraceProgramInfo, "speculations_count", dtraceprograminfo_speculations_count, 0); // in dtrace_programinfo.c
|
52
|
+
|
53
|
+
cDtraceAggData = rb_define_class("DtraceAggData", rb_cObject);
|
54
|
+
rb_define_method(cDtraceAggData, "initialize", dtraceaggdata_init, 0); // in dtrace_aggregate.c
|
55
|
+
rb_define_method(cDtraceAggData, "desc", dtraceaggdata_desc, 0); // in dtrace_aggregate.c
|
56
|
+
rb_define_method(cDtraceAggData, "value", dtraceaggdata_value, 0); // in dtrace_aggregate.c
|
57
|
+
rb_define_method(cDtraceAggData, "size", dtraceaggdata_size, 0); // in dtrace_aggregate.c
|
58
|
+
rb_define_method(cDtraceAggData, "each_record", dtraceaggdata_each_record, 0); // in dtrace_aggregate.c
|
59
|
+
rb_define_method(cDtraceAggData, "num_records", dtraceaggdata_num_records, 0); // in dtrace_aggregate.c
|
60
|
+
rb_define_method(cDtraceAggData, "[]", dtraceaggdata_record, 1); // in dtrace_aggregate.c
|
61
|
+
rb_define_method(cDtraceAggData, "probe", dtraceaggdata_probe, 0); // in dtrace_aggregate.c
|
62
|
+
|
63
|
+
cDtraceRecDesc = rb_define_class("DtraceRecDesc", rb_cObject);
|
64
|
+
rb_define_method(cDtraceRecDesc, "initialize", dtracerecdesc_init, 0); // in dtrace_recdesc.c
|
65
|
+
rb_define_method(cDtraceRecDesc, "data", dtracerecdesc_data, 0); // in dtrace_recdesc.c
|
66
|
+
|
67
|
+
eDtraceException = rb_define_class("DtraceException", rb_eStandardError);
|
68
|
+
}
|
69
|
+
|
data/ext/dtrace_api.h
ADDED
@@ -0,0 +1,53 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
/* this is a full path because the ruby-dtrace probes add a "dtrace.h"
|
6
|
+
* in the same directory as ruby.h, and we must avoid loading that...
|
7
|
+
*/
|
8
|
+
#include "/usr/include/dtrace.h"
|
9
|
+
#include "ruby.h"
|
10
|
+
|
11
|
+
VALUE dtraceaggdata_init(VALUE self);
|
12
|
+
VALUE dtraceaggdata_desc(VALUE self);
|
13
|
+
VALUE dtraceaggdata_value(VALUE self);
|
14
|
+
VALUE dtraceaggdata_size(VALUE self);
|
15
|
+
VALUE dtraceaggdata_each_record(VALUE self);
|
16
|
+
VALUE dtraceaggdata_num_records(VALUE self);
|
17
|
+
VALUE dtraceaggdata_record(VALUE self, VALUE index);
|
18
|
+
VALUE dtraceaggdata_probe(VALUE self);
|
19
|
+
|
20
|
+
void dtrace_hdl_free (void *handle);
|
21
|
+
VALUE dtrace_hdl_alloc(VALUE klass);
|
22
|
+
VALUE dtrace_init(VALUE self);
|
23
|
+
VALUE dtrace_each_probe(VALUE self);
|
24
|
+
VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self);
|
25
|
+
VALUE dtrace_hdl_go(VALUE self);
|
26
|
+
VALUE dtrace_hdl_status(VALUE self);
|
27
|
+
VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value);
|
28
|
+
VALUE dtrace_hdl_stop(VALUE self);
|
29
|
+
VALUE dtrace_hdl_each_aggregate(VALUE self);
|
30
|
+
VALUE dtrace_hdl_aggregate_print(VALUE self);
|
31
|
+
VALUE dtrace_hdl_aggregate_snap(VALUE self);
|
32
|
+
VALUE dtrace_hdl_aggregate_clear(VALUE self);
|
33
|
+
VALUE dtrace_hdl_error(VALUE self);
|
34
|
+
|
35
|
+
VALUE dtraceprobe_init(VALUE self);
|
36
|
+
VALUE dtraceprobe_probe_id(VALUE self);
|
37
|
+
VALUE dtraceprobe_provider(VALUE self);
|
38
|
+
VALUE dtraceprobe_mod(VALUE self);
|
39
|
+
VALUE dtraceprobe_func(VALUE self);
|
40
|
+
VALUE dtraceprobe_name(VALUE self);
|
41
|
+
|
42
|
+
VALUE dtraceprogram_init(VALUE self);
|
43
|
+
VALUE dtraceprogram_exec(VALUE self);
|
44
|
+
VALUE dtraceprogram_info(VALUE self);
|
45
|
+
|
46
|
+
VALUE dtraceprograminfo_init(VALUE self);
|
47
|
+
VALUE dtraceprograminfo_aggregates_count(VALUE self);
|
48
|
+
VALUE dtraceprograminfo_recgens_count(VALUE self);
|
49
|
+
VALUE dtraceprograminfo_matches_count(VALUE self);
|
50
|
+
VALUE dtraceprograminfo_speculations_count(VALUE self);
|
51
|
+
|
52
|
+
VALUE dtracerecdesc_init(VALUE self);
|
53
|
+
VALUE dtracerecdesc_data(VALUE self);
|
data/ext/dtrace_hdl.c
ADDED
@@ -0,0 +1,280 @@
|
|
1
|
+
/* Ruby-Dtrace
|
2
|
+
* (c) 2007 Chris Andrews <chris@nodnol.org>
|
3
|
+
*/
|
4
|
+
|
5
|
+
#include "dtrace_api.h"
|
6
|
+
|
7
|
+
RUBY_EXTERN VALUE eDtraceException;
|
8
|
+
RUBY_EXTERN VALUE cDtraceProbe;
|
9
|
+
RUBY_EXTERN VALUE cDtraceProgram;
|
10
|
+
RUBY_EXTERN VALUE cDtraceAggData;
|
11
|
+
|
12
|
+
void dtrace_hdl_free (void *handle)
|
13
|
+
{
|
14
|
+
dtrace_close(handle);
|
15
|
+
}
|
16
|
+
|
17
|
+
VALUE dtrace_hdl_alloc(VALUE klass)
|
18
|
+
{
|
19
|
+
dtrace_hdl_t *handle;
|
20
|
+
int err;
|
21
|
+
VALUE obj;
|
22
|
+
|
23
|
+
handle = dtrace_open(DTRACE_VERSION, 0, &err);
|
24
|
+
|
25
|
+
if (handle) {
|
26
|
+
obj = Data_Wrap_Struct(klass, 0, dtrace_hdl_free, handle);
|
27
|
+
return obj;
|
28
|
+
}
|
29
|
+
else {
|
30
|
+
rb_raise(eDtraceException, "unable to open dtrace (not root?)");
|
31
|
+
}
|
32
|
+
}
|
33
|
+
|
34
|
+
/* :nodoc: */
|
35
|
+
VALUE dtrace_init(VALUE self)
|
36
|
+
{
|
37
|
+
dtrace_hdl_t *handle;
|
38
|
+
|
39
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
40
|
+
if (handle)
|
41
|
+
return self;
|
42
|
+
else
|
43
|
+
return Qnil;
|
44
|
+
}
|
45
|
+
|
46
|
+
int _dtrace_next_probe(dtrace_hdl_t *dtp, const dtrace_probedesc_t *pdp, void *arg)
|
47
|
+
{
|
48
|
+
VALUE probe;
|
49
|
+
|
50
|
+
probe = Data_Wrap_Struct(cDtraceProbe, 0, NULL, (dtrace_probedesc_t *)pdp);
|
51
|
+
|
52
|
+
rb_yield(probe);
|
53
|
+
return 0;
|
54
|
+
}
|
55
|
+
|
56
|
+
/*
|
57
|
+
* Yields each probe found on the system.
|
58
|
+
* (equivalent to dtrace -l)
|
59
|
+
*
|
60
|
+
* Each probe is represented by a DtraceProbe object
|
61
|
+
*/
|
62
|
+
VALUE dtrace_each_probe(VALUE self)
|
63
|
+
{
|
64
|
+
dtrace_hdl_t *handle;
|
65
|
+
|
66
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
67
|
+
(void) dtrace_probe_iter(handle, NULL, _dtrace_next_probe, NULL);
|
68
|
+
|
69
|
+
return self;
|
70
|
+
}
|
71
|
+
|
72
|
+
/*
|
73
|
+
* Compile a D program.
|
74
|
+
*
|
75
|
+
* Arguments:
|
76
|
+
* * The program text to compile
|
77
|
+
* * (Optionally) any arguments required by the program
|
78
|
+
*
|
79
|
+
* Raises a DtraceException if the program cannot be compiled.
|
80
|
+
*/
|
81
|
+
VALUE dtrace_strcompile(int argc, VALUE *argv, VALUE self)
|
82
|
+
{
|
83
|
+
dtrace_hdl_t *handle;
|
84
|
+
dtrace_prog_t *program;
|
85
|
+
VALUE dtrace_program;
|
86
|
+
|
87
|
+
VALUE dtrace_text;
|
88
|
+
int dtrace_argc;
|
89
|
+
VALUE dtrace_argv_array;
|
90
|
+
|
91
|
+
char **dtrace_argv;
|
92
|
+
int i;
|
93
|
+
|
94
|
+
rb_scan_args(argc, argv, "1*", &dtrace_text, &dtrace_argv_array);
|
95
|
+
|
96
|
+
dtrace_argc = FIX2INT(rb_funcall(dtrace_argv_array, rb_intern("length"), 0));
|
97
|
+
dtrace_argv = ALLOC_N(char *, dtrace_argc + 1);
|
98
|
+
for (i = 0; i < dtrace_argc; i++) {
|
99
|
+
dtrace_argv[i + 1] = STR2CSTR(rb_ary_entry(dtrace_argv_array, i));
|
100
|
+
}
|
101
|
+
|
102
|
+
dtrace_argv[0] = "ruby";
|
103
|
+
dtrace_argc++;
|
104
|
+
|
105
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
106
|
+
program = dtrace_program_strcompile(handle, STR2CSTR(dtrace_text),
|
107
|
+
DTRACE_PROBESPEC_NAME, DTRACE_C_PSPEC,
|
108
|
+
dtrace_argc, dtrace_argv);
|
109
|
+
|
110
|
+
if (!program) {
|
111
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
112
|
+
return Qnil;
|
113
|
+
}
|
114
|
+
else {
|
115
|
+
dtrace_program = Data_Wrap_Struct(cDtraceProgram, 0, NULL, program);
|
116
|
+
rb_iv_set(dtrace_program, "@dtrace", self);
|
117
|
+
return dtrace_program;
|
118
|
+
}
|
119
|
+
}
|
120
|
+
|
121
|
+
/*
|
122
|
+
* Start tracing. Must be called once a program has been successfully
|
123
|
+
* compiled and executed.
|
124
|
+
*
|
125
|
+
* Raises a DtraceException on any error.
|
126
|
+
*/
|
127
|
+
VALUE dtrace_hdl_go(VALUE self)
|
128
|
+
{
|
129
|
+
dtrace_hdl_t *handle;
|
130
|
+
|
131
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
132
|
+
if (dtrace_go(handle) < 0)
|
133
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
134
|
+
|
135
|
+
return Qnil;
|
136
|
+
}
|
137
|
+
|
138
|
+
/*
|
139
|
+
* Returns the status of the DTrace handle.
|
140
|
+
*
|
141
|
+
* Status values are defined as:
|
142
|
+
*
|
143
|
+
* * 0 - none
|
144
|
+
* * 1 - ok
|
145
|
+
* * 4 - stopped
|
146
|
+
*/
|
147
|
+
VALUE dtrace_hdl_status(VALUE self)
|
148
|
+
{
|
149
|
+
dtrace_hdl_t *handle;
|
150
|
+
int status;
|
151
|
+
|
152
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
153
|
+
if ((status = dtrace_status(handle)) < 0)
|
154
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
155
|
+
|
156
|
+
return INT2FIX(status);
|
157
|
+
}
|
158
|
+
|
159
|
+
/*
|
160
|
+
* Set an option on the DTrace handle.
|
161
|
+
*
|
162
|
+
* Options which may be set:
|
163
|
+
*
|
164
|
+
* * aggsize
|
165
|
+
* * bufsize
|
166
|
+
*/
|
167
|
+
VALUE dtrace_hdl_setopt(VALUE self, VALUE key, VALUE value)
|
168
|
+
{
|
169
|
+
dtrace_hdl_t *handle;
|
170
|
+
int ret;
|
171
|
+
|
172
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
173
|
+
|
174
|
+
if (NIL_P(value)) {
|
175
|
+
ret = dtrace_setopt(handle, STR2CSTR(key), 0);
|
176
|
+
}
|
177
|
+
else {
|
178
|
+
ret = dtrace_setopt(handle, STR2CSTR(key), STR2CSTR(value));
|
179
|
+
}
|
180
|
+
|
181
|
+
if (ret < 0)
|
182
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
183
|
+
|
184
|
+
return Qnil;
|
185
|
+
}
|
186
|
+
|
187
|
+
/* Stop tracing.
|
188
|
+
*
|
189
|
+
* Must be called after go has been called to start tracing.
|
190
|
+
*/
|
191
|
+
VALUE dtrace_hdl_stop(VALUE self)
|
192
|
+
{
|
193
|
+
dtrace_hdl_t *handle;
|
194
|
+
|
195
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
196
|
+
if (dtrace_stop(handle) < 0)
|
197
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
198
|
+
|
199
|
+
return Qnil;
|
200
|
+
}
|
201
|
+
|
202
|
+
int _agg_walk_yield(const dtrace_aggdata_t *data, void *arg)
|
203
|
+
{
|
204
|
+
VALUE aggdata;
|
205
|
+
|
206
|
+
aggdata = Data_Wrap_Struct(cDtraceAggData, 0, NULL, (dtrace_aggdata_t *)data);
|
207
|
+
|
208
|
+
rb_yield(aggdata);
|
209
|
+
return (DTRACE_AGGWALK_NEXT);
|
210
|
+
}
|
211
|
+
|
212
|
+
/*
|
213
|
+
* Yields each aggregate in turn.
|
214
|
+
*
|
215
|
+
* Aggregates are represented by a DtraceAggregate object.
|
216
|
+
*/
|
217
|
+
VALUE dtrace_hdl_each_aggregate(VALUE self)
|
218
|
+
{
|
219
|
+
dtrace_hdl_t *handle;
|
220
|
+
|
221
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
222
|
+
if (dtrace_aggregate_walk_keyvarsorted(handle, _agg_walk_yield, NULL) < 0)
|
223
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
224
|
+
|
225
|
+
return Qnil;
|
226
|
+
}
|
227
|
+
|
228
|
+
/*
|
229
|
+
* Uses libdtrace to print a summary of aggregates to STDERR.
|
230
|
+
*/
|
231
|
+
VALUE dtrace_hdl_aggregate_print(VALUE self)
|
232
|
+
{
|
233
|
+
dtrace_hdl_t *handle;
|
234
|
+
|
235
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
236
|
+
if (dtrace_aggregate_print(handle, stderr, NULL) < 0)
|
237
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
238
|
+
|
239
|
+
return Qnil;
|
240
|
+
}
|
241
|
+
|
242
|
+
/*
|
243
|
+
* Take a snapshot of the current aggregate values.
|
244
|
+
*/
|
245
|
+
VALUE dtrace_hdl_aggregate_snap(VALUE self)
|
246
|
+
{
|
247
|
+
dtrace_hdl_t *handle;
|
248
|
+
|
249
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
250
|
+
if (dtrace_aggregate_snap(handle) < 0)
|
251
|
+
rb_raise(eDtraceException, dtrace_errmsg(handle, dtrace_errno(handle)));
|
252
|
+
|
253
|
+
return Qnil;
|
254
|
+
}
|
255
|
+
|
256
|
+
/*
|
257
|
+
* Clear the current aggregate snapshot.
|
258
|
+
*/
|
259
|
+
VALUE dtrace_hdl_aggregate_clear(VALUE self)
|
260
|
+
{
|
261
|
+
dtrace_hdl_t *handle;
|
262
|
+
|
263
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
264
|
+
dtrace_aggregate_clear(handle);
|
265
|
+
return Qnil;
|
266
|
+
}
|
267
|
+
|
268
|
+
/*
|
269
|
+
* Return the most recent DTrace error.
|
270
|
+
*/
|
271
|
+
VALUE dtrace_hdl_error(VALUE self)
|
272
|
+
{
|
273
|
+
dtrace_hdl_t *handle;
|
274
|
+
const char *error_string;
|
275
|
+
|
276
|
+
Data_Get_Struct(self, dtrace_hdl_t, handle);
|
277
|
+
error_string = dtrace_errmsg(handle, dtrace_errno(handle));
|
278
|
+
return rb_str_new2(error_string);
|
279
|
+
}
|
280
|
+
|