copperegg-apm 1.0.0.pre6 → 1.0.0.pre7
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.
- 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
|