oboe 2.5.0.7 → 2.6.0.2

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 812e394b380905601c8d1fbae241aaedce6231b4
4
- data.tar.gz: 317bb57275d9eb6b23054d9d2e51dd0c8fbd64d6
3
+ metadata.gz: bf5cf2103662335b54454808e24505e4c0fe01ac
4
+ data.tar.gz: 0e18b3bac19c85fbfba7a34c38c7edb28bb0f53b
5
5
  SHA512:
6
- metadata.gz: af3e85508ec28a8a56e05ebed1f1ee6a90c8475ca258c9b9127ee81c8d33226331f4604f856426cb1aca24b90592f7d0ec22e2c6da0df4d47e3e30a0e96f4294
7
- data.tar.gz: a8744c90e5d216672d774b094deadf1d1ccf031a25de3f262984c10d83593fb5908fdb05527671ee7a53f99b5719c9238f65cea6965c197861815cf482970d86
6
+ metadata.gz: 94c63bc3a414703e1f29c2890a077af2c752dbcbd6f8de2e229b982802fa0b226d06186f8a0c8c5af54a526263c9dceb5f2074d64911f2420ba1ee595f5f0642
7
+ data.tar.gz: a7519e0aded683d91e0cf088d82a12349183616c3dec0b27beb97d969df0fa7e54df7b47c63120078c7743cddf72bd1b6a5730be608fe2e794f985b98b6fbda1
data/Gemfile CHANGED
@@ -1,9 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
- # Import dependencies from oboe.gemspec
4
- gemspec :name => 'oboe'
5
-
6
-
7
3
  group :development, :test do
8
4
  gem 'minitest'
9
5
  gem 'minitest-reporters'
@@ -12,7 +8,7 @@ group :development, :test do
12
8
  gem 'bson'
13
9
  end
14
10
 
15
- group :development do
11
+ group :development, :test do
16
12
  gem 'ruby-debug', :platform => :mri_18
17
13
  gem 'ruby-debug19', :platform => :mri_19, :require => 'ruby-debug'
18
14
  gem 'byebug', :platform => :mri_20
@@ -31,3 +27,10 @@ gem 'moped' unless (RUBY_VERSION =~ /^1.8/) == 0
31
27
  gem 'resque'
32
28
  gem 'redis'
33
29
 
