traceview 3.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (137) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +10 -0
  3. data/.rubocop.yml +5 -0
  4. data/.travis.yml +58 -0
  5. data/Appraisals +10 -0
  6. data/CHANGELOG.md +490 -0
  7. data/CONFIG.md +16 -0
  8. data/Gemfile +95 -0
  9. data/LICENSE +199 -0
  10. data/README.md +380 -0
  11. data/Rakefile +109 -0
  12. data/examples/DNT.md +35 -0
  13. data/examples/carrying_context.rb +225 -0
  14. data/examples/instrumenting_metal_controller.rb +8 -0
  15. data/examples/puma_on_heroku_config.rb +17 -0
  16. data/examples/tracing_async_threads.rb +125 -0
  17. data/examples/tracing_background_jobs.rb +52 -0
  18. data/examples/tracing_forked_processes.rb +100 -0
  19. data/examples/unicorn_on_heroku_config.rb +28 -0
  20. data/ext/oboe_metal/extconf.rb +61 -0
  21. data/ext/oboe_metal/noop/noop.c +7 -0
  22. data/ext/oboe_metal/src/bson/bson.h +221 -0
  23. data/ext/oboe_metal/src/bson/platform_hacks.h +91 -0
  24. data/ext/oboe_metal/src/oboe.h +275 -0
  25. data/ext/oboe_metal/src/oboe.hpp +352 -0
  26. data/ext/oboe_metal/src/oboe_wrap.cxx +3886 -0
  27. data/ext/oboe_metal/tests/test.rb +11 -0
  28. data/gemfiles/mongo.gemfile +33 -0
  29. data/gemfiles/moped.gemfile +33 -0
  30. data/get_version.rb +5 -0
  31. data/init.rb +4 -0
  32. data/lib/joboe_metal.rb +206 -0
  33. data/lib/oboe.rb +7 -0
  34. data/lib/oboe/README +2 -0
  35. data/lib/oboe/backward_compatibility.rb +59 -0
  36. data/lib/oboe/inst/rack.rb +11 -0
  37. data/lib/oboe_metal.rb +151 -0
  38. data/lib/rails/generators/traceview/install_generator.rb +76 -0
  39. data/lib/rails/generators/traceview/templates/traceview_initializer.rb +159 -0
  40. data/lib/traceview.rb +62 -0
  41. data/lib/traceview/api.rb +18 -0
  42. data/lib/traceview/api/layerinit.rb +51 -0
  43. data/lib/traceview/api/logging.rb +209 -0
  44. data/lib/traceview/api/memcache.rb +31 -0
  45. data/lib/traceview/api/profiling.rb +50 -0
  46. data/lib/traceview/api/tracing.rb +135 -0
  47. data/lib/traceview/api/util.rb +121 -0
  48. data/lib/traceview/base.rb +225 -0
  49. data/lib/traceview/config.rb +238 -0
  50. data/lib/traceview/frameworks/grape.rb +97 -0
  51. data/lib/traceview/frameworks/padrino.rb +64 -0
  52. data/lib/traceview/frameworks/padrino/templates.rb +58 -0
  53. data/lib/traceview/frameworks/rails.rb +145 -0
  54. data/lib/traceview/frameworks/rails/helpers/rum/rum_ajax_header.js.erb +5 -0
  55. data/lib/traceview/frameworks/rails/helpers/rum/rum_footer.js.erb +1 -0
  56. data/lib/traceview/frameworks/rails/helpers/rum/rum_header.js.erb +3 -0
  57. data/lib/traceview/frameworks/rails/inst/action_controller.rb +216 -0
  58. data/lib/traceview/frameworks/rails/inst/action_view.rb +56 -0
  59. data/lib/traceview/frameworks/rails/inst/action_view_2x.rb +54 -0
  60. data/lib/traceview/frameworks/rails/inst/action_view_30.rb +48 -0
  61. data/lib/traceview/frameworks/rails/inst/active_record.rb +24 -0
  62. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql.rb +43 -0
  63. data/lib/traceview/frameworks/rails/inst/connection_adapters/mysql2.rb +28 -0
  64. data/lib/traceview/frameworks/rails/inst/connection_adapters/oracle.rb +18 -0
  65. data/lib/traceview/frameworks/rails/inst/connection_adapters/postgresql.rb +30 -0
  66. data/lib/traceview/frameworks/rails/inst/connection_adapters/utils.rb +117 -0
  67. data/lib/traceview/frameworks/sinatra.rb +95 -0
  68. data/lib/traceview/frameworks/sinatra/templates.rb +56 -0
  69. data/lib/traceview/inst/cassandra.rb +279 -0
  70. data/lib/traceview/inst/dalli.rb +86 -0
  71. data/lib/traceview/inst/em-http-request.rb +99 -0
  72. data/lib/traceview/inst/excon.rb +111 -0
  73. data/lib/traceview/inst/faraday.rb +73 -0
  74. data/lib/traceview/inst/http.rb +87 -0
  75. data/lib/traceview/inst/httpclient.rb +173 -0
  76. data/lib/traceview/inst/memcache.rb +102 -0
  77. data/lib/traceview/inst/memcached.rb +94 -0
  78. data/lib/traceview/inst/mongo.rb +238 -0
  79. data/lib/traceview/inst/moped.rb +474 -0
  80. data/lib/traceview/inst/rack.rb +122 -0
  81. data/lib/traceview/inst/redis.rb +271 -0
  82. data/lib/traceview/inst/resque.rb +192 -0
  83. data/lib/traceview/inst/rest-client.rb +38 -0
  84. data/lib/traceview/inst/sequel.rb +162 -0
  85. data/lib/traceview/inst/typhoeus.rb +102 -0
  86. data/lib/traceview/instrumentation.rb +21 -0
  87. data/lib/traceview/loading.rb +94 -0
  88. data/lib/traceview/logger.rb +41 -0
  89. data/lib/traceview/method_profiling.rb +84 -0
  90. data/lib/traceview/ruby.rb +36 -0
  91. data/lib/traceview/support.rb +113 -0
  92. data/lib/traceview/thread_local.rb +26 -0
  93. data/lib/traceview/util.rb +250 -0
  94. data/lib/traceview/version.rb +16 -0
  95. data/lib/traceview/xtrace.rb +90 -0
  96. data/test/frameworks/apps/grape_nested.rb +30 -0
  97. data/test/frameworks/apps/grape_simple.rb +24 -0
  98. data/test/frameworks/apps/padrino_simple.rb +45 -0
  99. data/test/frameworks/apps/sinatra_simple.rb +24 -0
  100. data/test/frameworks/grape_test.rb +142 -0
  101. data/test/frameworks/padrino_test.rb +30 -0
  102. data/test/frameworks/sinatra_test.rb +30 -0
  103. data/test/instrumentation/cassandra_test.rb +380 -0
  104. data/test/instrumentation/dalli_test.rb +171 -0
  105. data/test/instrumentation/em_http_request_test.rb +86 -0
  106. data/test/instrumentation/excon_test.rb +207 -0
  107. data/test/instrumentation/faraday_test.rb +235 -0
  108. data/test/instrumentation/http_test.rb +140 -0
  109. data/test/instrumentation/httpclient_test.rb +296 -0
  110. data/test/instrumentation/memcache_test.rb +251 -0
  111. data/test/instrumentation/memcached_test.rb +226 -0
  112. data/test/instrumentation/mongo_test.rb +462 -0
  113. data/test/instrumentation/moped_test.rb +496 -0
  114. data/test/instrumentation/rack_test.rb +116 -0
  115. data/test/instrumentation/redis_hashes_test.rb +265 -0
  116. data/test/instrumentation/redis_keys_test.rb +318 -0
  117. data/test/instrumentation/redis_lists_test.rb +310 -0
  118. data/test/instrumentation/redis_misc_test.rb +160 -0
  119. data/test/instrumentation/redis_sets_test.rb +293 -0
  120. data/test/instrumentation/redis_sortedsets_test.rb +325 -0
  121. data/test/instrumentation/redis_strings_test.rb +333 -0
  122. data/test/instrumentation/resque_test.rb +62 -0
  123. data/test/instrumentation/rest-client_test.rb +294 -0
  124. data/test/instrumentation/sequel_mysql2_test.rb +326 -0
  125. data/test/instrumentation/sequel_mysql_test.rb +326 -0
  126. data/test/instrumentation/sequel_pg_test.rb +330 -0
  127. data/test/instrumentation/typhoeus_test.rb +285 -0
  128. data/test/minitest_helper.rb +187 -0
  129. data/test/profiling/method_test.rb +198 -0
  130. data/test/servers/rackapp_8101.rb +22 -0
  131. data/test/support/backcompat_test.rb +269 -0
  132. data/test/support/config_test.rb +128 -0
  133. data/test/support/dnt_test.rb +73 -0
  134. data/test/support/liboboe_settings_test.rb +104 -0
  135. data/test/support/xtrace_test.rb +35 -0
  136. data/traceview.gemspec +29 -0
  137. metadata +250 -0
