traceview 3.1.0 → 3.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,631 @@
1
+ # Copyright (c) 2015 AppNeta, Inc.
2
+ # All rights reserved.
3
+ require 'minitest_helper'
4
+
5
+ # TV Method profiling only supports Ruby 1.9.3 or greater. For earlier Ruby versions
6
+ # see the legacy method profiling in lib/traceview/legacy_method_profiling.rb.
7
+ if RUBY_VERSION >= '1.9.3'
8
+ describe "TraceViewMethodProfiling" do
9
+ before do
10
+ clear_all_traces
11
+ # Conditionally Undefine TestWorker
12
+ # http://stackoverflow.com/questions/11503558/how-to-undefine-class-in-ruby
13
+ Object.send(:remove_const, :TestKlass) if defined?(TestKlass)
14
+ Object.send(:remove_const, :TestModule) if defined?(TestModule)
15
+ end
16
+
17
+ it 'should be loaded, defined and ready' do
18
+ defined?(::TraceView::MethodProfiling).wont_match nil
19
+ assert_equal true, TraceView::API.respond_to?(:profile_method), "has profile_method method"
20
+ end
21
+
22
+ it 'should return false for bad arguments' do
23
+ class TestKlass
24
+ def do_work
25
+ return 687
26
+ end
27
+ end
28
+
29
+ # Bad first param
30
+ rv = TraceView::API.profile_method('blah', :do_work)
31
+ assert_equal false, rv, "Return value must be false for bad args"
32
+
33
+ # Bad first param
34
+ rv = TraceView::API.profile_method(TestKlass, 52)
35
+ assert_equal false, rv, "Return value must be false for bad args"
36
+ end
37
+
38
+ it 'should profile class instance methods' do
39
+ class TestKlass
40
+ def do_work
41
+ return 687
42
+ end
43
+ end
44
+
45
+ result = TraceView::API.profile_method(TestKlass, :do_work)
46
+ assert_equal true, result, "profile_method return value must be true"
47
+
48
+ result = nil
49
+
50
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
51
+ # Call the profiled class method
52
+ result = TestKlass.new.do_work
53
+ end
54
+
55
+ traces = get_all_traces
56
+ traces.count.must_equal 4
57
+ assert valid_edges?(traces), "Trace edge validation"
58
+
59
+ validate_outer_layers(traces, 'method_profiling')
60
+
61
+ result.must_equal 687
62
+
63
+ kvs = {}
64
+ kvs["Label"] = 'profile_entry'
65
+ kvs["Language"] = "ruby"
66
+ kvs["ProfileName"] = "do_work"
67
+ kvs["Class"] = "TestKlass"
68
+ kvs["MethodName"] = "do_work"
69
+
70
+ validate_event_keys(traces[1], kvs)
71
+
72
+ traces[1].key?("Layer").must_equal false
73
+ traces[1].key?("Module").must_equal false
74
+ traces[1].key?("File").must_equal true
75
+ traces[1].key?("LineNumber").must_equal true
76
+
77
+ kvs.clear
78
+ kvs["Label"] = "profile_exit"
79
+ kvs["Language"] = "ruby"
80
+ kvs["ProfileName"] = "do_work"
81
+
82
+ validate_event_keys(traces[2], kvs)
83
+ traces[2].key?("Layer").must_equal false
84
+ end
85
+
86
+ it 'should not double profile already profiled methods' do
87
+ class TestKlass
88
+ def do_work
89
+ return 687
90
+ end
91
+ end
92
+
93
+ # Attempt to double profile
94
+ rv = TraceView::API.profile_method(TestKlass, :do_work)
95
+ assert_equal true, rv, "Return value must be true"
96
+
97
+ rv = TraceView::API.profile_method(TestKlass, :do_work)
98
+ assert_equal false, rv, "Return value must be false"
99
+
100
+ with_tv = TestKlass.instance_methods.select{ |m| m == :do_work_with_traceview }
101
+ assert_equal with_tv.count, 1, ":do_work_with_traceview method count"
102
+
103
+ without_tv = TestKlass.instance_methods.select{ |m| m == :do_work_without_traceview }
104
+ assert_equal without_tv.count, 1, ":do_work_without_traceview method count"
105
+ end
106
+
107
+ it 'should error out for non-existent methods' do
108
+ class TestKlass
109
+ def do_work
110
+ return 687
111
+ end
112
+ end
113
+
114
+ rv = TraceView::API.profile_method(TestKlass, :does_not_exist)
115
+ assert_equal false, rv, "Return value must be false"
116
+
117
+ with_tv = TestKlass.instance_methods.select{ |m| m == :does_not_exit_with_traceview }
118
+ assert_equal with_tv.count, 0, ":does_not_exit_with_traceview method count"
119
+
120
+ without_tv = TestKlass.instance_methods.select{ |m| m == :does_not_exit_without_traceview }
121
+ assert_equal without_tv.count, 0, ":does_not_exit_without_traceview method count"
122
+ end
123
+
124
+ it 'should trace class singleton methods' do
125
+ class TestKlass
126
+ def self.do_work
127
+ return 687
128
+ end
129
+ end
130
+
131
+ result = TraceView::API.profile_method(TestKlass, :do_work)
132
+ assert_equal true, result, "profile_method return value must be true"
133
+
134
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
135
+ result = TestKlass.do_work
136
+ end
137
+
138
+ traces = get_all_traces
139
+ traces.count.must_equal 4
140
+ assert valid_edges?(traces), "Trace edge validation"
141
+
142
+ validate_outer_layers(traces, 'method_profiling')
143
+
144
+ result.must_equal 687
145
+
146
+ kvs = {}
147
+ kvs["Label"] = 'profile_entry'
148
+ kvs["Language"] = "ruby"
149
+ kvs["ProfileName"] = "do_work"
150
+ kvs["Class"] = "TestKlass"
151
+ kvs["MethodName"] = "do_work"
152
+
153
+ validate_event_keys(traces[1], kvs)
154
+
155
+ traces[1].key?("Layer").must_equal false
156
+ traces[1].key?("Module").must_equal false
157
+ traces[1].key?("File").must_equal true
158
+ traces[1].key?("LineNumber").must_equal true
159
+
160
+ kvs.clear
161
+ kvs["Label"] = "profile_exit"
162
+ kvs["Language"] = "ruby"
163
+ kvs["ProfileName"] = "do_work"
164
+
165
+ validate_event_keys(traces[2], kvs)
166
+ traces[2].key?("Layer").must_equal false
167
+ end
168
+
169
+ it 'should trace class private instance methods' do
170
+ class TestKlass
171
+ private
172
+ def do_work_privately
173
+ return 687
174
+ end
175
+ end
176
+
177
+ result = TraceView::API.profile_method(TestKlass, :do_work_privately)
178
+ assert_equal true, result, "profile_method return value must be true"
179
+
180
+ result = nil
181
+
182
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
183
+ # Call the profiled class method
184
+ result = TestKlass.new.do_work_privately
185
+ end
186
+
187
+ traces = get_all_traces
188
+ traces.count.must_equal 4
189
+ assert valid_edges?(traces), "Trace edge validation"
190
+
191
+ validate_outer_layers(traces, 'method_profiling')
192
+
193
+ result.must_equal 687
194
+
195
+ kvs = {}
196
+ kvs["Label"] = 'profile_entry'
197
+ kvs["Language"] = "ruby"
198
+ kvs["ProfileName"] = "do_work_privately"
199
+ kvs["Class"] = "TestKlass"
200
+ kvs["MethodName"] = "do_work_privately"
201
+
202
+ validate_event_keys(traces[1], kvs)
203
+
204
+ traces[1].key?("Layer").must_equal false
205
+ traces[1].key?("Module").must_equal false
206
+ traces[1].key?("File").must_equal true
207
+ traces[1].key?("LineNumber").must_equal true
208
+
209
+ kvs.clear
210
+ kvs["Label"] = "profile_exit"
211
+ kvs["Language"] = "ruby"
212
+ kvs["ProfileName"] = "do_work_privately"
213
+
214
+ validate_event_keys(traces[2], kvs)
215
+ traces[2].key?("Layer").must_equal false
216
+ end
217
+
218
+ it 'should trace class private singleton methods' do
219
+ class TestKlass
220
+ private
221
+ def self.do_work_privately
222
+ return 687
223
+ end
224
+ end
225
+
226
+ result = TraceView::API.profile_method(TestKlass, :do_work_privately)
227
+ assert_equal true, result, "profile_method return value must be true"
228
+
229
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
230
+ result = TestKlass.do_work_privately
231
+ end
232
+
233
+ traces = get_all_traces
234
+ traces.count.must_equal 4
235
+ assert valid_edges?(traces), "Trace edge validation"
236
+
237
+ validate_outer_layers(traces, 'method_profiling')
238
+
239
+ result.must_equal 687
240
+
241
+ kvs = {}
242
+ kvs["Label"] = 'profile_entry'
243
+ kvs["Language"] = "ruby"
244
+ kvs["ProfileName"] = "do_work_privately"
245
+ kvs["Class"] = "TestKlass"
246
+ kvs["MethodName"] = "do_work_privately"
247
+
248
+ validate_event_keys(traces[1], kvs)
249
+
250
+ traces[1].key?("Layer").must_equal false
251
+ traces[1].key?("Module").must_equal false
252
+ traces[1].key?("File").must_equal true
253
+ traces[1].key?("LineNumber").must_equal true
254
+
255
+ kvs.clear
256
+ kvs["Label"] = "profile_exit"
257
+ kvs["Language"] = "ruby"
258
+ kvs["ProfileName"] = "do_work_privately"
259
+
260
+ validate_event_keys(traces[2], kvs)
261
+ traces[2].key?("Layer").must_equal false
262
+ end
263
+
264
+ it 'should trace module singleton methods' do
265
+ module TestModule
266
+ def self.do_work
267
+ return 687
268
+ end
269
+ end
270
+
271
+ result = TraceView::API.profile_method(TestModule, :do_work)
272
+ assert_equal true, result, "profile_method return value must be true"
273
+
274
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
275
+ result = TestModule.do_work
276
+ end
277
+
278
+ traces = get_all_traces
279
+ traces.count.must_equal 4
280
+ assert valid_edges?(traces), "Trace edge validation"
281
+
282
+ validate_outer_layers(traces, 'method_profiling')
283
+
284
+ result.must_equal 687
285
+
286
+ kvs = {}
287
+ kvs["Label"] = 'profile_entry'
288
+ kvs["Language"] = "ruby"
289
+ kvs["ProfileName"] = "do_work"
290
+ kvs["Module"] = "TestModule"
291
+ kvs["MethodName"] = "do_work"
292
+
293
+ validate_event_keys(traces[1], kvs)
294
+
295
+ traces[1].key?("Layer").must_equal false
296
+ traces[1].key?("Class").must_equal false
297
+ traces[1].key?("File").must_equal true
298
+ traces[1].key?("LineNumber").must_equal true
299
+
300
+ kvs.clear
301
+ kvs["Label"] = "profile_exit"
302
+ kvs["Language"] = "ruby"
303
+ kvs["ProfileName"] = "do_work"
304
+
305
+ validate_event_keys(traces[2], kvs)
306
+ traces[2].key?("Layer").must_equal false
307
+ end
308
+
309
+ it 'should trace module instance methods' do
310
+ module TestModule
311
+ def do_work
312
+ return 687
313
+ end
314
+ end
315
+
316
+ # Profile the module before including in a class
317
+ result = TraceView::API.profile_method(TestModule, :do_work)
318
+ assert_equal true, result, "profile_method return value must be true"
319
+
320
+ class TestKlass
321
+ include TestModule
322
+ end
323
+
324
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
325
+ result = TestKlass.new.do_work
326
+ end
327
+
328
+ traces = get_all_traces
329
+ traces.count.must_equal 4
330
+ assert valid_edges?(traces), "Trace edge validation"
331
+
332
+ validate_outer_layers(traces, 'method_profiling')
333
+
334
+ result.must_equal 687
335
+
336
+ kvs = {}
337
+ kvs["Label"] = 'profile_entry'
338
+ kvs["Language"] = "ruby"
339
+ kvs["ProfileName"] = "do_work"
340
+ kvs["Module"] = "TestModule"
341
+ kvs["MethodName"] = "do_work"
342
+
343
+ validate_event_keys(traces[1], kvs)
344
+
345
+ traces[1].key?("Layer").must_equal false
346
+ traces[1].key?("Class").must_equal false
347
+ traces[1].key?("File").must_equal true
348
+ traces[1].key?("LineNumber").must_equal true
349
+
350
+ kvs.clear
351
+ kvs["Label"] = "profile_exit"
352
+ kvs["Language"] = "ruby"
353
+ kvs["ProfileName"] = "do_work"
354
+
355
+ validate_event_keys(traces[2], kvs)
356
+ traces[2].key?("Layer").must_equal false
357
+ end
358
+
359
+ it 'should profile methods that use blocks' do
360
+ class TestKlass
361
+ def self.do_work(&block)
362
+ yield
363
+ end
364
+ end
365
+
366
+ result = TraceView::API.profile_method(TestKlass, :do_work)
367
+ assert_equal true, result, "profile_method return value must be true"
368
+
369
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
370
+ result = TestKlass.do_work do
371
+ 787
372
+ end
373
+ end
374
+
375
+ traces = get_all_traces
376
+ traces.count.must_equal 4
377
+ assert valid_edges?(traces), "Trace edge validation"
378
+
379
+ validate_outer_layers(traces, 'method_profiling')
380
+
381
+ result.must_equal 787
382
+
383
+ kvs = {}
384
+ kvs["Label"] = 'profile_entry'
385
+ kvs["Language"] = "ruby"
386
+ kvs["ProfileName"] = "do_work"
387
+ kvs["Class"] = "TestKlass"
388
+ kvs["MethodName"] = "do_work"
389
+
390
+ validate_event_keys(traces[1], kvs)
391
+
392
+ traces[1].key?("Layer").must_equal false
393
+ traces[1].key?("Module").must_equal false
394
+ traces[1].key?("File").must_equal true
395
+ traces[1].key?("LineNumber").must_equal true
396
+
397
+ kvs.clear
398
+ kvs["Label"] = "profile_exit"
399
+ kvs["Language"] = "ruby"
400
+ kvs["ProfileName"] = "do_work"
401
+
402
+ validate_event_keys(traces[2], kvs)
403
+ traces[2].key?("Layer").must_equal false
404
+ end
405
+
406
+ it 'should not store arguments and return value by default' do
407
+ class TestKlass
408
+ def do_work(blah = {})
409
+ return 687
410
+ end
411
+ end
412
+
413
+ result = TraceView::API.profile_method(TestKlass, :do_work)
414
+ assert_equal true, result, "profile_method return value must be true"
415
+
416
+ result = nil
417
+
418
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
419
+ # Call the profiled class method
420
+ result = TestKlass.new.do_work(:ok => :blue)
421
+ end
422
+
423
+ traces = get_all_traces
424
+ traces.count.must_equal 4
425
+ assert valid_edges?(traces), "Trace edge validation"
426
+
427
+ validate_outer_layers(traces, 'method_profiling')
428
+
429
+ result.must_equal 687
430
+
431
+ kvs = {}
432
+ kvs["Label"] = 'profile_entry'
433
+ kvs["Language"] = "ruby"
434
+ kvs["ProfileName"] = "do_work"
435
+ kvs["Class"] = "TestKlass"
436
+ kvs["MethodName"] = "do_work"
437
+
438
+ validate_event_keys(traces[1], kvs)
439
+
440
+ traces[1].key?("Layer").must_equal false
441
+ traces[1].key?("Module").must_equal false
442
+ traces[1].key?("File").must_equal true
443
+ traces[1].key?("LineNumber").must_equal true
444
+
445
+ kvs.clear
446
+ kvs["Label"] = "profile_exit"
447
+ kvs["Language"] = "ruby"
448
+ kvs["ProfileName"] = "do_work"
449
+
450
+ validate_event_keys(traces[2], kvs)
451
+ traces[2].key?("Layer").must_equal false
452
+
453
+ traces[2].key?("Arguments").must_equal false
454
+ traces[2].key?("ReturnValue").must_equal false
455
+ end
456
+
457
+ it 'should store arguments and return value when asked' do
458
+ class TestKlass
459
+ def do_work(blah = {})
460
+ return 687
461
+ end
462
+ end
463
+
464
+ opts = {}
465
+ opts[:arguments] = true
466
+ opts[:result] = true
467
+
468
+ result = TraceView::API.profile_method(TestKlass, :do_work, opts)
469
+ assert_equal true, result, "profile_method return value must be true"
470
+
471
+ result = nil
472
+
473
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
474
+ # Call the profiled class method
475
+ result = TestKlass.new.do_work(:ok => :blue)
476
+ end
477
+
478
+ traces = get_all_traces
479
+ traces.count.must_equal 4
480
+ assert valid_edges?(traces), "Trace edge validation"
481
+
482
+ validate_outer_layers(traces, 'method_profiling')
483
+
484
+ result.must_equal 687
485
+
486
+ kvs = {}
487
+ kvs["Label"] = 'profile_entry'
488
+ kvs["Language"] = "ruby"
489
+ kvs["ProfileName"] = "do_work"
490
+ kvs["Class"] = "TestKlass"
491
+ kvs["MethodName"] = "do_work"
492
+
493
+ validate_event_keys(traces[1], kvs)
494
+
495
+ traces[1].key?("Layer").must_equal false
496
+ traces[1].key?("Module").must_equal false
497
+ traces[1].key?("File").must_equal true
498
+ traces[1].key?("LineNumber").must_equal true
499
+
500
+ kvs.clear
501
+ kvs["Label"] = "profile_exit"
502
+ kvs["Language"] = "ruby"
503
+ kvs["ProfileName"] = "do_work"
504
+
505
+ validate_event_keys(traces[2], kvs)
506
+ traces[2].key?("Layer").must_equal false
507
+
508
+ traces[2].key?("Arguments").must_equal true
509
+ traces[2]["Arguments"].must_equal "[{:ok=>:blue}]"
510
+
511
+ traces[2].key?("ReturnValue").must_equal true
512
+ traces[2]["ReturnValue"].must_equal 687
513
+ end
514
+
515
+ it 'should not report backtraces by default' do
516
+ class TestKlass
517
+ def do_work(blah = {})
518
+ return 687
519
+ end
520
+ end
521
+
522
+ result = TraceView::API.profile_method(TestKlass, :do_work)
523
+ assert_equal true, result, "profile_method return value must be true"
524
+
525
+ result = nil
526
+
527
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
528
+ # Call the profiled class method
529
+ result = TestKlass.new.do_work(:ok => :blue)
530
+ end
531
+
532
+ traces = get_all_traces
533
+ traces.count.must_equal 4
534
+ assert valid_edges?(traces), "Trace edge validation"
535
+
536
+ validate_outer_layers(traces, 'method_profiling')
537
+
538
+ result.must_equal 687
539
+
540
+ kvs = {}
541
+ kvs["Label"] = 'profile_entry'
542
+ kvs["Language"] = "ruby"
543
+ kvs["ProfileName"] = "do_work"
544
+ kvs["Class"] = "TestKlass"
545
+ kvs["MethodName"] = "do_work"
546
+
547
+ validate_event_keys(traces[1], kvs)
548
+
549
+ traces.each { |t|
550
+ t.key?("Backtrace").must_equal false, "shoudn't have backtrace"
551
+ }
552
+ end
553
+
554
+ it 'should report backtraces when requested' do
555
+ class TestKlass
556
+ def do_work(blah = {})
557
+ return 687
558
+ end
559
+ end
560
+
561
+ opts = { :backtrace => true }
562
+ result = TraceView::API.profile_method(TestKlass, :do_work, opts)
563
+ assert_equal true, result, "profile_method return value must be true"
564
+
565
+ result = nil
566
+
567
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
568
+ # Call the profiled class method
569
+ result = TestKlass.new.do_work(:ok => :blue)
570
+ end
571
+
572
+ traces = get_all_traces
573
+ traces.count.must_equal 4
574
+ assert valid_edges?(traces), "Trace edge validation"
575
+
576
+ validate_outer_layers(traces, 'method_profiling')
577
+
578
+ result.must_equal 687
579
+
580
+ kvs = {}
581
+ kvs["Label"] = 'profile_entry'
582
+ kvs["Language"] = "ruby"
583
+ kvs["ProfileName"] = "do_work"
584
+ kvs["Class"] = "TestKlass"
585
+ kvs["MethodName"] = "do_work"
586
+
587
+ validate_event_keys(traces[1], kvs)
588
+
589
+ traces[1].key?("Backtrace").must_equal true, "should report a backtrace"
590
+ end
591
+
592
+ it 'should report extra KVs when requested' do
593
+ class TestKlass
594
+ def do_work(blah = {})
595
+ return 687
596
+ end
597
+ end
598
+
599
+ opts = { :backtrace => true }
600
+ result = TraceView::API.profile_method(TestKlass, :do_work, opts, :another => "value")
601
+ assert_equal true, result, "profile_method return value must be true"
602
+
603
+ result = nil
604
+
605
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
606
+ # Call the profiled class method
607
+ result = TestKlass.new.do_work(:ok => :blue)
608
+ end
609
+
610
+ traces = get_all_traces
611
+ traces.count.must_equal 4
612
+ assert valid_edges?(traces), "Trace edge validation"
613
+
614
+ validate_outer_layers(traces, 'method_profiling')
615
+
616
+ result.must_equal 687
617
+
618
+ kvs = {}
619
+ kvs["Label"] = 'profile_entry'
620
+ kvs["Language"] = "ruby"
621
+ kvs["ProfileName"] = "do_work"
622
+ kvs["Class"] = "TestKlass"
623
+ kvs["MethodName"] = "do_work"
624
+ kvs["another"] = "value"
625
+
626
+ validate_event_keys(traces[1], kvs)
627
+
628
+ traces[1].key?("Backtrace").must_equal true, "should report a backtrace"
629
+ end
630
+ end
631
+ end
@@ -64,11 +64,10 @@ class FerroController < ActionController::Metal
64
64
  def world
