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.
- data/History.txt +21 -0
- data/Manifest.txt +86 -19
- data/README.txt +48 -6
- data/Rakefile +61 -20
- data/examples/scsi.rb +1 -1
- data/ext/dof/Makefile +154 -0
- data/ext/dof/constants.c +57 -0
- data/ext/dof/dof.h +56 -0
- data/ext/dof/dof_api.c +58 -0
- data/ext/dof/dof_helper.c +82 -0
- data/ext/dof/extconf.rb +4 -0
- data/ext/dof/file.c +90 -0
- data/ext/dof/generator.c +9 -0
- data/ext/dof/header.c +79 -0
- data/ext/dof/mkmf.log +10 -0
- data/ext/dof/parser.c +415 -0
- data/ext/dof/parser.h +10 -0
- data/ext/dof/section.c +312 -0
- data/ext/dtrace_aggdata.c +2 -2
- data/ext/dtrace_api.c +46 -34
- data/ext/dtrace_api.h +31 -7
- data/ext/dtrace_bufdata.c +3 -3
- data/ext/dtrace_hdl.c +66 -3
- data/ext/dtrace_probedata.c +4 -4
- data/ext/{dtrace_probe.c → dtrace_probedesc.c} +7 -7
- data/ext/extconf.rb +25 -0
- data/ext/i386-darwin/dtrace_probe.c +278 -0
- data/ext/i386-solaris/dtrace_probe.c +225 -0
- data/ext/stubs.txt +78 -0
- data/lib/dtrace.rb +34 -13
- data/lib/dtrace/aggregate.rb +40 -0
- data/lib/dtrace/aggregateset.rb +19 -0
- data/lib/dtrace/consumer.rb +174 -0
- data/lib/dtrace/data.rb +82 -0
- data/lib/dtrace/dof.rb +8 -0
- data/lib/dtrace/dof/file.rb +64 -0
- data/lib/dtrace/dof/section.rb +75 -0
- data/lib/dtrace/dof/section/strtab.rb +28 -0
- data/lib/{dtraceprintfrecord.rb → dtrace/printfrecord.rb} +4 -2
- data/lib/dtrace/probe.rb +3 -6
- data/lib/dtrace/probedata.rb +23 -0
- data/lib/dtrace/probedesc.rb +15 -0
- data/lib/dtrace/provider.rb +190 -169
- data/lib/dtrace/provider/klass.rb +33 -0
- data/lib/dtrace/provider/probedef.rb +24 -0
- data/lib/{dtracerecord.rb → dtrace/record.rb} +4 -2
- data/lib/{dtracestackrecord.rb → dtrace/stackrecord.rb} +10 -8
- data/lib/dtrace/version.rb +9 -0
- data/lib/dtraceconsumer.rb +3 -167
- data/plugin/dtrace/lib/dtracer.rb +4 -4
- data/test/apple-dof +0 -0
- data/test/disabled_probe_effect.txt +19 -0
- data/test/dof +0 -0
- data/test/dof2 +0 -0
- data/test/test_disabled_probe_effect.rb +56 -0
- data/test/test_dof_generator.rb +142 -0
- data/test/test_dof_helper.rb +106 -0
- data/test/test_dof_parser.rb +27 -0
- data/test/test_dof_providers.rb +278 -0
- data/test/test_dof_strtabs.rb +98 -0
- data/test/test_dtrace.rb +67 -1
- data/test/test_dtrace_aggregates.rb +5 -5
- data/test/test_dtrace_drops_errors.rb +5 -5
- data/test/test_dtrace_probe.rb +385 -0
- data/test/test_dtrace_probes.rb +414 -0
- data/test/test_dtrace_processes.rb +2 -2
- data/test/test_dtrace_profile.rb +12 -12
- data/test/test_dtrace_provider.rb +138 -0
- data/test/test_dtrace_repeat.rb +1 -1
- data/test/test_dtrace_rubyprobe.rb +3 -1
- data/test/test_dtrace_typefilter.rb +9 -9
- data/test/test_legacy_consumer.rb +56 -0
- metadata +112 -71
- data/lib/dtrace/provider/osx.rb +0 -25
- data/lib/dtrace/provider/solaris.rb +0 -29
- data/lib/dtraceaggregate.rb +0 -37
- data/lib/dtraceaggregateset.rb +0 -17
- data/lib/dtracedata.rb +0 -80
- data/lib/dtraceprobe.rb +0 -13
- data/lib/dtraceprobedata.rb +0 -21
- data/test/test_dynusdt.rb +0 -135
data/ext/stubs.txt
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
disassembly of C probe stub:
|
2
|
+
|
3
|
+
/* 3. void probe8(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7) { */
|
4
|
+
/* <Function: probe8> */
|
5
|
+
/* [ 3] 805133c: pushl %ebp */
|
6
|
+
/* [ 3] 805133d: movl %esp,%ebp */
|
7
|
+
/* [ 3] 805133f: subl $8,%esp */
|
8
|
+
/* 4. TEST_TEST_INT_INT_INT_INT_INT_INT_INT_INT_PROBE(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); */
|
9
|
+
/* [ 4] 8051342: pushl 0x24(%ebp) */
|
10
|
+
/* [ 4] 8051345: pushl 0x20(%ebp) */
|
11
|
+
/* [ 4] 8051348: pushl 0x1c(%ebp) */
|
12
|
+
/* [ 4] 805134b: pushl 0x18(%ebp) */
|
13
|
+
/* [ 4] 805134e: pushl 0x14(%ebp) */
|
14
|
+
/* [ 4] 8051351: pushl 0x10(%ebp) */
|
15
|
+
/* [ 4] 8051354: pushl 0xc(%ebp) */
|
16
|
+
/* [ 4] 8051357: pushl 8(%ebp) */
|
17
|
+
/* [ 4] 805135a: nop */
|
18
|
+
/* [ 4] 805135b: nop */
|
19
|
+
/* [ 4] 805135c: nop */
|
20
|
+
/* [ 4] 805135d: nop */
|
21
|
+
/* [ 4] 805135e: nop */
|
22
|
+
/* [ 4] 805135f: addl $0x20,%esp */
|
23
|
+
/* 5. } */
|
24
|
+
/* [ 5] 8051362: leave */
|
25
|
+
/* [ 5] 8051363: ret */
|
26
|
+
|
27
|
+
Corresponding binary:
|
28
|
+
|
29
|
+
/* 1330 55 89 e5 83 .....^[. ....U... */
|
30
|
+
/* 1340 ec 08 ff 75 24 ff 75 20 ff 75 1c ff 75 18 ff 75 ...u$.u .u..u..u */
|
31
|
+
/* 1350 14 ff 75 10 ff 75 0c ff 75 08 90 90 90 90 90 83 ..u..u.. u....... */
|
32
|
+
/* 1360 c4 20 c9 c3 */
|
33
|
+
|
34
|
+
Hand-built 8-arg stub:
|
35
|
+
|
36
|
+
/* char insns[FUNC_SIZE] = */
|
37
|
+
/* { */
|
38
|
+
/* 0x55, 0x89, 0xe5, 0x83, 0xec, 0x08, */
|
39
|
+
/* 0xff, 0x75, 0x24, */
|
40
|
+
/* 0xff, 0x75, 0x20, */
|
41
|
+
/* 0xff, 0x75, 0x1c, */
|
42
|
+
/* 0xff, 0x75, 0x18, */
|
43
|
+
/* 0xff, 0x75, 0x14, */
|
44
|
+
/* 0xff, 0x75, 0x10, */
|
45
|
+
/* 0xff, 0x75, 0x0c, */
|
46
|
+
/* 0xff, 0x75, 0x08, */
|
47
|
+
/* 0x90, 0x90, 0x90, 0x90, 0x90, */
|
48
|
+
/* 0x83, 0xc4, 0x20, */
|
49
|
+
/* 0xc9, 0xc3 */
|
50
|
+
/* }; */
|
51
|
+
|
52
|
+
disassembly of is_enabled function:
|
53
|
+
|
54
|
+
21. int is_enabled(void) {
|
55
|
+
<Function: is_enabled>
|
56
|
+
[21] 805142a: pushl %ebp
|
57
|
+
[21] 805142b: movl %esp,%ebp
|
58
|
+
[21] 805142d: subl $8,%esp
|
59
|
+
22. return TEST_TEST_PROBE_ENABLED() ? 1 : 0;
|
60
|
+
[22] 8051430: xorl %eax,%eax
|
61
|
+
[22] 8051432: nop
|
62
|
+
[22] 8051433: nop
|
63
|
+
[22] 8051434: nop
|
64
|
+
[22] 8051435: movl %eax,-4(%ebp)
|
65
|
+
[22] 8051438: cmpl $0,-4(%ebp)
|
66
|
+
[22] 805143c: setne %al
|
67
|
+
[22] 805143f: movzbl %al,%eax
|
68
|
+
[22] 8051442: movl %eax,-4(%ebp)
|
69
|
+
[22] 8051445: movl -4(%ebp),%eax
|
70
|
+
23. }
|
71
|
+
[23] 8051448: leave
|
72
|
+
[23] 8051449: ret
|
73
|
+
|
74
|
+
Binary:
|
75
|
+
|
76
|
+
55 89 e5 83 ec 08 ....... ..U.....
|
77
|
+
1430 33 c0 90 90 90 89 45 fc 83 7d fc 00 0f 95 c0 0f 3.....E. .}......
|
78
|
+
1440 b6 c0 89 45 fc 8b 45 fc c9 c3
|
data/lib/dtrace.rb
CHANGED
@@ -4,15 +4,17 @@
|
|
4
4
|
#
|
5
5
|
|
6
6
|
require 'dtrace_api'
|
7
|
-
require '
|
7
|
+
require 'dtrace/record'
|
8
|
+
require 'dtrace/consumer'
|
8
9
|
require 'dtraceconsumer'
|
9
|
-
require '
|
10
|
-
require '
|
11
|
-
require '
|
12
|
-
require '
|
13
|
-
require '
|
14
|
-
require '
|
15
|
-
require '
|
10
|
+
require 'dtrace/aggregate'
|
11
|
+
require 'dtrace/aggregateset'
|
12
|
+
require 'dtrace/probedata'
|
13
|
+
require 'dtrace/probedesc'
|
14
|
+
require 'dtrace/stackrecord'
|
15
|
+
require 'dtrace/printfrecord'
|
16
|
+
require 'dtrace/data'
|
17
|
+
require 'dtrace/version'
|
16
18
|
|
17
19
|
# A DTrace handle. Provides methods for inspecting available probes,
|
18
20
|
# compiling and running programs, and for setting up callbacks to
|
@@ -22,10 +24,10 @@ require 'dtracedata'
|
|
22
24
|
#
|
23
25
|
# * Create a handle with Dtrace.new
|
24
26
|
# * Set options
|
25
|
-
# * Compile the program, possibly inspecting the return
|
27
|
+
# * Compile the program, possibly inspecting the return Dtrace::ProgramInfo
|
26
28
|
# * Execute the program
|
27
29
|
# * Start tracing
|
28
|
-
# * Consume data, either directly by setting up callbacks, or using a
|
30
|
+
# * Consume data, either directly by setting up callbacks, or using a Dtrace::Consumer.
|
29
31
|
# * Stop tracing
|
30
32
|
#
|
31
33
|
# === Listing probes
|
@@ -57,18 +59,37 @@ require 'dtracedata'
|
|
57
59
|
# t.go
|
58
60
|
# p.continue
|
59
61
|
#
|
60
|
-
# c =
|
62
|
+
# c = Dtrace::Consumer.new(t)
|
61
63
|
# c.consume do |d|
|
62
64
|
# ..
|
63
65
|
# end
|
64
66
|
|
65
67
|
class Dtrace
|
66
|
-
VERSION = '0.0.6'
|
67
|
-
|
68
68
|
STATUS_NONE = 0
|
69
69
|
STATUS_OKAY = 1
|
70
70
|
STATUS_EXITED = 2
|
71
71
|
STATUS_FILLED = 3
|
72
72
|
STATUS_STOPPED = 4
|
73
|
+
|
74
|
+
# Yields each probe on the system, optionally matching against a
|
75
|
+
# probe specification:
|
76
|
+
#
|
77
|
+
# e.g.
|
78
|
+
# syscall::: -> all probes in the syscall provider
|
79
|
+
# pid123:::return -> all return probes in pid 123.
|
80
|
+
#
|
81
|
+
def each_probe(match=nil, &block)
|
82
|
+
if match
|
83
|
+
parts = match.split(':', 4)
|
84
|
+
begin
|
85
|
+
each_probe_match(*parts, &block)
|
86
|
+
rescue ArgumentError => e
|
87
|
+
raise Dtrace::Exception.new("each_probe: probe specification expected (e.g. 'provider:::')")
|
88
|
+
end
|
89
|
+
else
|
90
|
+
each_probe_all(&block)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
73
94
|
end
|
74
95
|
|
@@ -0,0 +1,40 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
# Represents an aggregation record built from a series of
|
7
|
+
# DtraceAggData records.
|
8
|
+
#
|
9
|
+
# Intended to to built up by calling +add_record+ repeatedly with
|
10
|
+
# Dtrace::AggData objects until a completed Dtrace::Aggregate is
|
11
|
+
# returned. (until a complete record is available, +add_record+
|
12
|
+
# returns nil).
|
13
|
+
#
|
14
|
+
# See consumer.rb for an example of this.
|
15
|
+
class Dtrace
|
16
|
+
class Aggregate
|
17
|
+
attr_reader :value, :tuple
|
18
|
+
|
19
|
+
# Create an empty Dtrace::Aggregate: use +add_record+ to add data.
|
20
|
+
def initialize
|
21
|
+
@tuple = Array.new
|
22
|
+
end
|
23
|
+
|
24
|
+
# Add a Dtrace::AggData record to this aggregate. Returns nil until it
|
25
|
+
# receives a record of aggtype "last", when it returns the complete
|
26
|
+
# Dtrace::Aggregate.
|
27
|
+
def add_record(r)
|
28
|
+
case r.aggtype
|
29
|
+
when "tuple"
|
30
|
+
@tuple << r.value
|
31
|
+
when "value"
|
32
|
+
@value = r.value
|
33
|
+
when "last"
|
34
|
+
return self
|
35
|
+
end
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
|
39
|
+
end
|
40
|
+
end
|
@@ -0,0 +1,174 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
|
6
|
+
# A Dtrace::Consumer provides access to the data produced by the running
|
7
|
+
# D program. Having compiled and executed a D program, you typically
|
8
|
+
# create a Dtrace::Consumer, 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 Dtrace::Data 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 = Dtrace::Consumer.new(t)
|
33
|
+
# c.consume_once do |d|
|
34
|
+
# # handle Dtrace::Data objects
|
35
|
+
# # ...
|
36
|
+
# # get bored:
|
37
|
+
# c.finish
|
38
|
+
# end
|
39
|
+
|
40
|
+
class Dtrace
|
41
|
+
class Consumer
|
42
|
+
|
43
|
+
def initialize(t)
|
44
|
+
@t = t
|
45
|
+
@done = false
|
46
|
+
@types = []
|
47
|
+
|
48
|
+
@drophandler = nil
|
49
|
+
@errhandler = nil
|
50
|
+
end
|
51
|
+
|
52
|
+
private
|
53
|
+
|
54
|
+
# The consumer callbacks:
|
55
|
+
#
|
56
|
+
# DtraceRecDesc -> rec_consumer
|
57
|
+
# DtraceProbeData -> probe_consumer
|
58
|
+
# DtraceBufData -> buf_consumer
|
59
|
+
#
|
60
|
+
# We expect a sequence of calls to these procs, and we accumulate
|
61
|
+
# data in the @curr Dtrace::Data based on this:
|
62
|
+
#
|
63
|
+
# Dtrace::ProbeData (initial callback for a probe firing)
|
64
|
+
# Dtrace::RecDesc
|
65
|
+
# ...
|
66
|
+
# Dtrace::RecDesc = nil (end of data)
|
67
|
+
#
|
68
|
+
|
69
|
+
def rec_consumer(block)
|
70
|
+
proc do |rec|
|
71
|
+
if rec
|
72
|
+
@curr.add_recdata(rec)
|
73
|
+
else
|
74
|
+
@curr.finish
|
75
|
+
block.call(@curr)
|
76
|
+
@curr = Dtrace::Data.new(@types)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
def probe_consumer
|
82
|
+
proc do |probe|
|
83
|
+
@curr.add_probedata(probe)
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def buf_consumer
|
88
|
+
proc do |buf|
|
89
|
+
@curr.add_bufdata(buf)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def filter_types(types)
|
94
|
+
@types = types
|
95
|
+
@curr = Dtrace::Data.new(types)
|
96
|
+
end
|
97
|
+
|
98
|
+
public
|
99
|
+
|
100
|
+
# Provide a proc which will be executed when a drop record is
|
101
|
+
# received.
|
102
|
+
def drophandler(&block)
|
103
|
+
@drophandler = block
|
104
|
+
@t.drop_consumer(proc do |drop|
|
105
|
+
if @drophandler
|
106
|
+
@drophandler.call(drop)
|
107
|
+
end
|
108
|
+
end)
|
109
|
+
end
|
110
|
+
|
111
|
+
# Provide a proc which will be executed when an error record is
|
112
|
+
# received.
|
113
|
+
def errhandler(&block)
|
114
|
+
@errhandler = block
|
115
|
+
@t.err_consumer(proc do |err|
|
116
|
+
if @errhandler
|
117
|
+
@errhandler.call(err)
|
118
|
+
end
|
119
|
+
end)
|
120
|
+
end
|
121
|
+
|
122
|
+
# Signals that the client wishes to stop consuming trace data.
|
123
|
+
def finish
|
124
|
+
@t.stop
|
125
|
+
@done = true
|
126
|
+
end
|
127
|
+
|
128
|
+
# Waits for data from the D program, and yields the records returned
|
129
|
+
# to the block given. Returns when the D program exits.
|
130
|
+
#
|
131
|
+
# Pass a list of classes to restrict the types of data returned,
|
132
|
+
# from:
|
133
|
+
#
|
134
|
+
# * DtraceRecord
|
135
|
+
# * DtracePrintfRecord
|
136
|
+
# * DtraceAggregateSet
|
137
|
+
# * DtraceStackRecord
|
138
|
+
#
|
139
|
+
def consume(*types, &block)
|
140
|
+
filter_types(types)
|
141
|
+
@t.buf_consumer(buf_consumer)
|
142
|
+
begin
|
143
|
+
while(true) do
|
144
|
+
@t.sleep
|
145
|
+
work = @t.work(probe_consumer, rec_consumer(block))
|
146
|
+
if (@done || work > 0)
|
147
|
+
break
|
148
|
+
end
|
149
|
+
end
|
150
|
+
ensure
|
151
|
+
@t.stop
|
152
|
+
@t.work(probe_consumer)
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
# Yields the data waiting from the current program, then returns.
|
157
|
+
#
|
158
|
+
# Pass a list of classes to restrict the types of data returned,
|
159
|
+
# from:
|
160
|
+
#
|
161
|
+
# * DtraceRecord
|
162
|
+
# * DtracePrintfRecord
|
163
|
+
# * DtraceAggregateSet
|
164
|
+
# * DtraceStackRecord
|
165
|
+
#
|
166
|
+
def consume_once(*types, &block)
|
167
|
+
filter_types(types)
|
168
|
+
@t.buf_consumer(buf_consumer)
|
169
|
+
@t.stop
|
170
|
+
@t.work(probe_consumer, rec_consumer(block))
|
171
|
+
end
|
172
|
+
|
173
|
+
end
|
174
|
+
end
|
data/lib/dtrace/data.rb
ADDED
@@ -0,0 +1,82 @@
|
|
1
|
+
#
|
2
|
+
# Ruby-Dtrace
|
3
|
+
# (c) 2007 Chris Andrews <chris@nodnol.org>
|
4
|
+
#
|
5
|
+
# The object returned from a consumer when a probe fires. Accumulates
|
6
|
+
# records from the callbacks, and is yielded when the data is complete.
|
7
|
+
class Dtrace
|
8
|
+
class Data
|
9
|
+
attr_reader :data
|
10
|
+
attr_reader :probe
|
11
|
+
attr_reader :cpu, :indent, :prefix, :flow
|
12
|
+
|
13
|
+
def initialize(types)
|
14
|
+
@types = types
|
15
|
+
@data = []
|
16
|
+
@curraggset = nil
|
17
|
+
@curragg = nil
|
18
|
+
end
|
19
|
+
|
20
|
+
def add_data(d)
|
21
|
+
if @types.length == 0 || @types.include?(d.class)
|
22
|
+
@data << d
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def finish
|
27
|
+
if @curraggset
|
28
|
+
add_data(@curraggset)
|
29
|
+
@curraggset = nil
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_recdata(rec)
|
34
|
+
if @curraggset
|
35
|
+
add_data(@curraggset)
|
36
|
+
@curraggset = nil
|
37
|
+
end
|
38
|
+
if rec.action == "printa"
|
39
|
+
@curraggset = Dtrace::AggregateSet.new
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def add_probedata(probedata)
|
44
|
+
probedata.each_record do |p|
|
45
|
+
add_data(p)
|
46
|
+
end
|
47
|
+
|
48
|
+
# Record the probe that fired, and CPU/indent/prefix/flow
|
49
|
+
@probe = probedata.probe
|
50
|
+
@cpu = probedata.cpu
|
51
|
+
@indent = probedata.indent
|
52
|
+
@prefix = probedata.prefix
|
53
|
+
@flow = probedata.flow
|
54
|
+
end
|
55
|
+
|
56
|
+
def add_bufdata(buf)
|
57
|
+
r = buf.record
|
58
|
+
# buf records can be empty (trace();)
|
59
|
+
if r
|
60
|
+
case r.class.to_s
|
61
|
+
when Dtrace::StackRecord.to_s
|
62
|
+
add_data(r)
|
63
|
+
when Dtrace::Record.to_s
|
64
|
+
add_data(r)
|
65
|
+
when Dtrace::PrintfRecord.to_s
|
66
|
+
add_data(r)
|
67
|
+
when Dtrace::AggData.to_s
|
68
|
+
if @curragg == nil
|
69
|
+
@curragg = Dtrace::Aggregate.new
|
70
|
+
end
|
71
|
+
if agg = @curragg.add_record(r)
|
72
|
+
if @curraggset
|
73
|
+
@curraggset.add_aggregate(@curragg)
|
74
|
+
end
|
75
|
+
@curragg = nil
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
end
|
82
|
+
end
|