@@ -0,0 +1,187 @@
1
+ require "minitest/spec"
2
+ require "minitest/autorun"
3
+ require "minitest/reporters"
4
+ require "minitest/debugger" if ENV['DEBUG']
5
+
6
+ ENV["RACK_ENV"] = "test"
7
+ ENV["TRACEVIEW_GEM_TEST"] = "true"
8
+ ENV["TRACEVIEW_GEM_VERBOSE"] = "true"
9
+
10
+ # FIXME: Temp hack to fix padrino-core calling RUBY_ENGINE when it's
11
+ # not defined under Ruby 1.8.7 and 1.9.3
12
+ RUBY_ENGINE = "ruby" unless defined?(RUBY_ENGINE)
13
+
14
+ Minitest::Spec.new 'pry'
15
+
16
+ unless RUBY_VERSION =~ /^1.8/
17
+ MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
18
+ end
19
+
20
+ if defined?(JRUBY_VERSION)
21
+ ENV['JAVA_OPTS'] = "-J-javaagent:/usr/local/tracelytics/tracelyticsagent.jar"
22
+ end
23
+
24
+ require 'rubygems'
25
+ require 'bundler'
26
+
27
+ # Preload memcache-client
28
+ require 'memcache'
29
+
30
+ Bundler.require(:default, :test)
31
+
32
+ @trace_dir = "/tmp/"
33
+ $trace_file = @trace_dir + "trace_output.bson"
34
+
35
+ # Configure TraceView
36
+ TraceView::Config[:verbose] = true
37
+ TraceView::Config[:tracing_mode] = "always"
38
+ TraceView::Config[:sample_rate] = 1000000
39
+ TraceView.logger.level = Logger::DEBUG
40
+
41
+ # Our background Rack-app for http client testing
42
+ require "./test/servers/rackapp_8101"
43
+
44
+ ##
45
+ # clear_all_traces
46
+ #
47
+ # Truncates the trace output file to zero
48
+ #
49
+ def clear_all_traces
50
+ TraceView::Reporter.clear_all_traces
51
+ end
52
+
53
+ ##
54
+ # get_all_traces
55
+ #
56
+ # Retrieves all traces written to the trace file
57
+ #
58
+ def get_all_traces
59
+ TraceView::Reporter.get_all_traces
60
+ end
61
+
62
+ ##
63
+ # validate_outer_layers
64
+ #
65
+ # Validates that the KVs in kvs are present
66
+ # in event
67
+ #
68
+ def validate_outer_layers(traces, layer)
69
+ traces.first['Layer'].must_equal layer
70
+ traces.first['Label'].must_equal 'entry'
71
+ traces.last['Layer'].must_equal layer
72
+ traces.last['Label'].must_equal 'exit'
73
+ end
74
+
75
+ ##
76
+ # validate_event_keys
77
+ #
78
+ # Validates that the KVs in kvs are present
79
+ # in event
80
+ #
81
+ def validate_event_keys(event, kvs)
82
+ kvs.each do |k, v|
83
+ event.has_key?(k).must_equal true
84
+ event[k].must_equal v
85
+ end
86
+ end
87
+
88
+ ##
89
+ # has_edge?
90
+ #
91
+ # Searches the array of <tt>traces</tt> for
92
+ # <tt>edge</tt>
93
+ #
94
+ def has_edge?(edge, traces)
95
+ traces.each do |t|
96
+ if TraceView::XTrace.edge_id(t["X-Trace"]) == edge
97
+ return true
98
+ end
99
+ end
100
+ TraceView.logger.debug "[oboe/debug] edge #{edge} not found in traces."
101
+ false
102
+ end
103
+
104
+ ##
105
+ # valid_edges?
106
+ #
107
+ # Runs through the array of <tt>traces</tt> to validate
108
+ # that all edges connect.
109
+ #
110
+ # Not that this won't work for external cross-app tracing
111
+ # since we won't have those remote traces to validate
112
+ # against.
113
+ #
114
+ def valid_edges?(traces)
115
+ traces.reverse.each do |t|
116
+ if t.key?("Edge")
117
+ return false unless has_edge?(t["Edge"], traces)
118
+ end
119
+ end
120
+ true
121
+ end
122
+
123
+ ##
124
+ # layer_has_key
125
+ #
126
+ # Checks an array of trace events if a specific layer (regardless of event type)
127
+ # has he specified key
128
+ #
129
+ def layer_has_key(traces, layer, key)
130
+ return false if traces.empty?
131
+ has_key = false
132
+
133
+ traces.each do |t|
134
+ if t["Layer"] == layer and t.has_key?(key)
135
+ has_key = true
136
+
137
+ (t["Backtrace"].length > 0).must_equal true
138
+ end
139
+ end
140
+
141
+ has_key.must_equal true
142
+ end
143
+
144
+ ##
145
+ # layer_doesnt_have_key
146
+ #
147
+ # Checks an array of trace events to assure that a specific layer
148
+ # (regardless of event type) doesn't have the specified key
149
+ #
150
+ def layer_doesnt_have_key(traces, layer, key)
151
+ return false if traces.empty?
152
+ has_key = false
153
+
154
+ traces.each do |t|
155
+ has_key = true if t["Layer"] == layer and t.has_key?(key)
156
+ end
157
+
158
+ has_key.must_equal false
159
+ end
160
+
161
+ ##
162
+ # Sinatra and Padrino Related Helpers
163
+ #
164
+ # Taken from padrino-core gem
165
+ #
166
+
167
+ class Sinatra::Base
168
+ # Allow assertions in request context
169
+ include MiniTest::Assertions
170
+ end
171
+
172
+
173
+ class MiniTest::Spec
174
+ include Rack::Test::Methods
175
+
176
+ # Sets up a Sinatra::Base subclass defined with the block
177
+ # given. Used in setup or individual spec methods to establish
178
+ # the application.
179
+ def mock_app(base=Padrino::Application, &block)
180
+ @app = Sinatra.new(base, &block)
181
+ end
182
+
183
+ def app
184
+ Rack::Lint.new(@app)
185
+ end
186
+ end
187
+
@@ -0,0 +1,198 @@
1
+ require 'minitest_helper'
2
+
3
+ describe "TraceViewMethodProfiling" do
4
+ before do
5
+ clear_all_traces
6
+ # Conditionally Undefine TestWorker
7
+ # http://stackoverflow.com/questions/11503558/how-to-undefine-class-in-ruby
8
+ Object.send(:remove_const, :TestWorker) if defined?(TestWorker)
9
+ end
10
+
11
+ it 'should be loaded, defined and ready' do
12
+ defined?(::TraceViewMethodProfiling).wont_match nil
13
+ end
14
+
15
+ it 'should trace Class methods' do
16
+ class TestWorker
17
+ def self.do_work
18
+ sleep 1
19
+ end
20
+
21
+ class << self
22
+ include TraceViewMethodProfiling
23
+ profile_method :do_work, 'do_work'
24
+ end
25
+ end
26
+
27
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
28
+ # Call the profiled class method
29
+ TestWorker.do_work
30
+ end
31
+
32
+ traces = get_all_traces
33
+ traces.count.must_equal 4
34
+
35
+ validate_outer_layers(traces, 'method_profiling')
36
+
37
+ kvs = {}
38
+ kvs["Label"] = 'profile_entry'
39
+ kvs["Language"] = "ruby"
40
+ kvs["ProfileName"] = "do_work"
41
+ kvs["FunctionName"] = "do_work"
42
+ kvs["Class"] = "TestWorker"
43
+
44
+ validate_event_keys(traces[1], kvs)
45
+
46
+ traces[1].has_key?("Layer").must_equal false
47
+ traces[1].has_key?("File").must_equal true
48
+ traces[1].has_key?("LineNumber").must_equal true
49
+
50
+ kvs.clear
51
+ kvs["Label"] = "profile_exit"
52
+ kvs["Language"] = "ruby"
53
+ kvs["ProfileName"] = "do_work"
54
+
55
+ validate_event_keys(traces[2], kvs)
56
+ traces[2].has_key?("Layer").must_equal false
57
+ end
58
+
59
+ it 'should trace Instance methods' do
60
+ class TestWorker
61
+ def do_work
62
+ sleep 1
63
+ end
64
+
65
+ include TraceViewMethodProfiling
66
+ profile_method :do_work, 'do_work'
67
+ end
68
+
69
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
70
+ # Call the profiled class method
71
+ tw = TestWorker.new
72
+ tw.do_work
73
+ end
74
+
75
+ traces = get_all_traces
76
+ traces.count.must_equal 4
77
+
78
+ validate_outer_layers(traces, 'method_profiling')
79
+
80
+ kvs = {}
81
+ kvs["Label"] = 'profile_entry'
82
+ kvs["Language"] = "ruby"
83
+ kvs["ProfileName"] = "do_work"
84
+ kvs["FunctionName"] = "do_work"
85
+ kvs["Class"] = "TestWorker"
86
+
87
+ validate_event_keys(traces[1], kvs)
88
+
89
+ traces[1].has_key?("Layer").must_equal false
90
+ traces[1].has_key?("File").must_equal true
91
+ traces[1].has_key?("LineNumber").must_equal true
92
+
93
+ kvs.clear
94
+ kvs["Label"] = "profile_exit"
95
+ kvs["Language"] = "ruby"
96
+ kvs["ProfileName"] = "do_work"
97
+
98
+ validate_event_keys(traces[2], kvs)
99
+ traces[2].has_key?("Layer").must_equal false
100
+ end
101
+
102
+ it 'should trace Module class methods' do
103
+ module TestWorker
104
+ def self.do_work
105
+ sleep 1
106
+ end
107
+
108
+ class << self
109
+ include TraceViewMethodProfiling
110
+ profile_method :do_work, 'do_work'
111
+ end
112
+ end
113
+
114
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
115
+ # Call the profiled class method
116
+ TestWorker.do_work
117
+ end
118
+
119
+ traces = get_all_traces
120
+ traces.count.must_equal 4
121
+ validate_outer_layers(traces, 'method_profiling')
122
+
123
+ kvs = {}
124
+ kvs["Label"] = 'profile_entry'
125
+ kvs["Language"] = "ruby"
126
+ kvs["ProfileName"] = "do_work"
127
+ kvs["FunctionName"] = "do_work"
128
+ kvs["Module"] = "TestWorker"
129
+
130
+ validate_event_keys(traces[1], kvs)
131
+
132
+ traces[1].has_key?("Layer").must_equal false
133
+ traces[1].has_key?("File").must_equal true
134
+ traces[1].has_key?("LineNumber").must_equal true
135
+
136
+ kvs.clear
137
+ kvs["Label"] = "profile_exit"
138
+ kvs["Language"] = "ruby"
139
+ kvs["ProfileName"] = "do_work"
140
+
141
+ validate_event_keys(traces[2], kvs)
142
+ traces[2].has_key?("Layer").must_equal false
143
+ end
144
+
145
+ it 'should not store arguments and return value by default' do
146
+ class TestWorker
147
+ def self.do_work(s, i, a, h)
148
+ sleep 1
149
+ return "the zebra is loose"
150
+ end
151
+
152
+ class << self
153
+ include TraceViewMethodProfiling
154
+ # Default call method
155
+ profile_method :do_work, 'do_work'
156
+ end
157
+ end
158
+
159
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
160
+ # Call the profiled class method
161
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
162
+ end
163
+
164
+ traces = get_all_traces
165
+ traces.count.must_equal 4
166
+
167
+ traces[1].has_key?("Args").must_equal false
168
+ traces[2].has_key?("ReturnValue").must_equal false
169
+ end
170
+
171
+ it 'should store arguments and return value when asked' do
172
+ class TestWorker
173
+ def self.do_work(s, i, a, h)
174
+ sleep 1
175
+ return "the zebra is loose"
176
+ end
177
+
178
+ class << self
179
+ include TraceViewMethodProfiling
180
+ profile_method :do_work, 'do_work', true, true
181
+ end
182
+ end
183
+
184
+ ::TraceView::API.start_trace('method_profiling', '', {}) do
185
+ # Call the profiled class method
186
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
187
+ end
188
+
189
+ traces = get_all_traces
190
+ traces.count.must_equal 4
191
+
192
+ traces[1].has_key?("Args").must_equal true
193
+ traces[1]["Args"].must_equal "\"String Argument\"\n203984\n[\"1\", \"2\", 3]\n{:color=>:black}\n"
194
+
195
+ traces[2].has_key?("ReturnValue").must_equal true
196
+ traces[2]["ReturnValue"].must_equal "\"the zebra is loose\"\n"
197
+ end
198
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright (c) 2015 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ require 'rack/handler/puma'
5
+ require 'traceview/inst/rack'
6
+
7
+ TraceView.logger.info "[oboe/info] Starting background utility rack app on localhost:8101."
8
+
9
+ Thread.new do
10
+ app = Rack::Builder.new {
11
+ use TraceView::Rack
12
+ run Proc.new { |env|
13
+ [200, {"Content-Type" => "text/html"}, ['Hello TraceView!']]
14
+ }
15
+ }
16
+
17
+ Rack::Handler::Puma.run(app, {:Host => '127.0.0.1', :Port => 8101})
18
+ end
19
+
20
+ # Allow Thin to boot.
21
+ sleep(2)
22
+
@@ -0,0 +1,269 @@
1
+ require 'minitest_helper'
2
+
3
+ describe "BackwardCompatibility" do
4
+
5
+ it 'should still respond to Oboe::Config' do
6
+ @verbose = Oboe::Config[:verbose]
7
+ @dalli_enabled = Oboe::Config[:dalli][:enabled]
8
+ @tm = Oboe::Config[:tracing_mode]
9
+ @sr = Oboe::Config[:sample_rate]
10
+
11
+ Oboe::Config[:verbose] = true
12
+ Oboe::Config[:verbose].must_equal true
13
+ Oboe::Config.verbose.must_equal true
14
+ TraceView::Config[:verbose].must_equal true
15
+ TraceView::Config.verbose.must_equal true
16
+
17
+ Oboe::Config[:dalli][:enabled] = false
18
+ Oboe::Config[:dalli][:enabled].must_equal false
19
+ TraceView::Config[:dalli][:enabled].must_equal false
20
+
21
+ Oboe::Config[:sample_rate] = 8e5
22
+ Oboe::Config.sample_rate.must_equal 8e5
23
+ TraceView::Config.sample_rate.must_equal 8e5
24
+
25
+ Oboe::Config[:tracing_mode] = 'always'
26
+ Oboe::Config.tracing_mode.must_equal 'always'
27
+ TraceView::Config.tracing_mode.must_equal 'always'
28
+
29
+ Oboe::Config[:sample_rate] = @sr
30
+ Oboe::Config[:tracing_mode] = @tm
31
+ Oboe::Config[:dalli][:enabled] = @dalli_enabled
32
+ Oboe::Config[:verbose] = @verbose
33
+ end
34
+
35
+ it 'should still support Oboe::API.log calls' do
36
+ clear_all_traces
37
+
38
+ Oboe::API.log_start('rack', nil, {})
39
+ Oboe::API.log_end('rack')
40
+
41
+ traces = get_all_traces
42
+ traces.count.must_equal 2
43
+ end
44
+
45
+ it 'should still support Oboe::API.trace calls' do
46
+ clear_all_traces
47
+
48
+ Oboe::API.start_trace('api_test', '', {}) do
49
+ sleep 1
50
+ end
51
+
52
+ traces = get_all_traces
53
+ traces.count.must_equal 2
54
+
55
+ validate_outer_layers(traces, 'api_test')
56
+ end
57
+
58
+ it 'should still support Oboe.profile'do
59
+ clear_all_traces
60
+
61
+ Oboe::API.start_trace('outer_profile_test') do
62
+ Oboe::API.profile('profile_test', {}, false) do
63
+ sleep 1
64
+ end
65
+ end
66
+
67
+ traces = get_all_traces
68
+ traces.count.must_equal 4
69
+ end
70
+
71
+ # Pasted in from test/profiling/method_test.rb
72
+ # Modified to use OboeMethodProfiling
73
+ describe "OboeMethodProfiling" do
74
+ before do
75
+ clear_all_traces
76
+ # Conditionally Undefine TestWorker
77
+ # http://stackoverflow.com/questions/11503558/how-to-undefine-class-in-ruby
78
+ Object.send(:remove_const, :TestWorker) if defined?(TestWorker)
79
+ end
80
+
81
+ it 'should be loaded, defined and ready' do
82
+ defined?(::OboeMethodProfiling).wont_match nil
83
+ end
84
+
85
+ it 'should trace Class methods' do
86
+ class TestWorker
87
+ def self.do_work
88
+ sleep 1
89
+ end
90
+
91
+ class << self
92
+ include OboeMethodProfiling
93
+ profile_method :do_work, 'do_work'
94
+ end
95
+ end
96
+
97
+ ::Oboe::API.start_trace('method_profiling', '', {}) do
98
+ # Call the profiled class method
99
+ TestWorker.do_work
100
+ end
101
+
102
+ traces = get_all_traces
103
+ traces.count.must_equal 4
104
+
105
+ validate_outer_layers(traces, 'method_profiling')
106
+
107
+ kvs = {}
108
+ kvs["Label"] = 'profile_entry'
109
+ kvs["Language"] = "ruby"
110
+ kvs["ProfileName"] = "do_work"
111
+ kvs["FunctionName"] = "do_work"
112
+ kvs["Class"] = "TestWorker"
113
+
114
+ validate_event_keys(traces[1], kvs)
115
+
116
+ traces[1].has_key?("Layer").must_equal false
117
+ traces[1].has_key?("File").must_equal true
118
+ traces[1].has_key?("LineNumber").must_equal true
119
+
120
+ kvs.clear
121
+ kvs["Label"] = "profile_exit"
122
+ kvs["Language"] = "ruby"
123
+ kvs["ProfileName"] = "do_work"
124
+
125
+ validate_event_keys(traces[2], kvs)
126
+ traces[2].has_key?("Layer").must_equal false
127
+ end
128
+
129
+ it 'should trace Instance methods' do
130
+ class TestWorker
131
+ def do_work
132
+ sleep 1
133
+ end
134
+
135
+ include OboeMethodProfiling
136
+ profile_method :do_work, 'do_work'
137
+ end
138
+
139
+ ::Oboe::API.start_trace('method_profiling', '', {}) do
140
+ # Call the profiled class method
141
+ tw = TestWorker.new
142
+ tw.do_work
143
+ end
144
+
145
+ traces = get_all_traces
146
+ traces.count.must_equal 4
147
+
148
+ validate_outer_layers(traces, 'method_profiling')
149
+
150
+ kvs = {}
151
+ kvs["Label"] = 'profile_entry'
152
+ kvs["Language"] = "ruby"
153
+ kvs["ProfileName"] = "do_work"
154
+ kvs["FunctionName"] = "do_work"
155
+ kvs["Class"] = "TestWorker"
156
+
157
+ validate_event_keys(traces[1], kvs)
158
+
159
+ traces[1].has_key?("Layer").must_equal false
160
+ traces[1].has_key?("File").must_equal true
161
+ traces[1].has_key?("LineNumber").must_equal true
162
+
163
+ kvs.clear
164
+ kvs["Label"] = "profile_exit"
165
+ kvs["Language"] = "ruby"
166
+ kvs["ProfileName"] = "do_work"
167
+
168
+ validate_event_keys(traces[2], kvs)
169
+ traces[2].has_key?("Layer").must_equal false
170
+ end
171
+
172
+ it 'should trace Module class methods' do
173
+ module TestWorker
174
+ def self.do_work
175
+ sleep 1
176
+ end
177
+
178
+ class << self
179
+ include OboeMethodProfiling
180
+ profile_method :do_work, 'do_work'
181
+ end
182
+ end
183
+
184
+ ::Oboe::API.start_trace('method_profiling', '', {}) do
185
+ # Call the profiled class method
186
+ TestWorker.do_work
187
+ end
188
+
189
+ traces = get_all_traces
190
+ traces.count.must_equal 4
191
+ validate_outer_layers(traces, 'method_profiling')
192
+
193
+ kvs = {}
194
+ kvs["Label"] = 'profile_entry'
195
+ kvs["Language"] = "ruby"
196
+ kvs["ProfileName"] = "do_work"
197
+ kvs["FunctionName"] = "do_work"
198
+ kvs["Module"] = "TestWorker"
199
+
200
+ validate_event_keys(traces[1], kvs)
201
+
202
+ traces[1].has_key?("Layer").must_equal false
203
+ traces[1].has_key?("File").must_equal true
204
+ traces[1].has_key?("LineNumber").must_equal true
205
+
206
+ kvs.clear
207
+ kvs["Label"] = "profile_exit"
208
+ kvs["Language"] = "ruby"
209
+ kvs["ProfileName"] = "do_work"
210
+
211
+ validate_event_keys(traces[2], kvs)
212
+ traces[2].has_key?("Layer").must_equal false
213
+ end
214
+
215
+ it 'should not store arguments and return value by default' do
216
+ class TestWorker
217
+ def self.do_work(s, i, a, h)
218
+ sleep 1
219
+ return "the zebra is loose"
220
+ end
221
+
222
+ class << self
223
+ include OboeMethodProfiling
224
+ # Default call method
225
+ profile_method :do_work, 'do_work'
226
+ end
227
+ end
228
+
229
+ ::Oboe::API.start_trace('method_profiling', '', {}) do
230
+ # Call the profiled class method
231
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
232
+ end
233
+
234
+ traces = get_all_traces
235
+ traces.count.must_equal 4
236
+
237
+ traces[1].has_key?("Args").must_equal false
238
+ traces[2].has_key?("ReturnValue").must_equal false
239
+ end
240
+
241
+ it 'should store arguments and return value when asked' do
242
+ class TestWorker
243
+ def self.do_work(s, i, a, h)
244
+ sleep 1
245
+ return "the zebra is loose"
246
+ end
247
+
248
+ class << self
249
+ include OboeMethodProfiling
250
+ profile_method :do_work, 'do_work', true, true
251
+ end
252
+ end
253
+
254
+ ::Oboe::API.start_trace('method_profiling', '', {}) do
255
+ # Call the profiled class method
256
+ TestWorker.do_work('String Argument', 203984, ["1", "2", 3], { :color => :black })
257
+ end
258
+
259
+ traces = get_all_traces
260
+ traces.count.must_equal 4
261
+
262
+ traces[1].has_key?("Args").must_equal true
263
+ traces[1]["Args"].must_equal "\"String Argument\"\n203984\n[\"1\", \"2\", 3]\n{:color=>:black}\n"
264
+
265
+ traces[2].has_key?("ReturnValue").must_equal true
266
+ traces[2]["ReturnValue"].must_equal "\"the zebra is loose\"\n"
267
+ end
268
+ end
269
+ end