30
+ # Instrumented Frameworks
31
+ gem 'sinatra'
32
+ gem 'padrino' unless (RUBY_VERSION =~ /^1.8/) == 0
33
+
34
+ # Import dependencies from oboe.gemspec
35
+ gemspec :name => 'oboe'
36
+
data/README.md CHANGED
@@ -17,11 +17,15 @@ It requires a [TraceView](http://www.appneta.com/products/traceview/) account to
17
17
 
18
18
  The oboe gem is [available on Rubygems](https://rubygems.org/gems/oboe) and can be installed with:
19
19
 
20
- gem install oboe
20
+ ```bash
21
+ gem install oboe
22
+ ```
21
23
 
22
24
  or added to your bundle Gemfile and running `bundle install`:
23
25
 
24
- gem 'oboe'
26
+ ```ruby
27
+ gem 'oboe'
28
+ ```
25
29
 
26
30
  # Running
27
31
 
@@ -29,7 +33,7 @@ or added to your bundle Gemfile and running `bundle install`:
29
33
 
30
34
  No special steps are needed to instrument Ruby on Rails. Once part of the bundle, the oboe gem will automatically detect Rails and instrument on stack initialization.
31
35
 
32
- _Note: You will still need to decide on your `tracing_mode` depending on whether you are running with an instrumented Apache or nginx in front of your Rails stack. See below for more details._
36
+ *Note: You will still need to decide on your `tracing_mode` depending on whether you are running with an instrumented Apache or nginx in front of your Rails stack. See below for more details.*
33
37
 
34
38
  ### The Install Generator
35
39
 
@@ -37,16 +41,20 @@ The oboe gem provides a Rails generator used to seed an oboe initializer where y
37
41
 
38
42
  To run the install generator run:
39
43
 
40
- bundle exec rails generate oboe:install
44
+ ```bash
45
+ bundle exec rails generate oboe:install
46
+ ```
41
47
 
42
48
  After the prompts, this will create an initializer: `config/initializers/oboe.rb`.
43
49
 
44
- ## Sinatra/Padrino
50
+ ## Sinatra
45
51
 
46
- You can instrument your Sinatra or Padrino application by adding the following code to your `config.ru` Rackup file (Padrino example).
52
+ You can instrument your Sinatra application by adding the following code to your `config.ru` Rackup file:
47
53
 
54
+ ```ruby
55
+ # If you're not using Bundler.require. Make sure this is done
56
+ # after the Sinatra require directive.
48
57
  require 'oboe'
49
- require 'oboe/inst/rack'
50
58
 
51
59
  # When traces should be initiated for incoming requests. Valid options are
52
60
  # "always", "through" (when the request is initiated with a tracing header
@@ -58,32 +66,57 @@ You can instrument your Sinatra or Padrino application by adding the following c
58
66
  # auto sampling or managing the sample rate through the TraceView portal.
59
67
  # Oboe::Config[:sample_rate] = 1000000
60
68
 
61
- # You may want to replace the Oboe.logger with your own
62
- Oboe.logger = Padrino.logger
63
-
64
- Oboe::Ruby.initialize
65
- Padrino.use Oboe::Rack
69
+ # You may want to replace the Oboe.logger with whichever logger you are using
70
+ # Oboe.logger = Sinatra.logger
71
+ ```
72
+
73
+ Note: If you're on Heroku, you don't need to set `tracing_mode` or `sample_rate` - they will be automatically configured.
74
+
75
+ Make sure that the oboe gem is loaded _after_ Sinatra either by listing `gem 'oboe'` after Sinatra in your Gemfile or calling the `require 'oboe'` directive after Sinatra is loaded.
76
+
77
+ With this, the oboe gem will automatically detect Sinatra on boot and instrument key components.
78
+
79
+ ## Padrino
80
+
81
+ As long as the oboe gem is in your `Gemfile` (inserted after the `gem 'padrino'` directive) and you are calling `Bundler.require`, the oboe gem will automatically instrument Padrino applications.
82
+
83
+ If you need to set `Oboe::Config` values on stack boot, you can do so by adding the following
84
+ to your `config/boot.rb` file:
66
85
 
67
- _In a future release, much of this will be automated._
86
+ Padrino.before_load do
87
+ # When traces should be initiated for incoming requests. Valid options are
88
+ # "always", "through" (when the request is initiated with a tracing header
89
+ # from upstream) and "never". You must set this directive to "always" in
90
+ # order to initiate tracing.
91
+ Oboe::Config[:tracing_mode] = 'always'
92
+
93
+ # You can remove the following line in production to allow for
94
+ # auto sampling or managing the sample rate through the TraceView portal.
95
+ Oboe::Config[:sample_rate] = 1e6
96
+ end
97
+
98
+ Note: If you're on Heroku, you don't need to set `tracing_mode` or `sample_rate` - they will be automatically configured.
68
99
 
69
100
  ## Custom Ruby Scripts & Applications
70
101
 
71
102
  The oboe gem has the ability to instrument any arbitrary Ruby application or script as long as the gem is initialized with the manual methods:
72
103
 
73
- require 'rubygems'
74
- require 'bundler'
75
-
76
- Bundler.require
77
-
78
- require 'oboe'
104
+ ```ruby
105
+ require 'rubygems'
106
+ require 'bundler'
107
+
108
+ Bundler.require
79
109
 
80
- # Tracing mode can be 'never', 'through' (to follow upstream) or 'always'
81
- Oboe::Config[:tracing_mode] = 'always'
110
+ require 'oboe'
82
111
 
83
- # Number of requests to trace out of each million
84
- Oboe::Config[:sample_rate] = 1000000
112
+ # Tracing mode can be 'never', 'through' (to follow upstream) or 'always'
113
+ Oboe::Config[:tracing_mode] = 'always'
85
114
 
86
- Oboe::Ruby.initialize
115
+ # Number of requests to trace out of each million
116
+ Oboe::Config[:sample_rate] = 1000000
117
+
118
+ Oboe::Ruby.initialize
119
+ ```
87
120
 
88
121
  From here, you can use the Tracing API to instrument areas of code using `Oboe::API.start_trace` (see below). If you prefer to instead dive directly into code, take a look at [this example](https://gist.github.com/pglombardo/8550713) of an instrumented Ruby script.
89
122
 
@@ -97,20 +130,22 @@ You can send deploy notifications to TraceView and have the events show up on yo
97
130
 
98
131
  You can instrument any arbitrary block of code using `Oboe::API.trace`:
99
132
 
100
- # layer_name will show up in the TraceView app dashboard
101
- layer_name = 'subsystemX'
133
+ ```ruby
134
+ # layer_name will show up in the TraceView app dashboard
135
+ layer_name = 'subsystemX'
102
136
 
103
- # report_kvs are a set of information Key/Value pairs that are sent to
104
- # TraceView dashboard along with the performance metrics. These KV
105
- # pairs are used to report request, environment and/or client specific
106
- # information.
137
+ # report_kvs are a set of information Key/Value pairs that are sent to
138
+ # TraceView dashboard along with the performance metrics. These KV
139
+ # pairs are used to report request, environment and/or client specific
140
+ # information.
107
141
 
108
- report_kvs = {}
109
- report_kvs[:mykey] = @client.id
142
+ report_kvs = {}
143
+ report_kvs[:mykey] = @client.id
110
144
 
111
- Oboe::API.trace(layer_name, report_kvs) do
112
- # the block of code to be traced
113
- end
145
+ Oboe::API.trace(layer_name, report_kvs) do
146
+ # the block of code to be traced
147
+ end
148
+ ```
114
149
 
115
150
  `Oboe::API.trace` is used within the context of a request. It will follow the upstream state of the request being traced. i.e. the block of code will only be traced when the parent request is being traced.
116
151
 
@@ -126,20 +161,22 @@ By using class level declarations, it's possible to automatically have certain m
126
161
 
127
162
  The pattern for Method Profiling is as follows:
128
163
 
129
- # 'profile_name' is similar to a layer name.
130
- # It identifies this custom trace in your dashboard.
131
- #
132
- class Engine
133
- include OboeMethodProfiling
134
-
135
- def processor()
136
- # body of method
137
- end
164
+ ```ruby
165
+ # 'profile_name' is similar to a layer name.
166
+ # It identifies this custom trace in your dashboard.
167
+ #
168
+ class Engine
169
+ include OboeMethodProfiling
138
170
 
139
- # call syntax: profile_method <method>, <profile_name>
140
- profile_method :processor, 'processor'
171
+ def processor()
172
+ # body of method
141
173
  end
142
174
 
175
+ # call syntax: profile_method <method>, <profile_name>
176
+ profile_method :processor, 'processor'
177
+ end
178
+ ```
179
+
143
180
  This example demonstrates method profiling of instance methods. Class methods are profiled slightly differently. See the TraceView [documentation portal](https://support.tv.appneta.com/support/solutions/articles/86395-ruby-instrumentation-public-api) for full details.
144
181
 
145
182
  # Support
@@ -179,7 +216,9 @@ The oboe gem uses a standard gem layout. Here are the notable directories.
179
216
 
180
217
  The oboe gem is built with the standard `gem build` command passing in the gemspec:
181
218
 
182
- gem build oboe.gemspec
219
+ ```bash
220
+ gem build oboe.gemspec
221
+ ```
183
222
 
184
223
  ## Writing Custom Instrumentation
185
224
 
@@ -191,50 +230,54 @@ The Dalli gem nicely routes all memcache operations through a single `perform` o
191
230
 
192
231
  First, we define a module (Oboe::Inst::Dalli) and our own custom `perform_with_oboe` method that we will use as a wrapper around Dalli's `perform` method. We also declare an `included` method which automatically gets called when this module is included by another. See ['included' Ruby reference documentation](http://apidock.com/ruby/Module/included).
193
232
 
194
- module Oboe
195
- module Inst
196
- module Dalli
197
- include Oboe::API::Memcache
198
-
199
- def self.included(cls)
200
- cls.class_eval do
201
- if ::Dalli::Client.private_method_defined? :perform
202
- alias perform_without_oboe perform
203
- alias perform perform_with_oboe
204
- end
205
- end
233
+ ```ruby
234
+ module Oboe
235
+ module Inst
236
+ module Dalli
237
+ include Oboe::API::Memcache
238
+
239
+ def self.included(cls)
240
+ cls.class_eval do
241
+ if ::Dalli::Client.private_method_defined? :perform
242
+ alias perform_without_oboe perform
243
+ alias perform perform_with_oboe
206
244
  end
207
-
208
- def perform_with_oboe(*all_args, &blk)
209
- op, key, *args = *all_args
210
-
211
- if Oboe.tracing?
212
- opts = {}
213
- opts[:KVOp] = op
214
- opts[:KVKey] = key
215
-
216
- Oboe::API.trace('memcache', opts || {}) do
217
- result = perform_without_oboe(*all_args, &blk)
218
- if op == :get and key.class == String
219
- Oboe::API.log('memcache', 'info', { :KVHit => memcache_hit?(result) })
220
- end
221
- result
222
- end
223
- else
224
- perform_without_oboe(*all_args, &blk)
245
+ end
246
+ end
247
+
248
+ def perform_with_oboe(*all_args, &blk)
249
+ op, key, *args = *all_args
250
+
251
+ if Oboe.tracing?
252
+ opts = {}
253
+ opts[:KVOp] = op
254
+ opts[:KVKey] = key
255
+
256
+ Oboe::API.trace('memcache', opts || {}) do
257
+ result = perform_without_oboe(*all_args, &blk)
258
+ if op == :get and key.class == String
259
+ Oboe::API.log('memcache', 'info', { :KVHit => memcache_hit?(result) })
225
260
  end
261
+ result
226
262
  end
263
+ else
264
+ perform_without_oboe(*all_args, &blk)
227
265
  end
228
266
  end
229
267
  end
268
+ end
269
+ end
270
+ ```
230
271
 
231
272
  Second, we tail onto the end of the instrumentation file a simple `::Dalli::Client.module_eval` call to tell the Dalli module to include our newly defined instrumentation module. Doing this will invoke our previously defined `included` method.
232
273
 
233
- if defined?(Dalli) and Oboe::Config[:dalli][:enabled]
234
- ::Dalli::Client.module_eval do
235
- include Oboe::Inst::Dalli
236
- end
237
- end
274
+ ```ruby
275
+ if defined?(Dalli) and Oboe::Config[:dalli][:enabled]
276
+ ::Dalli::Client.module_eval do
277
+ include Oboe::Inst::Dalli
278
+ end
279
+ end
280
+ ```
238
281
 
239
282
  Third, in our wrapper method, we capture the arguments passed in, collect the operation and key information into a local hash and then invoke the `Oboe::API.trace` method to time the execution of the original operation.
240
283
 
@@ -248,9 +291,9 @@ Some other tips and guidelines:
248
291
 
249
292
  * If instrumenting a library, database or service, place your new instrumentation file into the `lib/oboe/inst/` directory. From there, the oboe gem will detect it and automatically load the instrumentation file.
250
293
 
251
- * If instrumentating a new framework, place your instrumentation file in `lib/oboe/frameworks`. Refer to the Rails instrumentation for on ideas on how to load the oboe gem correctly in your framework.
294
+ * If instrumenting a new framework, place your instrumentation file in `lib/oboe/frameworks`. Refer to the Rails instrumentation for on ideas on how to load the oboe gem correctly in your framework.
252
295
 
253
- * Review other existing instrumention similar to the one you wish to author. `lib/oboe/inst/` is a great place to start.
296
+ * Review other existing instrumentation similar to the one you wish to author. `lib/oboe/inst/` is a great place to start.
254
297
 
255
298
  * Depending on the configured `:sample_rate`, not all requests will be traced. Use `Oboe.tracing?` to determine of this is a request that is being traced.
256
299
 
@@ -262,21 +305,25 @@ Some other tips and guidelines:
262
305
 
263
306
  The oboe gem utilizes a C extension to interface with the system `liboboe.so` library. This system library is installed with the TraceView host packages (tracelyzer, liboboe0, liboboe-dev) and is used to report [host](http://www.appneta.com/blog/app-host-metrics/) and performance metrics from multiple sources (Ruby, Apache, Python etc.) back to TraceView servers.
264
307
 
265
- C extensions are usually built on `gem install` but when working out of a local git repository, it's required that you manually build this C extension for the gem to function.
308
+ C extensions are usually built on `gem install` but when working out of a local git repository, it's required that you manually build this C extension for the gem to function.
266
309
 
267
310
  To make this simpler, we've included a few rake tasks to automate this process:
268
311
 
269
- rake compile # Build the gem's c extension
270
- rake distclean # Remove all built files and extensions
271
- rake recompile # Rebuild the gem's c extension
312
+ ```bash
313
+ rake compile # Build the gem's c extension
314
+ rake distclean # Remove all built files and extensions
315
+ rake recompile # Rebuild the gem's c extension
316
+ ```
272
317
 
273
318
  Note: Make sure you have the development package `liboboe0-dev` installed before attempting to compile the C extension.
274
319
 
275
- >$ dpkg -l | grep liboboe
276
- ii liboboe-dev 1.1.1-precise1 Tracelytics common library -- development files
277
- ii liboboe0 1.1.1-precise1 Tracelytics common library
320
+ ```bash
321
+ >$ dpkg -l | grep liboboe
322
+ ii liboboe-dev 1.1.1-precise1 Tracelytics common library -- development files
323
+ ii liboboe0 1.1.1-precise1 Tracelytics common library
324
+ ```
278
325
 
279
- See [Installing Base Packages on Debian and Ubuntu](https://support.tv.appneta.com/support/solutions/articles/86359-installing-base-packages-on-debian-and-ubuntu) in the Knowledge Base for details. Our hacker extraodinaire [Rob Salmond](https://github.com/rsalmond) from the support team has even gotten these packages to [run on Gentoo](http://www.appneta.com/blog/unsupported-doesnt-work/)!
326
+ See [Installing Base Packages on Debian and Ubuntu](https://support.tv.appneta.com/support/solutions/articles/86359-installing-base-packages-on-debian-and-ubuntu) in the Knowledge Base for details. Our hacker extraordinaire [Rob Salmond](https://github.com/rsalmond) from the support team has even gotten these packages to [run on Gentoo](http://www.appneta.com/blog/unsupported-doesnt-work/)!
280
327
 
281
328
  To see the code related to the C extension, take a look at `ext/oboe_metal/extconf.rb` for details.
282
329
 
@@ -288,21 +335,25 @@ The tests bundled with the gem are implemented using [Minitest](https://github.c
288
335
 
289
336
  After a bundle install, the tests can be run as:
290
337
 
291
- bundle exec rake test
338
+ ```bash
339
+ bundle exec rake test
340
+ ```
292
341
 
293
342
  This will run a full end-to-end test suite that covers all supported libraries and databases. Note that this requires all of the supported software (Cassandra, Memcache, Mongo etc.) to be installed, configured and available.
294
343
 
295
- Since this is overly burdonsome for casual users, you can run just the tests that you're interested in.
344
+ Since this is overly burdensome for casual users, you can run just the tests that you're interested in.
296
345
 
297
346
  To run just the tests for the dalli gem trace validation:
298
347
 
299
- bundle exec rake test TEST=test/instrumentation/dalli_test.rb
348
+ ```bash
349
+ bundle exec rake test TEST=test/instrumentation/dalli_test.rb
350
+ ```
300
351
 
301
- We humbly request that any submitted instrumention is delivered with corresponding test coverage.
352
+ We humbly request that any submitted instrumentation is delivered with corresponding test coverage.
302
353
 
303
354
  # License
304
355
 
305
- Copyright (c) 2013 Appneta
356
+ Copyright (c) 2014 Appneta
306
357
 
307
358
  Released under the [AppNeta Open License](http://www.appneta.com/appneta-license), Version 1.0
308
359
 
data/Rakefile CHANGED
@@ -77,3 +77,11 @@ end
77
77
  desc "Rebuild the gem's c extension"
78
78
  task :recompile => [ :distclean, :compile ]
79
79
 
80
+ task :console do
81
+ require 'pry'
82
+ require 'oboe'
83
+ ARGV.clear
84
+ Pry.start
85
+ end
86
+
87
+
@@ -22,7 +22,7 @@ begin
22
22
  rescue LoadError
23
23
  Oboe.loaded = false
24
24
 
25
- unless $ENV['RAILS_GROUP'] == 'assets'
25
+ unless ENV['RAILS_GROUP'] == 'assets'
26
26
  $stderr.puts "=============================================================="
27
27
  $stderr.puts "Missing TraceView libraries. Tracing disabled."
28
28
  $stderr.puts "See: https://support.tv.appneta.com/solution/articles/137973"
@@ -38,8 +38,11 @@ begin
38
38
  require 'oboe/ruby'
39
39
 
40
40
  # Frameworks
41
- require 'oboe/frameworks/rails' if defined?(::Rails) and Oboe.loaded
42
-
41
+ if Oboe.loaded
42
+ require 'oboe/frameworks/rails' if defined?(::Rails)
43
+ require 'oboe/frameworks/sinatra' if defined?(::Sinatra)
44
+ require 'oboe/frameworks/padrino' if defined?(::Padrino)
45
+ end
43
46
  rescue Exception => e
44
47
  $stderr.puts "[oboe/error] Problem loading: #{e.inspect}"
45
48
  $stderr.puts e.backtrace
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2014 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module PadrinoInst
6
+ module Routing
7
+ def self.included(klass)
8
+ ::Oboe::Util.method_alias(klass, :dispatch!, ::Padrino::Routing)
9
+ end
10
+
11
+ def dispatch_with_oboe
12
+ if Oboe.tracing?
13
+ report_kvs = {}
14
+
15
+ # Fall back to the raw tracing API so we can pass KVs
16
+ # back on exit (a limitation of the Oboe::API.trace
17
+ # block method) This removes the need for an info
18
+ # event to send additonal KVs
19
+ ::Oboe::API.log_entry('padrino', {})
20
+
21
+ begin
22
+ r = dispatch_without_oboe
23
+
24
+ # Report Controller/Action as best possible
25
+ if request.controller and not request.controller.empty?
26
+ report_kvs[:Controller] = request.controller
27
+ else
28
+ report_kvs[:Controller] = self.class
29
+ end
30
+
31
+ report_kvs[:Action] = request.action
32
+ r
33
+ ensure
34
+ ::Oboe::API.log_exit('padrino', report_kvs)
35
+ end
36
+ else
37
+ dispatch_without_oboe
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+
44
+ if defined?(::Padrino)
45
+ # This instrumentation is a superset of the Sinatra instrumentation similar
46
+ # to how Padrino is a superset of Sinatra itself.
47
+ ::Oboe.logger.info "[oboe/loading] Instrumenting Padrino" if Oboe::Config[:verbose]
48
+
49
+ require 'oboe/frameworks/padrino/templates'
50
+
51
+ Padrino.after_load do
52
+ ::Oboe.logger = ::Padrino.logger if ::Padrino.respond_to?(:logger)
53
+ ::Oboe::Loading.load_access_key
54
+ ::Oboe::Inst.load_instrumentation
55
+
56
+ ::Oboe::Util.send_include(::Padrino::Routing::InstanceMethods, ::Oboe::PadrinoInst::Routing)
57
+ if defined?(::Padrino::Rendering)
58
+ ::Oboe::Util.send_include(::Padrino::Rendering::InstanceMethods, ::Oboe::PadrinoInst::Rendering)
59
+ end
60
+ end
61
+
62
+ end
63
+
@@ -0,0 +1,57 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module PadrinoInst
6
+ module Rendering
7
+ def self.included(klass)
8
+ ::Oboe::Util.method_alias(klass, :render, ::Padrino::Rendering)
9
+ end
10
+
11
+ def render_with_oboe(engine, data=nil, options={}, locals={}, &block)
12
+ if Oboe.tracing?
13
+ report_kvs = {}
14
+
15
+ if data
16
+ report_kvs[:engine] = engine
17
+ report_kvs[:template] = data
18
+ else
19
+ report_kvs[:template] = engine
20
+ end
21
+
22
+ if Oboe::Context.tracing_layer_op?('render')
23
+ # For recursive calls to :render (for sub-partials and layouts),
24
+ # use method profiling.
25
+ begin
26
+ report_kvs[:FunctionName] = :render
27
+ report_kvs[:Class] = :Rendering
28
+ report_kvs[:Module] = 'Padrino'
29
+ report_kvs[:File] = __FILE__
30
+ report_kvs[:LineNumber] = __LINE__
31
+ rescue StandardError => e
32
+ ::Oboe.logger.debug e.message
33
+ ::Oboe.logger.debug e.backtrace.join(", ")
34
+ end
35
+
36
+ Oboe::API.profile(report_kvs[:template], report_kvs, false) do
37
+ render_without_oboe(engine, data, options, locals, &block)
38
+ end
39
+ else
40
+ # Fall back to the raw tracing API so we can pass KVs
41
+ # back on exit (a limitation of the Oboe::API.trace
42
+ # block method) This removes the need for an info
43
+ # event to send additonal KVs
44
+ ::Oboe::API.log_entry('render', {}, 'render')
45
+
46
+ begin
47
+ render_without_oboe(engine, data, options, locals, &block)
48
+ ensure
49
+ ::Oboe::API.log_exit('render', report_kvs)
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+
@@ -4,7 +4,7 @@
4
4
  module Oboe
5
5
  module Rails
6
6
  module Helpers
7
- extend ActiveSupport::Concern if ::Rails::VERSION::MAJOR > 2
7
+ extend ActiveSupport::Concern if defined?(::Rails) and ::Rails::VERSION::MAJOR > 2
8
8
 
9
9
  @@rum_xhr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_ajax_header.js.erb')
10
10
  @@rum_hdr_tmpl = File.read(File.dirname(__FILE__) + '/rails/helpers/rum/rum_header.js.erb')
@@ -106,7 +106,8 @@ if defined?(::Rails)
106
106
  end
107
107
 
108
108
  config.after_initialize do
109
- Oboe::Loading.setup_logger
109
+ Oboe.logger = ::Rails.logger if ::Rails.logger
110
+
110
111
  Oboe::Loading.load_access_key
111
112
  Oboe::Inst.load_instrumentation
112
113
  Oboe::Rails.load_instrumentation
@@ -115,7 +116,8 @@ if defined?(::Rails)
115
116
  end
116
117
  end
117
118
  else
118
- Oboe::Loading.setup_logger
119
+ Oboe.logger = ::Rails.logger if ::Rails.logger
120
+
119
121
  Oboe::Rails.load_initializer
120
122
  Oboe::Loading.load_access_key
121
123
 
@@ -0,0 +1,63 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module Sinatra
6
+ module Base
7
+ def self.included(klass)
8
+ ::Oboe::Util.method_alias(klass, :dispatch!, ::Sinatra::Base)
9
+ ::Oboe::Util.method_alias(klass, :handle_exception!, ::Sinatra::Base)
10
+ end
11
+
12
+ def dispatch_with_oboe
13
+ if Oboe.tracing?
14
+ report_kvs = {}
15
+
16
+ report_kvs[:Controller] = self.class
17
+ report_kvs[:Action] = env['PATH_INFO']
18
+
19
+ # Fall back to the raw tracing API so we can pass KVs
20
+ # back on exit (a limitation of the Oboe::API.trace
21
+ # block method) This removes the need for an info
22
+ # event to send additonal KVs
23
+ ::Oboe::API.log_entry('sinatra', {})
24
+
25
+ begin
26
+ dispatch_without_oboe
27
+ ensure
28
+ ::Oboe::API.log_exit('sinatra', report_kvs)
29
+ end
30
+ else
31
+ dispatch_without_oboe
32
+ end
33
+ end
34
+
35
+ def handle_exception_with_oboe(boom)
36
+ Oboe::API.log_exception(nil, boom) if Oboe.tracing?
37
+ handle_exception_without_oboe(boom)
38
+ end
39
+ end
40
+ end
41
+ end
42
+
43
+ if defined?(::Sinatra)
44
+ require 'oboe/inst/rack'
45
+ require 'oboe/frameworks/sinatra/templates'
46
+
47
+ Oboe.logger.info "[oboe/loading] Instrumenting Sinatra" if Oboe::Config[:verbose]
48
+
49
+ Oboe::Loading.load_access_key
50
+ Oboe::Inst.load_instrumentation
51
+
52
+ ::Sinatra::Base.use Oboe::Rack
53
+
54
+ # When in TEST environment, we load this instrumentation regardless.
55
+ # Otherwise, only when Padrino isn't around.
56
+ unless defined?(::Padrino) and not (ENV['RACK_ENV'] == "test")
57
+ # Padrino has 'enhanced' routes and rendering so the Sinatra
58
+ # instrumentation won't work anyways. Only load for pure Sinatra apps.
59
+ ::Oboe::Util.send_include(::Sinatra::Base, ::Oboe::Sinatra::Base)
60
+ ::Oboe::Util.send_include(::Sinatra::Templates, ::Oboe::Sinatra::Templates)
61
+ end
62
+ end
63
+
@@ -0,0 +1,56 @@
1
+ # Copyright (c) 2013 AppNeta, Inc.
2
+ # All rights reserved.
3
+
4
+ module Oboe
5
+ module Sinatra
6
+ module Templates
7
+ def self.included(klass)
8
+ ::Oboe::Util.method_alias(klass, :render, ::Sinatra::Templates)
9
+ end
10
+
11
+ def render_with_oboe(engine, data, options = {}, locals = {}, &block)
12
+ if Oboe.tracing?
13
+ report_kvs = {}
14
+
15
+ report_kvs[:engine] = engine
16
+ report_kvs[:template] = data
17
+
18
+ if Oboe::Context.tracing_layer_op?('render')
19
+ # For recursive calls to :render (for sub-partials and layouts),
20
+ # use method profiling.
21
+ begin
22
+ name = data
23
+ report_kvs[:FunctionName] = :render
24
+ report_kvs[:Class] = :Templates
25
+ report_kvs[:Module] = 'Sinatra::Templates'
26
+ report_kvs[:File] = __FILE__
27
+ report_kvs[:LineNumber] = __LINE__
28
+ rescue StandardError => e
29
+ ::Oboe.logger.debug e.message
30
+ ::Oboe.logger.debug e.backtrace.join(", ")
31
+ end
32
+
33
+ Oboe::API.profile(name, report_kvs, false) do
34
+ render_without_oboe(engine, data, options, locals, &block)
35
+ end
36
+
37
+ else
38
+ # Fall back to the raw tracing API so we can pass KVs
39
+ # back on exit (a limitation of the Oboe::API.trace
40
+ # block method) This removes the need for an info
41
+ # event to send additonal KVs
42
+ ::Oboe::API.log_entry('render', {}, 'render')
43
+
44
+ begin
45
+ render_without_oboe(engine, data, options, locals, &block)
46
+ ensure
47
+ ::Oboe::API.log_exit('render', report_kvs)
48
+ end
49
+ end
50
+ else
51
+ render_without_oboe(engine, data, options, locals, &block)
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -34,31 +34,33 @@ if Oboe::Config[:nethttp][:enabled]
34
34
  req['X-Trace'] = context unless blacklisted
35
35
  end
36
36
 
37
- # The actual net::http call
38
- resp = request_without_oboe(*args, &block)
39
-
40
- # Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
41
- unless blacklisted
42
- xtrace = resp.get_fields('X-Trace')
43
- xtrace = xtrace[0] if xtrace and xtrace.is_a?(Array)
44
-
45
- if Oboe::XTrace.valid?(xtrace) and Oboe.tracing?
46
-
47
- # Assure that we received back a valid X-Trace with the same task_id
48
- if task_id == Oboe::XTrace.task_id(xtrace)
49
- Oboe::Context.fromString(xtrace)
50
- else
51
- Oboe.logger.debug "Mismatched returned X-Trace ID : #{xtrace}"
37
+ begin
38
+ # The actual net::http call
39
+ resp = request_without_oboe(*args, &block)
40
+
41
+ # Re-attach net::http edge unless blacklisted and is a valid X-Trace ID
42
+ unless blacklisted
43
+ xtrace = resp.get_fields('X-Trace')
44
+ xtrace = xtrace[0] if xtrace and xtrace.is_a?(Array)
45
+
46
+ if Oboe::XTrace.valid?(xtrace) and Oboe.tracing?
47
+
48
+ # Assure that we received back a valid X-Trace with the same task_id
49
+ if task_id == Oboe::XTrace.task_id(xtrace)
50
+ Oboe::Context.fromString(xtrace)
51
+ else
52
+ Oboe.logger.debug "Mismatched returned X-Trace ID : #{xtrace}"
53
+ end
52
54
  end
53
55
  end
54
- end
56
+
57
+ opts['HTTPStatus'] = resp.code
55
58
 
56
- opts['HTTPStatus'] = resp.code
57
-
58
- # Log the info event with the KVs in opts
59
- Oboe::API.log('net-http', 'info', opts)
60
-
61
- next resp
59
+ next resp
60
+ ensure
61
+ # Log the info event with the KVs in opts
62
+ Oboe::API.log('net-http', 'info', opts)
63
+ end
62
64
  end
63
65
  end
64
66
 
@@ -71,7 +71,7 @@ module Oboe
71
71
  xtrace = e.instance_variable_get(:@xtrace)
72
72
  raise
73
73
  ensure
74
- result[1]['X-Trace'] = xtrace if Oboe::XTrace.valid?(xtrace)
74
+ result[1]['X-Trace'] = xtrace if result and Oboe::XTrace.valid?(xtrace)
75
75
  return result
76
76
  end
77
77
  end
@@ -37,12 +37,6 @@ module Oboe
37
37
  # instrumented libraries are already loaded...
38
38
  #
39
39
  module Loading
40
- def self.setup_logger
41
- if defined?(::Rails) and ::Rails.logger
42
- Oboe.logger = ::Rails.logger
43
- end
44
- end
45
-
46
40
  ##
47
41
  # Load the TraceView access key (either from system configuration file
48
42
  # or environment variable) and calculate internal RUM ID
@@ -55,7 +49,7 @@ module Oboe
55
49
  Oboe::Config[:rum_id] = Oboe::Util::Base64URL.encode(Digest::SHA1.digest("RUM" + Oboe::Config[:access_key]))
56
50
  else
57
51
  # ..else read from system-wide configuration file
58
- unless Oboe::Config.access_key
52
+ if Oboe::Config.access_key.empty?
59
53
  config_file = '/etc/tracelytics.conf'
60
54
  return unless File.exists?(config_file)
61
55
 
@@ -90,25 +84,9 @@ module Oboe
90
84
  Oboe.logger.fatal "[oboe/error] Couldn't load oboe api."
91
85
  end
92
86
  end
93
-
94
- ##
95
- # Load instrumentation for the various frameworks located in
96
- # lib/oboe/frameworks/*/*.rb
97
- #
98
- def self.load_framework_instrumentation
99
- pattern = File.join(File.dirname(__FILE__), 'frameworks/*/', '*.rb')
100
- Dir.glob(pattern) do |f|
101
- begin
102
- require f
103
- rescue => e
104
- Oboe.logger.error "[oboe/loading] Error loading framework file '#{f}' : #{e}"
105
- end
106
- end
107
- end
108
87
  end
109
88
  end
110
89
 
111
90
  Oboe::Loading.require_api
112
- Oboe::Loading.load_framework_instrumentation
113
91
  Oboe::Reporter.start
114
92
 
@@ -23,9 +23,22 @@ module Oboe
23
23
  end
24
24
 
25
25
  if cls.method_defined? method.to_sym or cls.private_method_defined? method.to_sym
26
- cls.class_eval do
27
- alias_method "#{method}_without_oboe", "#{method}"
28
- alias_method "#{method}", "#{method}_with_oboe"
26
+
27
+ # Strip '!' or '?' from method if present
28
+ safe_method_name = method.to_s.chop if method.to_s =~ /\?$|\!$/
29
+ safe_method_name ||= method
30
+
31
+ without_oboe = "#{safe_method_name}_without_oboe"
32
+ with_oboe = "#{safe_method_name}_with_oboe"
33
+
34
+ # Only alias if we haven't done so already
35
+ unless cls.method_defined? without_oboe.to_sym or
36
+ cls.private_method_defined? without_oboe.to_sym
37
+
38
+ cls.class_eval do
39
+ alias_method without_oboe, "#{method}"
40
+ alias_method "#{method}", with_oboe
41
+ end
29
42
  end
30
43
  else Oboe.logger.warn "[oboe/loading] Couldn't properly instrument #{name}. Partial traces may occur."
31
44
  end
@@ -4,9 +4,9 @@
4
4
  module Oboe
5
5
  module Version
6
6
  MAJOR = 2
7
- MINOR = 5
7
+ MINOR = 6
8
8
  PATCH = 0
9
- BUILD = 7
9
+ BUILD = 2
10
10
 
11
11
  STRING = [MAJOR, MINOR, PATCH, BUILD].compact.join('.')
12
12
  end
@@ -12,6 +12,9 @@ module Oboe
12
12
  #
13
13
  def valid?(xtrace)
14
14
  begin
15
+ # Shouldn't be nil
16
+ return false unless xtrace
17
+
15
18
  # The X-Trace ID shouldn't be an initialized empty ID
16
19
  return false if (xtrace =~ /^1b0000000/i) == 0
17
20
 
@@ -1,3 +1,5 @@
1
+ # This test Padrino stack file was taken from the padrino-core gem.
2
+ #
1
3
  PADRINO_ROOT = File.dirname(__FILE__) unless defined? PADRINO_ROOT
2
4
  # Remove this comment if you want do some like this: ruby PADRINO_ENV=test app.rb
3
5
  #
@@ -0,0 +1,20 @@
1
+ require 'sinatra'
2
+
3
+ class SinatraSimple < Sinatra::Base
4
+ set :reload, true
5
+
6
+ get "/" do
7
+ 'The magick number is: 2767356926488785838763860464013972991031534522105386787489885890443740254365!' # Change only the number!!!
8
+ end
9
+
10
+ get "/rand" do
11
+ rand(2 ** 256).to_s
12
+ end
13
+
14
+ get "/render" do
15
+ render :erb, "This is an erb render"
16
+ end
17
+ end
18
+
19
+ use SinatraSimple
20
+
@@ -0,0 +1,25 @@
1
+ unless (RUBY_VERSION =~ /^1.8/) == 0
2
+ require "minitest_helper"
3
+ require File.expand_path(File.dirname(__FILE__) + '/apps/padrino_simple')
4
+
5
+ describe Padrino do
6
+ before do
7
+ clear_all_traces
8
+ end
9
+
10
+ it "should trace a request to a simple padrino stack" do
11
+ @app = SimpleDemo
12
+
13
+ r = get "/render"
14
+
15
+ traces = get_all_traces
16
+ traces.count.must_equal 9
17
+
18
+ validate_outer_layers(traces, 'rack')
19
+
20
+ traces[1]['Layer'].must_equal "padrino"
21
+ traces[6]['Controller'].must_equal "SimpleDemo"
22
+ traces[7]['Label'].must_equal "info"
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,25 @@
1
+ require "minitest_helper"
2
+ require File.expand_path(File.dirname(__FILE__) + '/apps/sinatra_simple')
3
+
4
+ describe Sinatra do
5
+ before do
6
+ clear_all_traces
7
+ end
8
+
9
+ it "should trace a request to a simple sinatra stack" do
10
+ @app = SinatraSimple
11
+
12
+ r = get "/render"
13
+
14
+ traces = get_all_traces
15
+ traces.count.must_equal 9
16
+
17
+ validate_outer_layers(traces, 'rack')
18
+
19
+ traces[1]['Layer'].must_equal "sinatra"
20
+ traces[3]['Label'].must_equal "profile_entry"
21
+ traces[6]['Controller'].must_equal "SinatraSimple"
22
+ traces[7]['Label'].must_equal "info"
23
+ end
24
+ end
25
+
@@ -3,6 +3,10 @@ require "minitest/reporters"
3
3
 
4
4
  ENV["RACK_ENV"] = "test"
5
5
 
6
+ # FIXME: Temp hack to fix padrino-core calling RUBY_ENGINE when it's
7
+ # not defined under Ruby 1.8.7 and 1.9.3
8
+ RUBY_ENGINE = "ruby" unless defined?(RUBY_ENGINE)
9
+
6
10
  unless RUBY_VERSION =~ /^1.8/
7
11
  MiniTest::Reporters.use! MiniTest::Reporters::SpecReporter.new
8
12
  end
@@ -10,11 +14,11 @@ end
10
14
  require 'rubygems'
11
15
  require 'bundler'
12
16
 
13
- Bundler.require(:default, :test)
14
-
15
17
  # Preload memcache-client
16
18
  require 'memcache'
17
19
 
20
+ Bundler.require(:default, :test)
21
+
18
22
  @trace_dir = "/tmp/"
19
23
  $trace_file = @trace_dir + "trace_output.bson"
20
24
 
@@ -110,3 +114,30 @@ def layer_doesnt_have_key(traces, layer, key)
110
114
  has_key.must_equal false
111
115
  end
112
116
 
117
+ ##
118
+ # Sinatra and Padrino Related Helpers
119
+ #
120
+ # Taken from padrino-core gem
121
+ #
122
+
123
+ class Sinatra::Base
124
+ # Allow assertions in request context
125
+ include MiniTest::Assertions
126
+ end
127
+
128
+
129
+ class MiniTest::Spec
130
+ include Rack::Test::Methods
131
+
132
+ # Sets up a Sinatra::Base subclass defined with the block
133
+ # given. Used in setup or individual spec methods to establish
134
+ # the application.
135
+ def mock_app(base=Padrino::Application, &block)
136
+ @app = Sinatra.new(base, &block)
137
+ end
138
+
139
+ def app
140
+ Rack::Lint.new(@app)
141
+ end
142
+ end
143
+
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: oboe
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.5.0.7
4
+ version: 2.6.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Giacomo Lombardo
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-02-13 00:00:00.000000000 Z
12
+ date: 2014-03-10 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: rake
@@ -85,6 +85,8 @@ files:
85
85
  - lib/oboe/api/tracing.rb
86
86
  - lib/oboe/api/util.rb
87
87
  - lib/oboe/config.rb
88
+ - lib/oboe/frameworks/padrino.rb
89
+ - lib/oboe/frameworks/padrino/templates.rb
88
90
  - lib/oboe/frameworks/rails.rb
89
91
  - lib/oboe/frameworks/rails/helpers/rum/rum_ajax_header.js.erb
90
92
  - lib/oboe/frameworks/rails/helpers/rum/rum_footer.js.erb
@@ -99,6 +101,8 @@ files:
99
101
  - lib/oboe/frameworks/rails/inst/connection_adapters/oracle.rb
100
102
  - lib/oboe/frameworks/rails/inst/connection_adapters/postgresql.rb
101
103
  - lib/oboe/frameworks/rails/inst/connection_adapters/utils.rb
104
+ - lib/oboe/frameworks/sinatra.rb
105
+ - lib/oboe/frameworks/sinatra/templates.rb
102
106
  - lib/oboe/inst/cassandra.rb
103
107
  - lib/oboe/inst/dalli.rb
104
108
  - lib/oboe/inst/http.rb
@@ -121,6 +125,10 @@ files:
121
125
  - lib/rails/generators/oboe/templates/oboe_initializer.rb
122
126
  - oboe.gemspec
123
127
  - release.sh
128
+ - test/frameworks/apps/padrino_simple.rb
129
+ - test/frameworks/apps/sinatra_simple.rb
130
+ - test/frameworks/padrino_test.rb
131
+ - test/frameworks/sinatra_test.rb
124
132
  - test/instrumentation/cassandra_test.rb
125
133
  - test/instrumentation/dalli_test.rb
126
134
  - test/instrumentation/http_test.rb
@@ -142,8 +150,6 @@ files:
142
150
  - test/support/config_test.rb
143
151
  - test/support/srv1_localset_test.rb
144
152
  - test/support/xtrace_test.rb
145
- - test/frameworks/apps/padrino_simple.rb
146
- - test/frameworks/test_padrino.rb
147
153
  homepage: http://www.appneta.com/products/traceview/
148
154
  licenses:
149
155
  - AppNeta Open License, Version 1.0
@@ -169,8 +175,10 @@ signing_key:
169
175
  specification_version: 4
170
176
  summary: AppNeta TraceView performance instrumentation gem for Ruby
171
177
  test_files:
178
+ - test/frameworks/padrino_test.rb
179
+ - test/frameworks/sinatra_test.rb
180
+ - test/frameworks/apps/sinatra_simple.rb
172
181
  - test/frameworks/apps/padrino_simple.rb
173
- - test/frameworks/test_padrino.rb
174
182
  - test/minitest_helper.rb
175
183
  - test/instrumentation/mongo_test.rb
176
184
  - test/instrumentation/redis_hashes_test.rb
@@ -1,32 +0,0 @@
1
- require "minitest_helper"
2
-
3
- describe Padrino do
4
- before do
5
- clear_all_traces
6
- end
7
-
8
- it "should do this" do
9
-
10
- mock_app do
11
- get("/") { render :erb, "ok" }
12
- end
13
- debugger
14
- r = get "/"
15
-
16
- traces = get_all_traces
17
- traces.count.must_equal 5
18
-
19
- validate_outer_layers(traces, 'dalli_test')
20
-
21
- traces[1].has_key?("KVOp").must_equal true
22
- traces[1].has_key?("KVKey").must_equal true
23
- traces[1]['Layer'].must_equal "memcache"
24
- traces[1]['KVKey'].must_equal "some_key"
25
-
26
- traces[2]['Layer'].must_equal "memcache"
27
- traces[2]['Label'].must_equal "info"
28
- traces[2].has_key?('KVHit')
29
-
30
- end
31
- end
32
-