rbtrace 0.2.7 → 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/README.md +6 -2
- data/bin/rbtrace +154 -41
- data/ext/rbtrace.c +80 -11
- data/rbtrace.gemspec +4 -4
- data/tracers/activerecord.tracer +1 -0
- data/tracers/eventmachine.tracer +27 -0
- data/tracers/io.tracer +4 -0
- data/tracers/redis.tracer +1 -0
- metadata +8 -4
data/README.md
CHANGED
@@ -156,8 +156,12 @@ rbtrace works on ruby 1.8 and 1.9, running on linux or mac osx.
|
|
156
156
|
|
157
157
|
* switch ipc to [msgpack](https://github.com/dhotson/msgpack/tree/master/c) instead of csv
|
158
158
|
* add triggers to start tracing slow methods only inside another method
|
159
|
+
* syntax check expressions before adding them
|
160
|
+
* add special expressions for method args (_arg0_, _arguments_)
|
159
161
|
* optimize local variable lookup to avoid instance_eval
|
160
|
-
*
|
161
|
-
*
|
162
|
+
* run process via bin/rbtrace (to trace rubygems and bootup time)
|
163
|
+
* let bin/rbtrace attach to multiple pids
|
164
|
+
* how to select on multiple msgrcv() targets?
|
165
|
+
* prefix pid to output in multiple pid mode
|
162
166
|
* investigate mach_msg on osx since msgget(2) has hard kernel limits
|
163
167
|
|
data/bin/rbtrace
CHANGED
@@ -142,9 +142,11 @@ class RBTracer
|
|
142
142
|
raise ArgumentError, 'pid is not listening for messages, did you `require "rbtrace"`'
|
143
143
|
end
|
144
144
|
|
145
|
+
@klasses = {}
|
146
|
+
@methods = {}
|
145
147
|
@tracers = Hash.new{ |h,k|
|
146
148
|
h[k] = {
|
147
|
-
:
|
149
|
+
:query => nil,
|
148
150
|
:times => [],
|
149
151
|
:names => [],
|
150
152
|
:exprs => {},
|
@@ -152,12 +154,16 @@ class RBTracer
|
|
152
154
|
:arglist => false
|
153
155
|
}
|
154
156
|
}
|
155
|
-
@nesting = 0
|
157
|
+
@max_nesting = @nesting = 0
|
156
158
|
@last_tracer = nil
|
159
|
+
|
157
160
|
@out = STDOUT
|
158
161
|
@prefix = ' '
|
162
|
+
|
159
163
|
@show_time = false
|
160
164
|
@show_duration = true
|
165
|
+
|
166
|
+
attach
|
161
167
|
end
|
162
168
|
|
163
169
|
# Watch for method calls slower than a threshold.
|
@@ -184,6 +190,7 @@ class RBTracer
|
|
184
190
|
def add(methods)
|
185
191
|
Array(methods).each do |func|
|
186
192
|
func = func.strip
|
193
|
+
next if func.empty?
|
187
194
|
|
188
195
|
if func =~ /^(.+)\((.+)\)$/
|
189
196
|
func, args = $1, $2
|
@@ -198,6 +205,18 @@ class RBTracer
|
|
198
205
|
end
|
199
206
|
end
|
200
207
|
|
208
|
+
# Attach to the process.
|
209
|
+
#
|
210
|
+
# Returns nothing.
|
211
|
+
def attach
|
212
|
+
send_cmd("attach,#{Process.pid}")
|
213
|
+
if wait_for{ @attached == true }
|
214
|
+
STDERR.puts "*** attached to process #{pid}"
|
215
|
+
else
|
216
|
+
raise ArgumentError, 'process already being traced?'
|
217
|
+
end
|
218
|
+
end
|
219
|
+
|
201
220
|
# Detach from the traced process.
|
202
221
|
#
|
203
222
|
# Returns nothing.
|
@@ -209,13 +228,16 @@ class RBTracer
|
|
209
228
|
|
210
229
|
puts
|
211
230
|
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
231
|
+
if wait_for{ @attached == false }
|
232
|
+
puts
|
233
|
+
STDERR.puts "*** detached from process #{pid}"
|
234
|
+
else
|
235
|
+
puts
|
236
|
+
STDERR.puts "*** could not detach cleanly from process #{pid}"
|
218
237
|
end
|
238
|
+
rescue Errno::EINVAL, Errno::EIDRM
|
239
|
+
puts
|
240
|
+
STDERR.puts "*** process #{pid} is gone"
|
219
241
|
end
|
220
242
|
|
221
243
|
# Process events from the traced process.
|
@@ -224,26 +246,62 @@ class RBTracer
|
|
224
246
|
def recv_loop
|
225
247
|
while true
|
226
248
|
# block until a message arrives
|
227
|
-
|
249
|
+
process_line(recv_cmd)
|
228
250
|
|
229
|
-
#
|
230
|
-
|
231
|
-
|
232
|
-
|
233
|
-
|
234
|
-
|
251
|
+
# process any remaining messages
|
252
|
+
recv_lines
|
253
|
+
end
|
254
|
+
rescue Errno::EINVAL, Errno::EIDRM
|
255
|
+
# process went away
|
256
|
+
end
|
235
257
|
|
236
|
-
|
237
|
-
|
238
|
-
|
258
|
+
# Process events from the traced process, without blocking if
|
259
|
+
# there is nothing to do. This is a useful way to drain the buffer
|
260
|
+
# so messages do not accumulate in kernel land.
|
261
|
+
#
|
262
|
+
# Returns nothing.
|
263
|
+
def recv_lines
|
264
|
+
50.times do
|
265
|
+
break unless line = recv_cmd(false)
|
266
|
+
process_line(line)
|
239
267
|
end
|
240
268
|
end
|
241
269
|
|
242
270
|
private
|
243
271
|
|
272
|
+
# Process incoming events until either a timeout or a condition becomes true.
|
273
|
+
#
|
274
|
+
# time - The Fixnum timeout in seconds.
|
275
|
+
# block - The Block that is checked every 50ms until it returns true.
|
276
|
+
#
|
277
|
+
# Returns true when the condition was met, or false on a timeout.
|
278
|
+
def wait_for(time=5)
|
279
|
+
wait = 0.05 # polling interval
|
280
|
+
|
281
|
+
(time/wait).to_i.times do
|
282
|
+
begin
|
283
|
+
recv_lines
|
284
|
+
sleep(wait)
|
285
|
+
time -= wait
|
286
|
+
|
287
|
+
return true if yield
|
288
|
+
rescue Interrupt
|
289
|
+
STDERR.puts "*** waiting to detach cleanly (#{time.to_i}s left)"
|
290
|
+
retry
|
291
|
+
end
|
292
|
+
end
|
293
|
+
|
294
|
+
false
|
295
|
+
end
|
296
|
+
|
244
297
|
def send_cmd(msg)
|
245
|
-
|
298
|
+
begin
|
299
|
+
MsgQ::EventMsg.send_cmd(@qo, msg)
|
300
|
+
rescue Errno::EINTR
|
301
|
+
retry
|
302
|
+
end
|
246
303
|
Process.kill 'URG', @pid
|
304
|
+
recv_lines
|
247
305
|
end
|
248
306
|
|
249
307
|
def recv_cmd(block=true)
|
@@ -263,19 +321,45 @@ class RBTracer
|
|
263
321
|
end
|
264
322
|
|
265
323
|
def process_line(line)
|
266
|
-
time, event,
|
324
|
+
time, event, _id, *args = line.strip.split(',')
|
267
325
|
time = time.to_i
|
268
|
-
id =
|
326
|
+
id = _id.to_i
|
327
|
+
|
328
|
+
case event
|
329
|
+
when 'attached'
|
330
|
+
@attached = true
|
331
|
+
if id != Process.pid
|
332
|
+
STDERR.puts "*** process #{pid} is already being traced"
|
333
|
+
exit!(-1)
|
334
|
+
end
|
335
|
+
return
|
336
|
+
|
337
|
+
when 'detached'
|
338
|
+
@attached = false
|
339
|
+
return
|
340
|
+
end
|
341
|
+
|
342
|
+
if !@attached
|
343
|
+
STDERR.puts "*** got #{event} before attaching"
|
344
|
+
return
|
345
|
+
end
|
346
|
+
|
269
347
|
tracer = @tracers[id] if id > -1
|
270
348
|
|
271
349
|
case event
|
350
|
+
when 'mid'
|
351
|
+
@methods[id.to_i] = args.first
|
352
|
+
|
353
|
+
when 'klass'
|
354
|
+
@klasses[_id.to_i(16)] = args.first
|
355
|
+
|
272
356
|
when 'add'
|
273
357
|
if id == -1
|
274
358
|
puts line
|
275
359
|
else
|
276
|
-
|
360
|
+
query = args.first
|
277
361
|
@tracers.delete(id)
|
278
|
-
@tracers[id][:
|
362
|
+
@tracers[id][:query] = query
|
279
363
|
end
|
280
364
|
|
281
365
|
when 'remove'
|
@@ -294,7 +378,8 @@ class RBTracer
|
|
294
378
|
end
|
295
379
|
|
296
380
|
when 'exprval'
|
297
|
-
expr_id
|
381
|
+
expr_id = args.shift
|
382
|
+
val = args.join(',')
|
298
383
|
expr_id = expr_id.to_i
|
299
384
|
expr = tracer[:exprs][expr_id]
|
300
385
|
|
@@ -311,8 +396,9 @@ class RBTracer
|
|
311
396
|
when 'call','ccall'
|
312
397
|
method, is_singleton, klass = *args
|
313
398
|
is_singleton = (is_singleton == '1')
|
399
|
+
klass = @klasses[klass.to_i(16)]
|
314
400
|
name = klass ? "#{klass}#{ is_singleton ? '.' : '#' }" : ''
|
315
|
-
name += method
|
401
|
+
name += @methods[method.to_i] || '(unknown)'
|
316
402
|
|
317
403
|
tracer[:times] << time
|
318
404
|
tracer[:names] << name
|
@@ -331,6 +417,7 @@ class RBTracer
|
|
331
417
|
print name
|
332
418
|
|
333
419
|
@nesting += 1
|
420
|
+
@max_nesting = @nesting if @nesting > @max_nesting
|
334
421
|
@last_tracer = tracer
|
335
422
|
tracer[:last] = name
|
336
423
|
|
@@ -351,7 +438,12 @@ class RBTracer
|
|
351
438
|
print name
|
352
439
|
end
|
353
440
|
print ' <%f>' % (diff/1_000_000.0) if @show_duration
|
354
|
-
|
441
|
+
|
442
|
+
if @nesting == 0 and @max_nesting > 1
|
443
|
+
# unless tracer == @last_tracer and @last_tracer[:last] == name
|
444
|
+
puts
|
445
|
+
# end
|
446
|
+
end
|
355
447
|
end
|
356
448
|
|
357
449
|
tracer[:arglist] = false
|
@@ -362,8 +454,9 @@ class RBTracer
|
|
362
454
|
diff = diff.to_i
|
363
455
|
|
364
456
|
is_singleton = (is_singleton == '1')
|
457
|
+
klass = @klasses[klass.to_i(16)]
|
365
458
|
name = klass ? "#{klass}#{ is_singleton ? '.' : '#' }" : ''
|
366
|
-
name += method
|
459
|
+
name += @methods[method.to_i] || '(unknown)'
|
367
460
|
|
368
461
|
print @prefix*nesting if nesting > 0
|
369
462
|
print name
|
@@ -390,7 +483,7 @@ class RBTracer
|
|
390
483
|
parser = Trollop::Parser.new do
|
391
484
|
version <<-EOS
|
392
485
|
rbtrace: like strace, but for ruby code
|
393
|
-
version 0.2.
|
486
|
+
version 0.2.8
|
394
487
|
(c) 2011 Aman Gupta (tmm1)
|
395
488
|
http://github.com/tmm1/rbtrace
|
396
489
|
EOS
|
@@ -416,6 +509,10 @@ Tracers:
|
|
416
509
|
rbtrace --slow=250 # trace method calls slower than 250ms
|
417
510
|
rbtrace --methods a b c # trace calls to given methods
|
418
511
|
|
512
|
+
rbtrace -c io # trace common input/output functions
|
513
|
+
rbtrace -c eventmachine # trace common eventmachine functions
|
514
|
+
rbtrace -c my.tracer # trace all methods listed in my.tracer
|
515
|
+
|
419
516
|
Method Selectors:
|
420
517
|
|
421
518
|
sleep # any instance or class method named sleep
|
@@ -469,6 +566,10 @@ EOS
|
|
469
566
|
:type => String,
|
470
567
|
:short => '-o'
|
471
568
|
|
569
|
+
opt :append,
|
570
|
+
"append to output file instead of overwriting",
|
571
|
+
:short => '-a'
|
572
|
+
|
472
573
|
opt :prefix,
|
473
574
|
"prefix nested method calls with N spaces",
|
474
575
|
:default => 2,
|
@@ -476,7 +577,7 @@ EOS
|
|
476
577
|
|
477
578
|
opt :config,
|
478
579
|
"config file",
|
479
|
-
:type =>
|
580
|
+
:type => :strings,
|
480
581
|
:short => '-c'
|
481
582
|
end
|
482
583
|
|
@@ -485,6 +586,10 @@ EOS
|
|
485
586
|
parser.parse(ARGV)
|
486
587
|
end
|
487
588
|
|
589
|
+
if out = opts[:output]
|
590
|
+
file = File.open(out, opts[:append] ? 'a+' : 'w')
|
591
|
+
end
|
592
|
+
|
488
593
|
slow = nil
|
489
594
|
firehose = nil
|
490
595
|
methods = nil
|
@@ -499,15 +604,25 @@ EOS
|
|
499
604
|
methods = opts[:methods]
|
500
605
|
|
501
606
|
elsif opts[:config_given]
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
607
|
+
methods = []
|
608
|
+
|
609
|
+
Array(opts[:config]).each do |config|
|
610
|
+
file = [
|
611
|
+
config,
|
612
|
+
File.expand_path("../../tracers/#{config}.tracer",__FILE__)
|
613
|
+
].find{ |f| File.exists?(f) }
|
614
|
+
|
615
|
+
unless file
|
616
|
+
parser.die :config, '(file does not exist)'
|
507
617
|
end
|
508
618
|
|
509
|
-
|
510
|
-
|
619
|
+
File.readlines(file).each do |line|
|
620
|
+
line.strip!
|
621
|
+
next if line =~ /^#/
|
622
|
+
next if line.empty?
|
623
|
+
|
624
|
+
methods << line
|
625
|
+
end
|
511
626
|
end
|
512
627
|
|
513
628
|
else
|
@@ -520,7 +635,7 @@ EOS
|
|
520
635
|
begin
|
521
636
|
tracer = RBTracer.new(opts[:pid])
|
522
637
|
rescue ArgumentError => e
|
523
|
-
parser.die :pid, "
|
638
|
+
parser.die :pid, "(#{e.message})"
|
524
639
|
end
|
525
640
|
|
526
641
|
if slow
|
@@ -531,8 +646,8 @@ EOS
|
|
531
646
|
tracer.add(methods)
|
532
647
|
end
|
533
648
|
|
534
|
-
if
|
535
|
-
tracer.out =
|
649
|
+
if file
|
650
|
+
tracer.out = file
|
536
651
|
end
|
537
652
|
|
538
653
|
tracer.prefix = ' ' * opts[:prefix]
|
@@ -540,14 +655,12 @@ EOS
|
|
540
655
|
tracer.show_time = opts[:start_time]
|
541
656
|
|
542
657
|
begin
|
543
|
-
STDERR.puts "*** attached to process #{tracer.pid}"
|
544
658
|
tracer.recv_loop
|
545
659
|
rescue Interrupt
|
546
660
|
end
|
547
661
|
ensure
|
548
662
|
if tracer
|
549
663
|
tracer.detach
|
550
|
-
STDERR.puts "*** detached from process #{tracer.pid}"
|
551
664
|
end
|
552
665
|
end
|
553
666
|
end
|
data/ext/rbtrace.c
CHANGED
@@ -20,9 +20,11 @@
|
|
20
20
|
#include <env.h>
|
21
21
|
#include <intern.h>
|
22
22
|
#include <node.h>
|
23
|
+
#include <st.h>
|
23
24
|
#define rb_sourcefile() (ruby_current_node ? ruby_current_node->nd_file : 0)
|
24
25
|
#define rb_sourceline() (ruby_current_node ? nd_line(ruby_current_node) : 0)
|
25
26
|
#else
|
27
|
+
#include <ruby/st.h>
|
26
28
|
// this is a nasty hack, and will probably break on anything except 1.9.2p136
|
27
29
|
int rb_thread_method_id_and_class(void *th, ID *idp, VALUE *klassp);
|
28
30
|
RUBY_EXTERN void *ruby_current_thread;
|
@@ -63,14 +65,17 @@ struct rbtracer_t {
|
|
63
65
|
};
|
64
66
|
typedef struct rbtracer_t rbtracer_t;
|
65
67
|
|
66
|
-
|
67
68
|
struct event_msg {
|
68
69
|
long mtype;
|
69
70
|
char buf[BUF_SIZE];
|
70
71
|
};
|
71
72
|
|
72
|
-
|
73
73
|
static struct {
|
74
|
+
st_table *mid_tbl;
|
75
|
+
st_table *klass_tbl;
|
76
|
+
|
77
|
+
pid_t attached_pid;
|
78
|
+
|
74
79
|
bool installed;
|
75
80
|
|
76
81
|
bool firehose;
|
@@ -89,6 +94,11 @@ static struct {
|
|
89
94
|
int mqi_id;
|
90
95
|
}
|
91
96
|
rbtracer = {
|
97
|
+
.mid_tbl = NULL,
|
98
|
+
.klass_tbl = NULL,
|
99
|
+
|
100
|
+
.attached_pid = 0,
|
101
|
+
|
92
102
|
.installed = false,
|
93
103
|
|
94
104
|
.firehose = false,
|
@@ -110,7 +120,7 @@ rbtracer = {
|
|
110
120
|
if (false) {\
|
111
121
|
fprintf(stderr, "%" PRIu64 "," format, usec, __VA_ARGS__);\
|
112
122
|
fprintf(stderr, "\n");\
|
113
|
-
} else if (rbtracer.mqo_id != -1) {\
|
123
|
+
} else if (rbtracer.mqo_id != -1 && rbtracer.attached_pid) {\
|
114
124
|
struct event_msg msg;\
|
115
125
|
int ret = -1, n = 0;\
|
116
126
|
\
|
@@ -119,8 +129,9 @@ rbtracer = {
|
|
119
129
|
\
|
120
130
|
for (n=0; n<10 && ret==-1; n++)\
|
121
131
|
ret = msgsnd(rbtracer.mqo_id, &msg, sizeof(msg)-sizeof(long), IPC_NOWAIT);\
|
122
|
-
|
123
|
-
|
132
|
+
\
|
133
|
+
if (ret == -1 && rbtracer.mqo_id != -1 && errno != EINVAL) {\
|
134
|
+
fprintf(stderr, "msgsnd(%d): %s\n", rbtracer.mqo_id, strerror(errno));\
|
124
135
|
struct msqid_ds stat;\
|
125
136
|
msgctl(rbtracer.mqo_id, IPC_STAT, &stat);\
|
126
137
|
fprintf(stderr, "cbytes: %lu, qbytes: %lu, qnum: %lu\n", stat.msg_cbytes, stat.msg_qbytes, stat.msg_qnum);\
|
@@ -128,6 +139,34 @@ rbtracer = {
|
|
128
139
|
}\
|
129
140
|
} while (0)
|
130
141
|
|
142
|
+
static inline void
|
143
|
+
SEND_NAMES(ID mid, VALUE klass)
|
144
|
+
{
|
145
|
+
if (!rbtracer.mid_tbl)
|
146
|
+
rbtracer.mid_tbl = st_init_numtable();
|
147
|
+
|
148
|
+
if (!st_is_member(rbtracer.mid_tbl, mid)) {
|
149
|
+
st_insert(rbtracer.mid_tbl, (st_data_t)mid, (st_data_t)1);
|
150
|
+
SEND_EVENT(
|
151
|
+
"mid,%lu,%s",
|
152
|
+
mid,
|
153
|
+
rb_id2name(mid)
|
154
|
+
);
|
155
|
+
}
|
156
|
+
|
157
|
+
if (!rbtracer.klass_tbl)
|
158
|
+
rbtracer.klass_tbl = st_init_numtable();
|
159
|
+
|
160
|
+
if (!st_is_member(rbtracer.klass_tbl, klass)) {
|
161
|
+
st_insert(rbtracer.klass_tbl, (st_data_t)klass, (st_data_t)1);
|
162
|
+
SEND_EVENT(
|
163
|
+
"klass,%p,%s",
|
164
|
+
(void*)klass,
|
165
|
+
rb_class2name(klass)
|
166
|
+
);
|
167
|
+
}
|
168
|
+
}
|
169
|
+
|
131
170
|
static void
|
132
171
|
#ifdef RUBY_VM
|
133
172
|
event_hook(rb_event_flag_t event, VALUE data, VALUE self, ID mid, VALUE klass)
|
@@ -191,14 +230,15 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
191
230
|
}
|
192
231
|
|
193
232
|
if (diff > rbtracer.threshold * 1e3) {
|
233
|
+
SEND_NAMES(mid, singleton ? self : klass);
|
194
234
|
SEND_EVENT(
|
195
|
-
"%s,-1,%" PRIu64 ",%d,%
|
235
|
+
"%s,-1,%" PRIu64 ",%d,%lu,%d,%p",
|
196
236
|
event == RUBY_EVENT_RETURN ? "slow" : "cslow",
|
197
237
|
diff,
|
198
238
|
rbtracer.num_calls,
|
199
|
-
|
239
|
+
mid,
|
200
240
|
singleton,
|
201
|
-
|
241
|
+
(void*)(singleton ? self : klass)
|
202
242
|
);
|
203
243
|
}
|
204
244
|
|
@@ -234,13 +274,14 @@ event_hook(rb_event_t event, NODE *node, VALUE self, ID mid, VALUE klass)
|
|
234
274
|
switch (event) {
|
235
275
|
case RUBY_EVENT_CALL:
|
236
276
|
case RUBY_EVENT_C_CALL:
|
277
|
+
SEND_NAMES(mid, singleton ? self : klass);
|
237
278
|
SEND_EVENT(
|
238
|
-
"%s,%d,%
|
279
|
+
"%s,%d,%lu,%d,%p",
|
239
280
|
event == RUBY_EVENT_CALL ? "call" : "ccall",
|
240
281
|
tracer ? tracer->id : 255, // hax
|
241
|
-
|
282
|
+
mid,
|
242
283
|
singleton,
|
243
|
-
|
284
|
+
(void*)(singleton ? self : klass)
|
244
285
|
);
|
245
286
|
|
246
287
|
if (tracer && tracer->num_exprs) {
|
@@ -385,6 +426,14 @@ rbtracer_remove_all()
|
|
385
426
|
rbtracer_remove(NULL, i);
|
386
427
|
}
|
387
428
|
}
|
429
|
+
|
430
|
+
if (rbtracer.mid_tbl)
|
431
|
+
st_free_table(rbtracer.mid_tbl);
|
432
|
+
rbtracer.mid_tbl = NULL;
|
433
|
+
|
434
|
+
if (rbtracer.klass_tbl)
|
435
|
+
st_free_table(rbtracer.klass_tbl);
|
436
|
+
rbtracer.klass_tbl = NULL;
|
388
437
|
}
|
389
438
|
|
390
439
|
static int
|
@@ -625,7 +674,27 @@ sigurg(int signal)
|
|
625
674
|
} else if (0 == strncmp("unwatch", msg.buf, 7)) {
|
626
675
|
rbtracer_unwatch();
|
627
676
|
|
677
|
+
} else if (0 == strncmp("attach,", msg.buf, 7)) {
|
678
|
+
pid_t pid = 0;
|
679
|
+
|
680
|
+
query = msg.buf + 7;
|
681
|
+
if (query && *query)
|
682
|
+
pid = (pid_t)atoi(query);
|
683
|
+
|
684
|
+
if (pid && rbtracer.attached_pid == 0)
|
685
|
+
rbtracer.attached_pid = pid;
|
686
|
+
|
687
|
+
SEND_EVENT(
|
688
|
+
"attached,%u",
|
689
|
+
rbtracer.attached_pid
|
690
|
+
);
|
691
|
+
|
628
692
|
} else if (0 == strncmp("detach", msg.buf, 6)) {
|
693
|
+
SEND_EVENT(
|
694
|
+
"detached,%u",
|
695
|
+
rbtracer.attached_pid
|
696
|
+
);
|
697
|
+
rbtracer.attached_pid = 0;
|
629
698
|
rbtracer_remove_all();
|
630
699
|
|
631
700
|
}
|
data/rbtrace.gemspec
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Gem::Specification.new do |s|
|
2
2
|
s.name = 'rbtrace'
|
3
|
-
s.version = '0.2.
|
3
|
+
s.version = '0.2.8'
|
4
4
|
s.homepage = 'http://github.com/tmm1/rbtrace'
|
5
5
|
|
6
|
-
s.authors =
|
7
|
-
s.email =
|
6
|
+
s.authors = 'Aman Gupta'
|
7
|
+
s.email = 'aman@tmm1.net'
|
8
8
|
|
9
9
|
s.files = `git ls-files`.split("\n")
|
10
|
-
s.extensions =
|
10
|
+
s.extensions = 'ext/extconf.rb'
|
11
11
|
|
12
12
|
s.bindir = 'bin'
|
13
13
|
s.executables << 'rbtrace'
|
@@ -0,0 +1 @@
|
|
1
|
+
ActiveRecord::ConnectionAdapters::MysqlAdapter#execute(sql)
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# incoming events
|
2
|
+
post_init(@signature)
|
3
|
+
connection_completed(@signature)
|
4
|
+
receive_data(@signature)
|
5
|
+
unbind(@signature)
|
6
|
+
|
7
|
+
# connection methods
|
8
|
+
EM::Connection#send_data(@signature, data.size, data[0..5])
|
9
|
+
EM::Connection#send_datagram(@signature, data.size, data[0..5])
|
10
|
+
EM::Connection#start_tls(@signature, args)
|
11
|
+
EM::Connection#close_connection(@signature, after_writing)
|
12
|
+
EM::Connection#proxy_incoming_to(@signature, conn, bufsize)
|
13
|
+
EM::Connection#(@signature)
|
14
|
+
|
15
|
+
# timers
|
16
|
+
EM.add_periodic_timer(args, block)
|
17
|
+
EM.add_timer(args, block)
|
18
|
+
EM.cancel_timer(timer_or_sig,@timers.size)
|
19
|
+
|
20
|
+
# event loop
|
21
|
+
EM.stop
|
22
|
+
|
23
|
+
# connections
|
24
|
+
EM.start_server(server, port, handler)
|
25
|
+
EM.stop_server
|
26
|
+
EM.connect(server, port, handler)
|
27
|
+
EM.reconnect(server, port, handler)
|
data/tracers/io.tracer
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
Redis::Client#process(commands)
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rbtrace
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 7
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
-
|
10
|
-
version: 0.2.
|
9
|
+
- 8
|
10
|
+
version: 0.2.8
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Aman Gupta
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2011-02-
|
18
|
+
date: 2011-02-17 00:00:00 -08:00
|
19
19
|
default_executable:
|
20
20
|
dependencies:
|
21
21
|
- !ruby/object:Gem::Dependency
|
@@ -70,6 +70,10 @@ files:
|
|
70
70
|
- rbtrace.gemspec
|
71
71
|
- server.rb
|
72
72
|
- test.sh
|
73
|
+
- tracers/activerecord.tracer
|
74
|
+
- tracers/eventmachine.tracer
|
75
|
+
- tracers/io.tracer
|
76
|
+
- tracers/redis.tracer
|
73
77
|
has_rdoc: true
|
74
78
|
homepage: http://github.com/tmm1/rbtrace
|
75
79
|
licenses: []
|