rbtrace 0.2.7 → 0.2.8
Sign up to get free protection for your applications and to get access to all the features.
- 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: []
|