copperegg-apm 1.0.0.pre6 → 1.0.0.pre7
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/README.md +70 -1
- data/copperegg_apm_test.db +0 -0
- data/lib/copperegg/apm.rb +1 -0
- data/lib/copperegg/apm/benchmark.rb +2 -2
- data/lib/copperegg/apm/configuration.rb +21 -5
- data/lib/copperegg/apm/railtie.rb +1 -1
- data/lib/copperegg/apm/rum.rb +15 -16
- data/lib/copperegg/apm/rum_blender.rb +51 -0
- data/lib/copperegg/apm/version.rb +1 -1
- data/spec/rum_spec.rb +4 -4
- metadata +4 -4
- data/lib/copperegg/apm/rum_middleware.rb +0 -45
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b6e3a0e3531849de3332f35761ab4e58d19e0b21
|
4
|
+
data.tar.gz: 21a430c08d341f29129701aeb46366f12df4ba96
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: bf59d18d0970a2eb9b4783e6d4233c7e311de3e80260d335656d93b59172a8b278ddee6c4035773bd02927e04a5a01fd0a5c433b318bc4fcee28bf14f760b3de
|
7
|
+
data.tar.gz: abcfa2620a899fba57a03015cc376e48d3f2e9a2092174885735d0257f368f6e05300e094f788445b4f50ccfeac329c17d4ac2b7e9fa9fd8cec991eec7ad5f1b
|
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
# CopperEgg APM
|
2
2
|
|
3
|
-
Monitor the performance of your application with code instrumentation and
|
3
|
+
Monitor the performance of your application with code instrumentation, exception aggregation, and real user monitoring.
|
4
4
|
|
5
5
|
**Code instrumentation** measures the elapsed time used to execute a SQL statement, outbound HTTP request, or method call.
|
6
6
|
|
7
7
|
**Exception aggregation** monitors the number and type of exceptions occurring in your code.
|
8
8
|
|
9
|
+
**Real User Monitoring (RUM)** provides metrics for your we application as it runs within web browsers from the perspective of the end user.
|
10
|
+
|
9
11
|
## Getting Started
|
10
12
|
|
11
13
|
### Prerequisites
|
@@ -177,6 +179,73 @@ Outbound HTTP requests performed within your project will be benchmarked from an
|
|
177
179
|
|
178
180
|
When exception benchmarking is enabled, any exception raised in your project will be aggregated by class, source location, and system.
|
179
181
|
|
182
|
+
## Real User Monitoring
|
183
|
+
|
184
|
+
Browser monitoring is added to your HTML pages using either Rack middleware or a helper method.
|
185
|
+
|
186
|
+
### Rails
|
187
|
+
|
188
|
+
For Rails projects, you can automatically monitor browser performance by setting the configuration directive `benchmark_browser`:
|
189
|
+
|
190
|
+
```ruby
|
191
|
+
config.benchmark_browser = true
|
192
|
+
```
|
193
|
+
|
194
|
+
This will add the `CopperEgg::APM::RUMBlender` to the bottom of the middleware stack.
|
195
|
+
|
196
|
+
Alternatively, in the Rails configuration, you can insert this anywhere in your middleware stack. For example:
|
197
|
+
|
198
|
+
```ruby
|
199
|
+
config.middleware.insert_after ActionDispatch::ParamsParser, CopperEgg::APM::RUMBlender
|
200
|
+
```
|
201
|
+
|
202
|
+
If you prefer to add RUM to your HTML pages manually, you can call the helper method `ce_rum_javascript_tag` in your HTML templates:
|
203
|
+
|
204
|
+
```ruby
|
205
|
+
<%= ce_rum_javascript_tag %>
|
206
|
+
```
|
207
|
+
|
208
|
+
For versions prior to 3.2, you will need to include the `CopperEgg::APM::RUM` module into your helper modules:
|
209
|
+
|
210
|
+
```ruby
|
211
|
+
module ApplicationHelper
|
212
|
+
include CopperEgg::APM::RUM
|
213
|
+
```
|
214
|
+
|
215
|
+
Alternatively, you can include the module in your controllers:
|
216
|
+
|
217
|
+
```ruby
|
218
|
+
class UsersController < ActionController::Base
|
219
|
+
helper CopperEgg::APM::RUM
|
220
|
+
```
|
221
|
+
|
222
|
+
### Sinatra
|
223
|
+
|
224
|
+
The following is an example of adding RUM to your Sinatra app:
|
225
|
+
|
226
|
+
```ruby
|
227
|
+
require 'sinatra'
|
228
|
+
require 'copperegg_apm_config'
|
229
|
+
|
230
|
+
use Rack::Lint
|
231
|
+
use CopperEgg::APM::RUM
|
232
|
+
|
233
|
+
get '/hello' do
|
234
|
+
'Hello World'
|
235
|
+
end
|
236
|
+
```
|
237
|
+
|
238
|
+
### Other Rack-based Projects
|
239
|
+
|
240
|
+
For other Rack-based projects, you can add RUMBlender in your `config.ru` file like so:
|
241
|
+
|
242
|
+
```ruby
|
243
|
+
require 'copperegg_apm_config'
|
244
|
+
|
245
|
+
use CopperEgg::APM::RUMBlender
|
246
|
+
run MyRackApplication
|
247
|
+
```
|
248
|
+
|
180
249
|
## Disable Gem Functionality
|
181
250
|
|
182
251
|
To disable all functionality of this gem, call `config.disable` in the configuration block and then restart your application:
|
data/copperegg_apm_test.db
CHANGED
Binary file
|
data/lib/copperegg/apm.rb
CHANGED
@@ -54,8 +54,8 @@ module CopperEgg
|
|
54
54
|
def benchmarkable_methods
|
55
55
|
return @@benchmarkable_methods if @@benchmarkable_methods.size > 0
|
56
56
|
|
57
|
-
if defined?(::Rails) && Rails.respond_to?(:application) && Rails.application.respond_to?(:eager_load!)
|
58
|
-
Rails.application.eager_load!
|
57
|
+
if defined?(::Rails) && ::Rails.respond_to?(:application) && ::Rails.application.respond_to?(:eager_load!)
|
58
|
+
::Rails.application.eager_load!
|
59
59
|
end
|
60
60
|
|
61
61
|
ObjectSpace.each_object(Class) do |class_or_module|
|
@@ -19,6 +19,7 @@ module CopperEgg
|
|
19
19
|
@@benchmark_active_record = false
|
20
20
|
@@benchmark_http = true
|
21
21
|
@@benchmark_exceptions = true
|
22
|
+
@@benchmark_browser = false
|
22
23
|
@@benchmark_methods_level = :disabled
|
23
24
|
@@only_methods = []
|
24
25
|
@@exclude_methods = []
|
@@ -105,6 +106,15 @@ module CopperEgg
|
|
105
106
|
@@benchmark_exceptions
|
106
107
|
end
|
107
108
|
|
109
|
+
def self.benchmark_browser=(boolean)
|
110
|
+
raise ConfigurationError.new("Boolean expected for benchmark_browser") if boolean != true && boolean != false
|
111
|
+
@@benchmark_browser = boolean
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.benchmark_browser?
|
115
|
+
@@benchmark_browser
|
116
|
+
end
|
117
|
+
|
108
118
|
def self.benchmark_methods(level, options={})
|
109
119
|
raise ConfigurationError.new("Method benchmark level can only be :disabled, :basic, :moderate, :full, or :custom") if !BENCHMARK_METHOD_LEVELS.include?(level)
|
110
120
|
|
@@ -159,7 +169,7 @@ module CopperEgg
|
|
159
169
|
|
160
170
|
if @@app_root.empty?
|
161
171
|
@@app_root = if defined?(::Rails) && Rails.respond_to?(:root)
|
162
|
-
Rails.root.to_s
|
172
|
+
::Rails.root.to_s
|
163
173
|
elsif defined?(RAILS_ROOT)
|
164
174
|
RAILS_ROOT
|
165
175
|
else
|
@@ -167,14 +177,20 @@ module CopperEgg
|
|
167
177
|
end
|
168
178
|
end
|
169
179
|
|
170
|
-
if @@disabled
|
171
|
-
@@benchmark_sql = @@benchmark_active_record = @@benchmark_http = @@benchmark_exceptions = false
|
180
|
+
if @@disabled || @@instrument_key.empty?
|
181
|
+
@@benchmark_sql = @@benchmark_active_record = @@benchmark_http = @@benchmark_exceptions = @@benchmark_browser = false
|
172
182
|
@@benchmark_methods_level = :disabled
|
173
183
|
@@only_methods = []
|
174
184
|
@@exclude_methods = []
|
175
185
|
@@include_methods = []
|
176
|
-
|
177
|
-
|
186
|
+
else
|
187
|
+
if @@benchmark_methods_level != :disabled
|
188
|
+
CopperEgg::APM.add_method_benchmarking
|
189
|
+
end
|
190
|
+
|
191
|
+
if @@benchmark_browser && defined?(::Rails) && ::Rails.respond_to?(:configuration) && ::Rails.configuration.respond_to?(:middleware) && ::Rails.configuration.middleware.respond_to?(:use)
|
192
|
+
::Rails.configuration.middleware.use CopperEgg::APM::RUMBlender
|
193
|
+
end
|
178
194
|
end
|
179
195
|
end
|
180
196
|
|
data/lib/copperegg/apm/rum.rb
CHANGED
@@ -1,23 +1,22 @@
|
|
1
1
|
module CopperEgg
|
2
2
|
module APM
|
3
|
-
module
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module RUM
|
4
|
+
def ce_rum_javascript_tag
|
5
|
+
tag = %Q(
|
6
|
+
<script type="text/javascript">
|
7
|
+
var BACON = BACON || {};
|
8
8
|
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
BACON.id = '#{Configuration.instrument_key}';
|
10
|
+
BACON.short_url = #{Configuration.rum_short_url};
|
11
|
+
BACON.beaconUrl = '#{Configuration.rum_beacon_url}';
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
)
|
20
|
-
script.respond_to?(:html_safe) ? script.html_safe : script
|
13
|
+
BACON.starttime = new Date().getTime();
|
14
|
+
(function(d, s) { var js = d.createElement(s);
|
15
|
+
js.async = true; js.src = "http://cdn.copperegg.com/rum/bacon.min.js";
|
16
|
+
var s = d.getElementsByTagName(s)[0]; s.parentNode.insertBefore(js, s);
|
17
|
+
})(document, "script");
|
18
|
+
</script>)
|
19
|
+
tag.respond_to?(:html_safe) ? tag.html_safe : tag
|
21
20
|
end
|
22
21
|
end
|
23
22
|
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'rack'
|
2
|
+
|
3
|
+
module CopperEgg
|
4
|
+
module APM
|
5
|
+
class RUMBlender
|
6
|
+
include RUM
|
7
|
+
RUM_BLENDED_KEY = 'THIS_RUM_BLENDED_FOR_YOU_BY_COPPEREGG'
|
8
|
+
|
9
|
+
def initialize(app)
|
10
|
+
@app = app
|
11
|
+
end
|
12
|
+
|
13
|
+
def call(env)
|
14
|
+
status, headers, response = @app.call(env)
|
15
|
+
|
16
|
+
if status != 200 || env[RUM_BLENDED_KEY] || !CopperEgg::APM::Configuration.benchmark_browser? || !html_request?(headers)
|
17
|
+
return [status, headers, response]
|
18
|
+
else
|
19
|
+
html = ''
|
20
|
+
response.each {|part| html << part}
|
21
|
+
open_head_tag_index = html.index /<head[^>]*>/
|
22
|
+
close_head_tag_index = html.index '</head>'
|
23
|
+
open_body_tag_index = html.index /<body[^>]*>/
|
24
|
+
close_body_tag_index = html.index '</body>'
|
25
|
+
|
26
|
+
if open_head_tag_index && open_head_tag_index < close_head_tag_index.to_i && open_head_tag_index < open_body_tag_index.to_i
|
27
|
+
html.sub!(/<head[^>]*>/) do |match|
|
28
|
+
match.to_s.insert(-1, ce_rum_javascript_tag)
|
29
|
+
end
|
30
|
+
elsif open_body_tag_index && open_body_tag_index < close_body_tag_index.to_i
|
31
|
+
html.sub!(/<body[^>]*>/) do |match|
|
32
|
+
match.to_s.insert(-1, ce_rum_javascript_tag)
|
33
|
+
end
|
34
|
+
else
|
35
|
+
return [status, headers, response]
|
36
|
+
end
|
37
|
+
|
38
|
+
headers['Content-Length'] = html.length if headers['Content-Length']
|
39
|
+
response = Rack::Response.new(html, status, headers)
|
40
|
+
response.finish
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def html_request?(headers)
|
47
|
+
headers["Content-Type"].to_s =~ /text\/html/ && !(headers['Content-Disposition'].to_s =~ /attachment/)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
data/spec/rum_spec.rb
CHANGED
@@ -2,17 +2,17 @@
|
|
2
2
|
require 'spec_helper'
|
3
3
|
|
4
4
|
class String
|
5
|
-
include CopperEgg::APM::
|
5
|
+
include CopperEgg::APM::RUM
|
6
6
|
end
|
7
7
|
|
8
|
-
describe CopperEgg::APM::
|
9
|
-
describe "#
|
8
|
+
describe CopperEgg::APM::RUM do
|
9
|
+
describe "#ce_rum_javascript_tag" do
|
10
10
|
before do
|
11
11
|
CopperEgg::APM::Configuration.rum_short_url = true
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should return javascript" do
|
15
|
-
javascript = "".
|
15
|
+
javascript = "".ce_rum_javascript_tag
|
16
16
|
|
17
17
|
expect(javascript).to match(/^[\s\n]*<script type="text\/javascript">.*<\/script>[\s\n]*$/m)
|
18
18
|
expect(javascript.include?("BACON.id = '#{CopperEgg::APM::Configuration.instrument_key}';")).to be_true
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: copperegg-apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.0.
|
4
|
+
version: 1.0.0.pre7
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Bradford
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-06-
|
11
|
+
date: 2013-06-06 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -209,7 +209,7 @@ files:
|
|
209
209
|
- ./lib/copperegg/apm/railtie.rb
|
210
210
|
- ./lib/copperegg/apm/restclient/request.rb
|
211
211
|
- ./lib/copperegg/apm/rum.rb
|
212
|
-
- ./lib/copperegg/apm/
|
212
|
+
- ./lib/copperegg/apm/rum_blender.rb
|
213
213
|
- ./lib/copperegg/apm/sqlite3/database.rb
|
214
214
|
- ./lib/copperegg/apm/tasks.rb
|
215
215
|
- ./lib/copperegg/apm/typhoeus/hydra.rb
|
@@ -293,7 +293,7 @@ rubyforge_project:
|
|
293
293
|
rubygems_version: 2.0.3
|
294
294
|
signing_key:
|
295
295
|
specification_version: 4
|
296
|
-
summary: copperegg-apm-1.0.0.
|
296
|
+
summary: copperegg-apm-1.0.0.pre7
|
297
297
|
test_files:
|
298
298
|
- spec/action_controller_spec.rb
|
299
299
|
- spec/apm_spec.rb
|
@@ -1,45 +0,0 @@
|
|
1
|
-
require 'rack'
|
2
|
-
|
3
|
-
module CopperEgg
|
4
|
-
module APM
|
5
|
-
class RumMiddleware
|
6
|
-
RUM_INJECTED_KEY = "COPPEREGG_APM_RUM_INJECTED"
|
7
|
-
|
8
|
-
def initialize(app)
|
9
|
-
@app = app
|
10
|
-
end
|
11
|
-
|
12
|
-
def call(evn)
|
13
|
-
status, headers, response = @app.call(env)
|
14
|
-
|
15
|
-
if status != 200 || rum_injected?(env) || !html_request?(env)
|
16
|
-
return [status, headers, response]
|
17
|
-
elsif has_head_tag?(response)
|
18
|
-
# if html request, extract <head>...</head> from request
|
19
|
-
|
20
|
-
# if <head> is extracted, insert rum <script> tag at the bottom
|
21
|
-
else
|
22
|
-
return [status, headers, response]
|
23
|
-
end
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def rum_injected?(env)
|
29
|
-
env[RUM_INJECTED_KEY]
|
30
|
-
end
|
31
|
-
|
32
|
-
def html_request?(env)
|
33
|
-
env["Content-Type"] && env["Content-Type"] =~ /text\/html/
|
34
|
-
end
|
35
|
-
|
36
|
-
def has_head_tag?(response)
|
37
|
-
|
38
|
-
end
|
39
|
-
|
40
|
-
def inject_rum(response, headers)
|
41
|
-
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|