traceview 3.1.0 → 3.2.1

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.
@@ -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