newrelic_rpm 4.0.0.332 → 4.1.0.333
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.yardopts +0 -1
- data/CHANGELOG.md +22 -0
- data/LICENSE +1 -27
- data/README.md +4 -57
- data/lib/new_relic/agent.rb +0 -1
- data/lib/new_relic/agent/attribute_filter.rb +0 -1
- data/lib/new_relic/agent/configuration/default_source.rb +3 -32
- data/lib/new_relic/agent/error_collector.rb +0 -2
- data/lib/new_relic/agent/http_clients/curb_wrappers.rb +1 -1
- data/lib/new_relic/agent/http_clients/typhoeus_wrappers.rb +1 -1
- data/lib/new_relic/agent/http_clients/uri_util.rb +12 -7
- data/lib/new_relic/agent/stats.rb +0 -14
- data/lib/new_relic/agent/stats_engine.rb +171 -3
- data/lib/new_relic/agent/supported_versions.rb +9 -9
- data/lib/new_relic/agent/traced_method_stack.rb +1 -1
- data/lib/new_relic/agent/transaction/attributes.rb +0 -2
- data/lib/new_relic/agent/transaction/external_request_segment.rb +1 -5
- data/lib/new_relic/agent/transaction/trace_node.rb +0 -10
- data/lib/new_relic/agent/transaction_sample_builder.rb +0 -3
- data/lib/new_relic/agent/transaction_sampler.rb +3 -13
- data/lib/new_relic/collection_helper.rb +0 -18
- data/lib/new_relic/control/frameworks/rails.rb +1 -21
- data/lib/new_relic/control/frameworks/rails3.rb +1 -1
- data/lib/new_relic/noticed_error.rb +1 -0
- data/lib/new_relic/version.rb +1 -1
- data/newrelic.yml +0 -4
- data/newrelic_rpm.gemspec +1 -1
- data/test/config/newrelic.yml +1 -1
- data/test/multiverse/lib/multiverse/runner.rb +9 -1
- data/test/multiverse/suites/active_record/config/newrelic.yml +0 -1
- data/test/multiverse/suites/agent_only/config/newrelic.yml +0 -1
- data/test/multiverse/suites/capistrano/config/newrelic.yml +0 -1
- data/test/multiverse/suites/capistrano2/config/newrelic.yml +0 -1
- data/test/multiverse/suites/curb/config/newrelic.yml +0 -1
- data/test/multiverse/suites/datamapper/config/newrelic.yml +0 -1
- data/test/multiverse/suites/deferred_instrumentation/config/newrelic.yml +0 -1
- data/test/multiverse/suites/delayed_job/config/newrelic.yml +0 -1
- data/test/multiverse/suites/excon/config/newrelic.yml +0 -1
- data/test/multiverse/suites/grape/config/newrelic.yml +0 -1
- data/test/multiverse/suites/high_security/config/newrelic.yml +0 -1
- data/test/multiverse/suites/httpclient/config/newrelic.yml +0 -1
- data/test/multiverse/suites/httprb/config/newrelic.yml +0 -1
- data/test/multiverse/suites/json/config/newrelic.yml +0 -1
- data/test/multiverse/suites/marshalling/config/newrelic.yml +0 -1
- data/test/multiverse/suites/mongo/config/newrelic.yml +0 -1
- data/test/multiverse/suites/net_http/config/newrelic.yml +0 -1
- data/test/multiverse/suites/padrino/config/newrelic.yml +0 -1
- data/test/multiverse/suites/rack/config/newrelic.yml +0 -1
- data/test/multiverse/suites/rails/config/newrelic.yml +0 -1
- data/test/multiverse/suites/rake/config/newrelic.yml +0 -1
- data/test/multiverse/suites/redis/config/newrelic.yml +0 -1
- data/test/multiverse/suites/resque/config/newrelic.yml +0 -1
- data/test/multiverse/suites/sequel/config/newrelic.yml +0 -1
- data/test/multiverse/suites/sidekiq/config/newrelic.yml +0 -1
- data/test/multiverse/suites/sinatra/config/newrelic.yml +0 -1
- data/test/multiverse/suites/typhoeus/config/newrelic.yml +0 -1
- data/test/multiverse/suites/yajl/config/newrelic.yml +0 -1
- data/test/multiverse/test/suite_examples/one/a/config/newrelic.yml +0 -1
- data/test/multiverse/test/suite_examples/one/b/config/newrelic.yml +0 -1
- data/test/new_relic/agent/agent/connect_test.rb +3 -12
- data/test/new_relic/agent/agent/start_test.rb +4 -2
- data/test/new_relic/agent/busy_calculator_test.rb +13 -5
- data/test/new_relic/agent/pipe_channel_manager_test.rb +3 -4
- data/test/new_relic/agent/stats_engine_test.rb +313 -1
- data/test/new_relic/agent/stats_test.rb +0 -20
- data/test/new_relic/agent/traced_method_stack_test.rb +2 -5
- data/test/new_relic/agent/transaction/external_request_segment_test.rb +5 -0
- data/test/new_relic/agent/transaction/trace_node_test.rb +0 -19
- data/test/new_relic/agent/transaction_sampler_test.rb +3 -6
- data/test/new_relic/collection_helper_test.rb +0 -39
- data/test/new_relic/control_test.rb +2 -4
- data/test/new_relic/license_test.rb +4 -14
- data/test/performance/suites/external_segment.rb +0 -2
- data/test/performance/suites/rack_middleware.rb +1 -3
- data/test/performance/suites/transaction_tracing.rb +0 -1
- metadata +2 -94
- data/lib/conditional_vendored_metric_parser.rb +0 -9
- data/lib/new_relic/agent/instrumentation/rubyprof.rb +0 -26
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +0 -188
- data/lib/new_relic/agent/transaction/developer_mode_sample_buffer.rb +0 -62
- data/lib/new_relic/merbtasks.rb +0 -10
- data/lib/new_relic/rack/developer_mode.rb +0 -321
- data/lib/new_relic/rack/developer_mode/segment_summary.rb +0 -56
- data/test/new_relic/agent/stats_engine/metric_stats_test.rb +0 -328
- data/test/new_relic/agent/transaction/developer_mode_sample_buffer_test.rb +0 -75
- data/test/new_relic/metric_parser/metric_parser_test.rb +0 -17
- data/test/new_relic/rack/developer_mode/segment_summary_test.rb +0 -96
- data/test/new_relic/rack/developer_mode_helper_test.rb +0 -136
- data/test/new_relic/rack/developer_mode_test.rb +0 -96
- data/ui/helpers/developer_mode_helper.rb +0 -325
- data/ui/helpers/google_pie_chart.rb +0 -54
- data/ui/views/layouts/newrelic_default.rhtml +0 -48
- data/ui/views/newrelic/_explain_plans.rhtml +0 -27
- data/ui/views/newrelic/_sample.rhtml +0 -20
- data/ui/views/newrelic/_segment.rhtml +0 -28
- data/ui/views/newrelic/_segment_limit_message.rhtml +0 -1
- data/ui/views/newrelic/_segment_row.rhtml +0 -12
- data/ui/views/newrelic/_show_sample_detail.rhtml +0 -24
- data/ui/views/newrelic/_show_sample_sql.rhtml +0 -24
- data/ui/views/newrelic/_show_sample_summary.rhtml +0 -3
- data/ui/views/newrelic/_sql_row.rhtml +0 -16
- data/ui/views/newrelic/_stack_trace.rhtml +0 -15
- data/ui/views/newrelic/_table.rhtml +0 -12
- data/ui/views/newrelic/explain_sql.rhtml +0 -43
- data/ui/views/newrelic/file/images/arrow-close.png +0 -0
- data/ui/views/newrelic/file/images/arrow-open.png +0 -0
- data/ui/views/newrelic/file/images/blue_bar.gif +0 -0
- data/ui/views/newrelic/file/images/file_icon.png +0 -0
- data/ui/views/newrelic/file/images/gray_bar.gif +0 -0
- data/ui/views/newrelic/file/images/new-relic-rpm-desktop.gif +0 -0
- data/ui/views/newrelic/file/images/new_relic_rpm_desktop.gif +0 -0
- data/ui/views/newrelic/file/images/textmate.png +0 -0
- data/ui/views/newrelic/file/javascript/jquery-1.4.2.js +0 -6243
- data/ui/views/newrelic/file/javascript/transaction_sample.js +0 -123
- data/ui/views/newrelic/file/stylesheets/style.css +0 -490
- data/ui/views/newrelic/index.rhtml +0 -70
- data/ui/views/newrelic/sample_not_found.rhtml +0 -2
- data/ui/views/newrelic/show_sample.rhtml +0 -81
- data/ui/views/newrelic/threads.rhtml +0 -45
- data/vendor/gems/metric_parser-0.1.0.pre1/.specification +0 -116
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/metric_parser.rb +0 -5
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser.rb +0 -70
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/action_mailer.rb +0 -18
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_merchant.rb +0 -35
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/active_record.rb +0 -37
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/apdex.rb +0 -93
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/background_transaction.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/client.rb +0 -50
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller.rb +0 -71
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_cpu.rb +0 -47
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/controller_ext.rb +0 -21
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database.rb +0 -52
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/database_pool.rb +0 -28
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net.rb +0 -32
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/dot_net_parser.rb +0 -21
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/errors.rb +0 -15
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/external.rb +0 -59
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/frontend.rb +0 -44
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/gc.rb +0 -24
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/hibernate_session.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +0 -35
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java_parser.rb +0 -21
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp.rb +0 -38
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/jsp_tag.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/mem_cache.rb +0 -56
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/metric_parser.rb +0 -138
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/middleware.rb +0 -33
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/nested.rb +0 -23
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/orm.rb +0 -31
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/other_transaction.rb +0 -44
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_context_listener.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_filter.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/servlet_init.rb +0 -11
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr.rb +0 -31
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/solr_request_handler.rb +0 -19
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring.rb +0 -58
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_controller.rb +0 -10
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/spring_view.rb +0 -10
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_action.rb +0 -24
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/struts_result.rb +0 -24
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/version.rb +0 -9
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +0 -74
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_frontend.rb +0 -22
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_service.rb +0 -18
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/web_transaction.rb +0 -137
@@ -1,188 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
require 'new_relic/language_support'
|
6
|
-
|
7
|
-
module NewRelic
|
8
|
-
module Agent
|
9
|
-
# @api public
|
10
|
-
class StatsEngine
|
11
|
-
# Handles methods related to actual Metric collection
|
12
|
-
# @api public
|
13
|
-
module MetricStats
|
14
|
-
SCOPE_PLACEHOLDER = '__SCOPE__'.freeze
|
15
|
-
|
16
|
-
# Update the unscoped metrics given in metric_names.
|
17
|
-
# metric_names may be either a single name, or an array of names.
|
18
|
-
#
|
19
|
-
# This is an internal method, subject to change at any time. Client apps
|
20
|
-
# and gems should use the public API (NewRelic::Agent.record_metric)
|
21
|
-
# instead.
|
22
|
-
#
|
23
|
-
# There are four ways to use this method:
|
24
|
-
#
|
25
|
-
# 1. With a numeric value, it will update the Stats objects associated
|
26
|
-
# with the given metrics by calling record_data_point(value, aux).
|
27
|
-
# aux will be treated in this case as the exclusive time associated
|
28
|
-
# with the call being recorded.
|
29
|
-
#
|
30
|
-
# 2. With a value of :apdex_s, :apdex_t, or :apdex_f, it will treat the
|
31
|
-
# associated stats as an Apdex metric, updating it to reflect the
|
32
|
-
# occurrence of a transaction falling into the given category.
|
33
|
-
# The aux value in this case should be the apdex threshold used in
|
34
|
-
# bucketing the request.
|
35
|
-
#
|
36
|
-
# 3. If a block is given, value and aux will be ignored, and instead the
|
37
|
-
# Stats object associated with each named unscoped metric will be
|
38
|
-
# yielded to the block for customized update logic.
|
39
|
-
#
|
40
|
-
# 4. If value is a Stats instance, it will be merged into the Stats
|
41
|
-
# associated with each named unscoped metric.
|
42
|
-
#
|
43
|
-
# If this method is called during a transaction, the metrics will be
|
44
|
-
# attached to the Transaction, and not merged into the global set until
|
45
|
-
# the end of the transaction.
|
46
|
-
#
|
47
|
-
# Otherwise, the metrics will be recorded directly into the global set
|
48
|
-
# of metrics, under a lock.
|
49
|
-
#
|
50
|
-
# @api private
|
51
|
-
#
|
52
|
-
def tl_record_unscoped_metrics(metric_names, value=nil, aux=nil, &blk)
|
53
|
-
state = NewRelic::Agent::TransactionState.tl_get
|
54
|
-
record_unscoped_metrics(state, metric_names, value, aux, &blk)
|
55
|
-
end
|
56
|
-
|
57
|
-
def record_unscoped_metrics(state, metric_names, value=nil, aux=nil, &blk)
|
58
|
-
txn = state.current_transaction
|
59
|
-
if txn
|
60
|
-
txn.metrics.record_unscoped(metric_names, value, aux, &blk)
|
61
|
-
else
|
62
|
-
specs = coerce_to_metric_spec_array(metric_names, nil)
|
63
|
-
with_stats_lock do
|
64
|
-
@stats_hash.record(specs, value, aux, &blk)
|
65
|
-
end
|
66
|
-
end
|
67
|
-
end
|
68
|
-
|
69
|
-
# Like tl_record_unscoped_metrics, but records a scoped metric as well.
|
70
|
-
#
|
71
|
-
# This is an internal method, subject to change at any time. Client apps
|
72
|
-
# and gems should use the public API (NewRelic::Agent.record_metric)
|
73
|
-
# instead.
|
74
|
-
#
|
75
|
-
# The given scoped_metric will be recoded as both a scoped *and* an
|
76
|
-
# unscoped metric. The summary_metrics will be recorded as unscoped
|
77
|
-
# metrics only.
|
78
|
-
#
|
79
|
-
# If called during a transaction, all metrics will be attached to the
|
80
|
-
# Transaction, and not merged into the global set of metrics until the
|
81
|
-
# end of the transaction.
|
82
|
-
#
|
83
|
-
# If called outside of a transaction, only the *unscoped* metrics will
|
84
|
-
# be recorded, directly into the global set of metrics (under a lock).
|
85
|
-
#
|
86
|
-
# @api private
|
87
|
-
#
|
88
|
-
def tl_record_scoped_and_unscoped_metrics(scoped_metric, summary_metrics=nil, value=nil, aux=nil, &blk)
|
89
|
-
state = NewRelic::Agent::TransactionState.tl_get
|
90
|
-
record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics, value, aux, &blk)
|
91
|
-
end
|
92
|
-
|
93
|
-
def record_scoped_and_unscoped_metrics(state, scoped_metric, summary_metrics=nil, value=nil, aux=nil, &blk)
|
94
|
-
txn = state.current_transaction
|
95
|
-
if txn
|
96
|
-
txn.metrics.record_scoped_and_unscoped(scoped_metric, value, aux, &blk)
|
97
|
-
if summary_metrics
|
98
|
-
txn.metrics.record_unscoped(summary_metrics, value, aux, &blk)
|
99
|
-
end
|
100
|
-
else
|
101
|
-
specs = coerce_to_metric_spec_array(scoped_metric, nil)
|
102
|
-
if summary_metrics
|
103
|
-
specs.concat(coerce_to_metric_spec_array(summary_metrics, nil))
|
104
|
-
end
|
105
|
-
with_stats_lock do
|
106
|
-
@stats_hash.record(specs, value, aux, &blk)
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
|
111
|
-
# Helper for recording a straight value into the count
|
112
|
-
def tl_record_supportability_metric_count(metric, value)
|
113
|
-
real_name = "Supportability/#{metric}"
|
114
|
-
tl_record_unscoped_metrics(real_name) do |stat|
|
115
|
-
stat.call_count = value
|
116
|
-
end
|
117
|
-
end
|
118
|
-
|
119
|
-
def reset!
|
120
|
-
with_stats_lock do
|
121
|
-
old = @stats_hash
|
122
|
-
@stats_hash = StatsHash.new
|
123
|
-
old
|
124
|
-
end
|
125
|
-
end
|
126
|
-
|
127
|
-
# merge data from previous harvests into this stats engine
|
128
|
-
def merge!(other_stats_hash)
|
129
|
-
with_stats_lock do
|
130
|
-
@stats_hash.merge!(other_stats_hash)
|
131
|
-
@stats_hash
|
132
|
-
end
|
133
|
-
end
|
134
|
-
|
135
|
-
def merge_transaction_metrics!(txn_metrics, scope)
|
136
|
-
with_stats_lock do
|
137
|
-
@stats_hash.merge_transaction_metrics!(txn_metrics, scope)
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
def harvest!
|
142
|
-
now = Time.now
|
143
|
-
snapshot = reset!
|
144
|
-
snapshot = apply_rules_to_metric_data(@metric_rules, snapshot)
|
145
|
-
snapshot.harvested_at = now
|
146
|
-
snapshot
|
147
|
-
end
|
148
|
-
|
149
|
-
def apply_rules_to_metric_data(rules_engine, stats_hash)
|
150
|
-
renamed_stats = NewRelic::Agent::StatsHash.new(stats_hash.started_at)
|
151
|
-
stats_hash.each do |spec, stats|
|
152
|
-
new_name = rules_engine.rename(spec.name)
|
153
|
-
unless new_name.nil?
|
154
|
-
new_spec = NewRelic::MetricSpec.new(new_name, spec.scope)
|
155
|
-
renamed_stats[new_spec].merge!(stats)
|
156
|
-
end
|
157
|
-
end
|
158
|
-
renamed_stats
|
159
|
-
end
|
160
|
-
|
161
|
-
def coerce_to_metric_spec_array(metric_names_or_specs, scope)
|
162
|
-
specs = []
|
163
|
-
Array(metric_names_or_specs).map do |name_or_spec|
|
164
|
-
case name_or_spec
|
165
|
-
when String
|
166
|
-
specs << NewRelic::MetricSpec.new(name_or_spec)
|
167
|
-
specs << NewRelic::MetricSpec.new(name_or_spec, scope) if scope
|
168
|
-
when NewRelic::MetricSpec
|
169
|
-
specs << name_or_spec
|
170
|
-
end
|
171
|
-
end
|
172
|
-
specs
|
173
|
-
end
|
174
|
-
|
175
|
-
# For use by test code only.
|
176
|
-
def clear_stats
|
177
|
-
reset!
|
178
|
-
NewRelic::Agent::BusyCalculator.reset
|
179
|
-
end
|
180
|
-
|
181
|
-
# For use by test code only.
|
182
|
-
def to_h
|
183
|
-
with_stats_lock { @stats_hash.to_h }
|
184
|
-
end
|
185
|
-
end
|
186
|
-
end
|
187
|
-
end
|
188
|
-
end
|
@@ -1,62 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
require 'new_relic/agent/transaction/transaction_sample_buffer'
|
6
|
-
|
7
|
-
module NewRelic
|
8
|
-
module Agent
|
9
|
-
class Transaction
|
10
|
-
class DeveloperModeSampleBuffer < TransactionSampleBuffer
|
11
|
-
|
12
|
-
CAPACITY = 100
|
13
|
-
|
14
|
-
def capacity
|
15
|
-
max_capacity
|
16
|
-
end
|
17
|
-
|
18
|
-
# Dev mode is allowed more than the typical upper limit.
|
19
|
-
# Sidestep normal cap by overriding max_capacity.
|
20
|
-
def max_capacity
|
21
|
-
CAPACITY
|
22
|
-
end
|
23
|
-
|
24
|
-
def harvest_samples
|
25
|
-
NO_SAMPLES
|
26
|
-
end
|
27
|
-
|
28
|
-
def enabled?
|
29
|
-
Agent.config[:developer_mode]
|
30
|
-
end
|
31
|
-
|
32
|
-
# Truncate to the last capacity samples we've received
|
33
|
-
def truncate_samples
|
34
|
-
@samples = @samples.last(capacity)
|
35
|
-
end
|
36
|
-
|
37
|
-
# We don't hold onto previously trapped transactions on harvest
|
38
|
-
# We've already got all the traces we want, thank you!
|
39
|
-
def store_previous(*)
|
40
|
-
end
|
41
|
-
|
42
|
-
# Captures the stack trace for a node
|
43
|
-
# This is expensive and not for production mode
|
44
|
-
def visit_node(node)
|
45
|
-
return unless enabled? && node
|
46
|
-
|
47
|
-
trace = strip_newrelic_frames(caller)
|
48
|
-
trace = trace.first(40) if trace.length > 40
|
49
|
-
node[:backtrace] = trace
|
50
|
-
end
|
51
|
-
|
52
|
-
def strip_newrelic_frames(trace)
|
53
|
-
while trace.first =~/\/lib\/new_relic\/agent\//
|
54
|
-
trace.shift
|
55
|
-
end
|
56
|
-
trace
|
57
|
-
end
|
58
|
-
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
end
|
data/lib/new_relic/merbtasks.rb
DELETED
@@ -1,10 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
|
5
|
-
namespace :newrelic do
|
6
|
-
desc "Install the developer mode newrelic.yml file"
|
7
|
-
task :default do
|
8
|
-
load File.expand_path(File.join(__FILE__,"..","..","install.rb"))
|
9
|
-
end
|
10
|
-
end
|
@@ -1,321 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
# This file is distributed under New Relic's license terms.
|
3
|
-
# See https://github.com/newrelic/rpm/blob/master/LICENSE for complete details.
|
4
|
-
require 'rack/request'
|
5
|
-
require 'rack/response'
|
6
|
-
require 'rack/file'
|
7
|
-
|
8
|
-
require 'conditional_vendored_metric_parser'
|
9
|
-
require 'new_relic/collection_helper'
|
10
|
-
require 'new_relic/metric_parser/metric_parser'
|
11
|
-
require 'new_relic/rack/agent_middleware'
|
12
|
-
require 'new_relic/agent/instrumentation/middleware_proxy'
|
13
|
-
|
14
|
-
module NewRelic
|
15
|
-
module Rack
|
16
|
-
# This middleware provides the 'developer mode' feature of newrelic_rpm,
|
17
|
-
# which allows you to see data about local web transactions in development
|
18
|
-
# mode immediately without needing to send this data to New Relic's servers.
|
19
|
-
#
|
20
|
-
# Enabling developer mode has serious performance and security impact, and
|
21
|
-
# thus you should never use this middleware in a production or non-local
|
22
|
-
# environment.
|
23
|
-
#
|
24
|
-
# This middleware should be automatically inserted in most contexts, but if
|
25
|
-
# automatic middleware insertion fails, you may manually insert it into your
|
26
|
-
# middleware chain.
|
27
|
-
#
|
28
|
-
# @api public
|
29
|
-
#
|
30
|
-
class DeveloperMode < AgentMiddleware
|
31
|
-
|
32
|
-
VIEW_PATH = File.expand_path('../../../../ui/views/' , __FILE__)
|
33
|
-
HELPER_PATH = File.expand_path('../../../../ui/helpers/', __FILE__)
|
34
|
-
require File.join(HELPER_PATH, 'developer_mode_helper.rb')
|
35
|
-
require 'new_relic/rack/developer_mode/segment_summary'
|
36
|
-
|
37
|
-
include NewRelic::DeveloperModeHelper
|
38
|
-
|
39
|
-
class << self
|
40
|
-
attr_writer :profiling_enabled
|
41
|
-
end
|
42
|
-
|
43
|
-
def self.profiling_enabled?
|
44
|
-
@profiling_enabled
|
45
|
-
end
|
46
|
-
|
47
|
-
def traced_call(env)
|
48
|
-
return @app.call(env) unless /^\/newrelic/ =~ ::Rack::Request.new(env).path_info
|
49
|
-
dup._call(env)
|
50
|
-
end
|
51
|
-
|
52
|
-
protected
|
53
|
-
|
54
|
-
def _call(env)
|
55
|
-
NewRelic::Agent.ignore_transaction
|
56
|
-
|
57
|
-
@req = ::Rack::Request.new(env)
|
58
|
-
@rendered = false
|
59
|
-
case @req.path_info
|
60
|
-
when /profile/
|
61
|
-
profile
|
62
|
-
when /file/
|
63
|
-
::Rack::File.new(VIEW_PATH).call(env)
|
64
|
-
when /index/
|
65
|
-
index
|
66
|
-
when /threads/
|
67
|
-
threads
|
68
|
-
when /reset/
|
69
|
-
reset
|
70
|
-
when /show_sample_detail/
|
71
|
-
show_sample_data
|
72
|
-
when /show_sample_summary/
|
73
|
-
show_sample_data
|
74
|
-
when /show_sample_sql/
|
75
|
-
show_sample_data
|
76
|
-
when /explain_sql/
|
77
|
-
explain_sql
|
78
|
-
when /^\/newrelic\/?$/
|
79
|
-
index
|
80
|
-
else
|
81
|
-
@app.call(env)
|
82
|
-
end
|
83
|
-
end
|
84
|
-
|
85
|
-
private
|
86
|
-
|
87
|
-
def index
|
88
|
-
get_samples
|
89
|
-
render(:index)
|
90
|
-
end
|
91
|
-
|
92
|
-
def reset
|
93
|
-
NewRelic::Agent.instance.transaction_sampler.reset!
|
94
|
-
NewRelic::Agent.instance.sql_sampler.reset!
|
95
|
-
::Rack::Response.new{|r| r.redirect('/newrelic/')}.finish
|
96
|
-
end
|
97
|
-
|
98
|
-
def explain_sql
|
99
|
-
get_segment
|
100
|
-
|
101
|
-
return render(:sample_not_found) unless @sample
|
102
|
-
|
103
|
-
@sql = @segment[:sql]
|
104
|
-
@trace = @segment[:backtrace]
|
105
|
-
|
106
|
-
if NewRelic::Agent.agent.record_sql == :obfuscated
|
107
|
-
@obfuscated_sql = @segment.obfuscated_sql
|
108
|
-
end
|
109
|
-
|
110
|
-
_headers, explanations = @segment.explain_sql
|
111
|
-
if explanations
|
112
|
-
@explanation = explanations
|
113
|
-
if !@explanation.blank?
|
114
|
-
first_row = @explanation.first
|
115
|
-
# Show the standard headers if it looks like a mysql explain plan
|
116
|
-
# Otherwise show blank headers
|
117
|
-
if first_row.length < NewRelic::MYSQL_EXPLAIN_COLUMNS.length
|
118
|
-
@row_headers = nil
|
119
|
-
else
|
120
|
-
@row_headers = NewRelic::MYSQL_EXPLAIN_COLUMNS
|
121
|
-
end
|
122
|
-
end
|
123
|
-
end
|
124
|
-
render(:explain_sql)
|
125
|
-
end
|
126
|
-
|
127
|
-
def profile
|
128
|
-
should_be_on = (params['start'] == 'true')
|
129
|
-
NewRelic::Rack::DeveloperMode.profiling_enabled = should_be_on
|
130
|
-
|
131
|
-
index
|
132
|
-
end
|
133
|
-
|
134
|
-
def threads
|
135
|
-
render(:threads)
|
136
|
-
end
|
137
|
-
|
138
|
-
def render(view, layout=true)
|
139
|
-
add_rack_array = true
|
140
|
-
if view.is_a? Hash
|
141
|
-
layout = false
|
142
|
-
if view[:object]
|
143
|
-
# object *is* used here, as it is capture in the binding below
|
144
|
-
object = view[:object]
|
145
|
-
end
|
146
|
-
|
147
|
-
if view[:collection]
|
148
|
-
return view[:collection].map do |obj|
|
149
|
-
render({:partial => view[:partial], :object => obj})
|
150
|
-
end.join(' ')
|
151
|
-
end
|
152
|
-
|
153
|
-
if view[:partial]
|
154
|
-
add_rack_array = false
|
155
|
-
view = "_#{view[:partial]}"
|
156
|
-
end
|
157
|
-
end
|
158
|
-
binding = Proc.new {}.binding
|
159
|
-
if layout
|
160
|
-
body = render_with_layout(view) do
|
161
|
-
render_without_layout(view, binding)
|
162
|
-
end
|
163
|
-
else
|
164
|
-
body = render_without_layout(view, binding)
|
165
|
-
end
|
166
|
-
if add_rack_array
|
167
|
-
::Rack::Response.new(body, 200, {'Content-Type' => 'text/html'}).finish
|
168
|
-
else
|
169
|
-
body
|
170
|
-
end
|
171
|
-
end
|
172
|
-
|
173
|
-
# You have to call this with a block - the contents returned from
|
174
|
-
# that block are interpolated into the layout
|
175
|
-
def render_with_layout(view)
|
176
|
-
body = ERB.new(File.read(File.join(VIEW_PATH, 'layouts/newrelic_default.rhtml')))
|
177
|
-
body.result(Proc.new {}.binding)
|
178
|
-
end
|
179
|
-
|
180
|
-
# you have to pass a binding to this (a proc) so that ERB can have
|
181
|
-
# access to helper functions and local variables
|
182
|
-
def render_without_layout(view, binding)
|
183
|
-
ERB.new(File.read(File.join(VIEW_PATH, 'newrelic', view.to_s + '.rhtml')), nil, nil, 'frobnitz').result(binding)
|
184
|
-
end
|
185
|
-
|
186
|
-
def content_tag(tag, contents, opts={})
|
187
|
-
opt_values = opts.map {|k, v| "#{k}=\"#{v}\"" }.join(' ')
|
188
|
-
"<#{tag} #{opt_values}>#{contents}</#{tag}>"
|
189
|
-
end
|
190
|
-
|
191
|
-
def sample
|
192
|
-
@sample || @samples[0]
|
193
|
-
end
|
194
|
-
|
195
|
-
def params
|
196
|
-
@req.params
|
197
|
-
end
|
198
|
-
|
199
|
-
def segment
|
200
|
-
@segment
|
201
|
-
end
|
202
|
-
|
203
|
-
def show_sample_data
|
204
|
-
get_sample
|
205
|
-
|
206
|
-
return render(:sample_not_found) unless @sample
|
207
|
-
|
208
|
-
@request_params = request_attributes_for(@sample)
|
209
|
-
@custom_params = custom_attributes_for(@sample)
|
210
|
-
|
211
|
-
controller_metric = @sample.transaction_name
|
212
|
-
|
213
|
-
metric_parser = NewRelic::MetricParser::MetricParser.for_metric_named controller_metric
|
214
|
-
@sample_controller_name = metric_parser.controller_name
|
215
|
-
@sample_action_name = metric_parser.action_name
|
216
|
-
|
217
|
-
@sql_segments = sql_segments(@sample)
|
218
|
-
if params['d']
|
219
|
-
@sql_segments.sort!{|a,b| b.duration <=> a.duration }
|
220
|
-
end
|
221
|
-
|
222
|
-
sort_method = params['sort'] || :total_time
|
223
|
-
@profile_options = {:min_percent => 0.5, :sort_method => sort_method.to_sym}
|
224
|
-
|
225
|
-
render(:show_sample)
|
226
|
-
end
|
227
|
-
|
228
|
-
def get_samples
|
229
|
-
@samples = NewRelic::Agent.instance.transaction_sampler.dev_mode_sample_buffer.samples.select do |sample|
|
230
|
-
sample.transaction_name != nil
|
231
|
-
end
|
232
|
-
|
233
|
-
return @samples = @samples.sort_by(&:duration).reverse if params['h']
|
234
|
-
return @samples = @samples.sort{|x,y| x.params[:uri] <=> y.params[:uri]} if params['u']
|
235
|
-
@samples = @samples.reverse
|
236
|
-
end
|
237
|
-
|
238
|
-
def get_sample
|
239
|
-
get_samples
|
240
|
-
id = params['id']
|
241
|
-
sample_id = id.to_i
|
242
|
-
@samples.each do |s|
|
243
|
-
if s.sample_id == sample_id
|
244
|
-
@sample = s
|
245
|
-
return
|
246
|
-
end
|
247
|
-
end
|
248
|
-
end
|
249
|
-
|
250
|
-
def get_segment
|
251
|
-
get_sample
|
252
|
-
return unless @sample
|
253
|
-
|
254
|
-
segment_id = params['segment'].to_i
|
255
|
-
@segment = @sample.root_node.find_node(segment_id)
|
256
|
-
end
|
257
|
-
|
258
|
-
def custom_attributes_for(sample)
|
259
|
-
sample.attributes.custom_attributes_for(NewRelic::Agent::AttributeFilter::DST_DEVELOPER_MODE)
|
260
|
-
end
|
261
|
-
|
262
|
-
REQUEST_PARAMETERS_PREFIX = "request.parameters".freeze
|
263
|
-
|
264
|
-
def request_attributes_for(sample)
|
265
|
-
agent_attributes = sample.attributes.agent_attributes_for(NewRelic::Agent::AttributeFilter::DST_DEVELOPER_MODE)
|
266
|
-
agent_attributes.inject({}) do |memo, (key, value)|
|
267
|
-
memo[key] = value if key.to_s.start_with?(REQUEST_PARAMETERS_PREFIX)
|
268
|
-
memo
|
269
|
-
end
|
270
|
-
end
|
271
|
-
|
272
|
-
def breakdown_data(sample, limit = nil)
|
273
|
-
metric_hash = {}
|
274
|
-
sample.each_node_with_nest_tracking do |node|
|
275
|
-
unless node == sample.root_node
|
276
|
-
metric_name = node.metric_name
|
277
|
-
metric_hash[metric_name] ||= SegmentSummary.new(metric_name, sample)
|
278
|
-
metric_hash[metric_name] << node
|
279
|
-
metric_hash[metric_name]
|
280
|
-
end
|
281
|
-
end
|
282
|
-
|
283
|
-
data = metric_hash.values
|
284
|
-
|
285
|
-
data.sort! do |x,y|
|
286
|
-
y.exclusive_time <=> x.exclusive_time
|
287
|
-
end
|
288
|
-
|
289
|
-
if limit && data.length > limit
|
290
|
-
data = data[0..limit - 1]
|
291
|
-
end
|
292
|
-
|
293
|
-
# add one last node for the remaining time if any
|
294
|
-
remainder = sample.duration
|
295
|
-
data.each do |node|
|
296
|
-
remainder -= node.exclusive_time
|
297
|
-
end
|
298
|
-
|
299
|
-
if (remainder*1000).round > 0
|
300
|
-
remainder_summary = SegmentSummary.new('Remainder', sample)
|
301
|
-
remainder_summary.total_time = remainder_summary.exclusive_time = remainder
|
302
|
-
remainder_summary.call_count = 1
|
303
|
-
data << remainder_summary
|
304
|
-
end
|
305
|
-
|
306
|
-
data
|
307
|
-
end
|
308
|
-
|
309
|
-
# return an array of sql statements executed by this transaction
|
310
|
-
# each element in the array contains [sql, parent_segment_metric_name, duration]
|
311
|
-
def sql_segments(sample, show_non_sql_segments = true)
|
312
|
-
segments = []
|
313
|
-
sample.each_node do |segment|
|
314
|
-
segments << segment if segment[:sql] || segment[:sql_obfuscated] || (show_non_sql_segments && segment[:key])
|
315
|
-
end
|
316
|
-
segments
|
317
|
-
end
|
318
|
-
|
319
|
-
end
|
320
|
-
end
|
321
|
-
end
|