65
65
  render :text => "Hello world!"
66
66
  end
67
-
68
- include TraceViewMethodProfiling
69
- profile_method :world, 'world'
70
67
  end
71
68
 
69
+ TraceView::API.profile_method(FerroController, :world)
70
+
72
71
  Rails40MetalStack.initialize!
73
72
 
74
73
  Thread.new do
@@ -99,31 +99,31 @@ describe "TraceView::Config" do
99
99
  # equivalents should follow suit.
100
100
 
101
101
  #
102
- # :include_url_query_params
102
+ # :include_remote_url_params
103
103
  #
104
104
 
105
105
  # Check defaults
106
- TraceView::Config[:include_url_query_params].must_equal true
106
+ TraceView::Config[:include_remote_url_params].must_equal true
107
107
  http_clients.each do |i|
108
108
  TraceView::Config[i][:log_args].must_equal true
109
109
  end
110
110
 
111
111
  # Check obedience
112
- TraceView::Config[:include_url_query_params] = false
112
+ TraceView::Config[:include_remote_url_params] = false
113
113
  http_clients.each do |i|
114
114
  TraceView::Config[i][:log_args].must_equal false
115
115
  end
116
116
 
117
117
  #
118
- # :include_remote_url_params
118
+ # :include_url_query_params
119
119
  #
120
120
 
121
121
  # Check default
122
- TraceView::Config[:include_remote_url_params].must_equal true
122
+ TraceView::Config[:include_url_query_params].must_equal true
123
123
  TraceView::Config[:rack][:log_args].must_equal true
124
124
 
125
125
  # Check obedience
126
- TraceView::Config[:include_remote_url_params] = false
126
+ TraceView::Config[:include_url_query_params] = false
127
127
  TraceView::Config[:rack][:log_args].must_equal false
128
128
 
129
129
  # Restore the previous values