newrelic_rpm 3.9.1.236 → 3.9.2.239
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +2 -4
- data/CHANGELOG +96 -2
- data/lib/new_relic/agent.rb +47 -4
- data/lib/new_relic/agent/agent.rb +51 -26
- data/lib/new_relic/agent/agent_logger.rb +4 -0
- data/lib/new_relic/agent/configuration.rb +2 -32
- data/lib/new_relic/agent/configuration/default_source.rb +153 -118
- data/lib/new_relic/agent/configuration/dotted_hash.rb +52 -0
- data/lib/new_relic/agent/configuration/environment_source.rb +1 -1
- data/lib/new_relic/agent/configuration/manager.rb +101 -2
- data/lib/new_relic/agent/configuration/manual_source.rb +17 -0
- data/lib/new_relic/agent/configuration/server_source.rb +12 -4
- data/lib/new_relic/agent/configuration/yaml_source.rb +46 -22
- data/lib/new_relic/agent/cross_app_monitor.rb +1 -1
- data/lib/new_relic/agent/cross_app_tracing.rb +1 -1
- data/lib/new_relic/agent/database/obfuscation_helpers.rb +55 -14
- data/lib/new_relic/agent/database/obfuscator.rb +22 -7
- data/lib/new_relic/agent/database/postgres_explain_obfuscator.rb +6 -8
- data/lib/new_relic/agent/error_collector.rb +24 -16
- data/lib/new_relic/agent/event_loop.rb +189 -0
- data/lib/new_relic/agent/instrumentation/action_controller_subscriber.rb +8 -17
- data/lib/new_relic/agent/instrumentation/active_record_helper.rb +1 -1
- data/lib/new_relic/agent/instrumentation/active_record_subscriber.rb +1 -1
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +17 -16
- data/lib/new_relic/agent/instrumentation/ignore_actions.rb +41 -0
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +0 -11
- data/lib/new_relic/agent/instrumentation/middleware_tracing.rb +1 -1
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +0 -8
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +1 -9
- data/lib/new_relic/agent/instrumentation/rails4/action_controller.rb +0 -18
- data/lib/new_relic/agent/instrumentation/rubyprof.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sidekiq.rb +1 -1
- data/lib/new_relic/agent/instrumentation/sinatra.rb +12 -1
- data/lib/new_relic/agent/instrumentation/sinatra/transaction_namer.rb +1 -1
- data/lib/new_relic/agent/method_tracer.rb +33 -39
- data/lib/new_relic/agent/new_relic_service.rb +35 -156
- data/lib/new_relic/agent/new_relic_service/encoders.rb +34 -0
- data/lib/new_relic/agent/new_relic_service/json_marshaller.rb +50 -0
- data/lib/new_relic/agent/new_relic_service/marshaller.rb +52 -0
- data/lib/new_relic/agent/new_relic_service/pruby_marshaller.rb +52 -0
- data/lib/new_relic/agent/threading/backtrace_node.rb +1 -1
- data/lib/new_relic/agent/traced_method_stack.rb +16 -2
- data/lib/new_relic/agent/transaction.rb +0 -4
- data/lib/new_relic/collection_helper.rb +2 -2
- data/lib/new_relic/control/frameworks/rails.rb +3 -0
- data/lib/new_relic/control/instrumentation.rb +6 -2
- data/lib/new_relic/json_wrapper.rb +47 -25
- data/lib/new_relic/language_support.rb +0 -4
- data/lib/new_relic/latest_changes.rb +2 -2
- data/lib/new_relic/rack/developer_mode.rb +4 -3
- data/lib/new_relic/recipes/capistrano3.rb +2 -2
- data/lib/new_relic/recipes/capistrano_legacy.rb +1 -1
- data/lib/new_relic/timer_lib.rb +1 -1
- data/lib/new_relic/version.rb +2 -2
- data/lib/tasks/config.html.erb +28 -0
- data/lib/tasks/config.rake +134 -0
- data/lib/tasks/config.text.erb +7 -0
- data/lib/tasks/install.rake +0 -63
- data/newrelic.yml +7 -0
- data/test/active_record_fixtures.rb +4 -4
- data/test/agent_helper.rb +58 -18
- data/test/environments/lib/environments/runner.rb +1 -1
- data/test/environments/rails21/Gemfile +1 -1
- data/test/environments/rails21/config/boot.rb +1 -1
- data/test/environments/rails22/Gemfile +1 -1
- data/test/environments/rails22/config/boot.rb +1 -1
- data/test/environments/rails23/config/boot.rb +2 -2
- data/test/environments/rails30/Gemfile +1 -1
- data/test/environments/rails31/Gemfile +1 -1
- data/test/environments/rails32/Gemfile +1 -1
- data/test/environments/rails40/Gemfile +1 -1
- data/test/environments/rails41/Gemfile +1 -1
- data/test/fixtures/cross_agent_tests/labels.json +104 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/README.md +23 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/back_quoted_identifiers.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/comment_delimiters_in_strings.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/double_quoted_identifiers.postgres.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.obfuscated +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comment_in_string.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_line_comments_with_quotes.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_cstyle.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.obfuscated +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_doubledash.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/end_of_query_comment_hash.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/escape_string_constants.postgres.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_double_quoted_string.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/malformed/unterminated_single_quoted_string.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_comments_and_quotes.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_comments_and_newlines.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/mixed_quotes_end_of_line_comments.sql +3 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/multiple_literal_types.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numbers_in_identifiers.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/numeric_literals.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/quote_delimiters_in_comments.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_double_quoted.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_single_quoted.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_backslash_and_twin_single_quotes.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_double_quote.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_newline.sql +2 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_embedded_single_quote.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_escaped_quotes.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_backslash.sql +4 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash.mysql.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_backslash_single_quoted.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_trailing_escaped_quote.sql +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.obfuscated +1 -0
- data/test/fixtures/cross_agent_tests/sql_obfuscation/string_with_twin_single_quotes.sql +1 -0
- data/test/multiverse/lib/multiverse/output_collector.rb +1 -1
- data/test/multiverse/lib/multiverse/runner.rb +1 -1
- data/test/multiverse/lib/multiverse/suite.rb +19 -4
- data/test/multiverse/suites/agent_only/audit_log_test.rb +1 -38
- data/test/multiverse/suites/agent_only/collector_exception_handling_test.rb +25 -35
- data/test/multiverse/suites/agent_only/config/newrelic.yml +2 -0
- data/test/multiverse/suites/agent_only/encoding_handling_test.rb +1 -0
- data/test/multiverse/suites/agent_only/harvest_timestamps_test.rb +1 -1
- data/test/multiverse/suites/agent_only/keepalive_test.rb +29 -0
- data/test/multiverse/suites/agent_only/labels_test.rb +89 -0
- data/test/multiverse/suites/agent_only/marshaling_test.rb +1 -3
- data/test/multiverse/suites/agent_only/service_timeout_test.rb +1 -1
- data/test/multiverse/suites/agent_only/start_up_test.rb +9 -1
- data/test/multiverse/suites/capistrano/config/deploy.rb +6 -2
- data/test/multiverse/suites/capistrano/deployment_test.rb +12 -4
- data/test/multiverse/suites/config_file_loading/config_file_loading_test.rb +29 -1
- data/test/multiverse/suites/curb/Envfile +6 -2
- data/test/multiverse/suites/datamapper/Envfile +0 -4
- data/test/multiverse/suites/deferred_instrumentation/Envfile +0 -4
- data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +1 -1
- data/test/multiverse/suites/excon/Envfile +5 -4
- data/test/multiverse/suites/excon/excon_test.rb +1 -1
- data/test/multiverse/suites/httpclient/Envfile +0 -4
- data/test/multiverse/suites/marshalling/Envfile +12 -0
- data/test/multiverse/suites/marshalling/config/newrelic.yml +20 -0
- data/test/multiverse/suites/marshalling/marshalling_test.rb +60 -0
- data/test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb +1 -1
- data/test/multiverse/suites/mongo/helpers/mongo_replica_set.rb +1 -1
- data/test/multiverse/suites/mongo/helpers/mongo_server.rb +4 -4
- data/test/multiverse/suites/padrino/Envfile +0 -5
- data/test/multiverse/suites/padrino/padrino_test.rb +1 -1
- data/test/multiverse/suites/rack/rack_auto_instrumentation_test.rb +1 -1
- data/test/multiverse/suites/rails/gc_instrumentation_test.rb +2 -1
- data/test/multiverse/suites/rails/ignore_test.rb +22 -0
- data/test/multiverse/suites/rails/rails2_app/config/boot.rb +2 -2
- data/test/multiverse/suites/rails/rails2_app/config/routes.rb +1 -0
- data/test/multiverse/suites/resque/Envfile +0 -4
- data/test/multiverse/suites/sequel/Envfile +0 -5
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +1 -1
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +1 -1
- data/test/multiverse/suites/sinatra/sinatra_test_cases.rb +22 -0
- data/test/multiverse/suites/typhoeus/Envfile +1 -4
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -13
- data/test/new_relic/agent/agent_logger_test.rb +11 -0
- data/test/new_relic/agent/agent_test.rb +43 -20
- data/test/new_relic/agent/audit_logger_test.rb +7 -3
- data/test/new_relic/agent/commands/thread_profiler_session_test.rb +0 -1
- data/test/new_relic/agent/commands/xray_session_collection_test.rb +1 -1
- data/test/new_relic/agent/configuration/dotted_hash_test.rb +53 -0
- data/test/new_relic/agent/configuration/manager_test.rb +99 -6
- data/test/new_relic/agent/configuration/manual_source_test.rb +18 -0
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +1 -1
- data/test/new_relic/agent/configuration/yaml_source_test.rb +8 -4
- data/test/new_relic/agent/database/sql_obfuscation_test.rb +76 -0
- data/test/new_relic/agent/database_test.rb +2 -38
- data/test/new_relic/agent/error_collector/notice_error_test.rb +21 -3
- data/test/new_relic/agent/error_collector_test.rb +15 -2
- data/test/new_relic/agent/event_loop_test.rb +202 -0
- data/test/new_relic/agent/instrumentation/active_record_helper_test.rb +4 -0
- data/test/new_relic/agent/instrumentation/controller_instrumentation_test.rb +283 -182
- data/test/new_relic/agent/method_tracer_test.rb +1 -2
- data/test/new_relic/agent/new_relic_service_test.rb +83 -27
- data/test/new_relic/agent/pipe_channel_manager_test.rb +6 -6
- data/test/new_relic/agent/rpm_agent_test.rb +1 -8
- data/test/new_relic/agent/sql_sampler_test.rb +10 -8
- data/test/new_relic/agent/threading/backtrace_service_test.rb +1 -1
- data/test/new_relic/agent/traced_method_stack_test.rb +45 -13
- data/test/new_relic/agent/transaction_sample_builder_test.rb +1 -2
- data/test/new_relic/agent/transaction_test.rb +3 -3
- data/test/new_relic/agent_test.rb +47 -8
- data/test/new_relic/collection_helper_test.rb +5 -5
- data/test/new_relic/control/instrumentation_test.rb +56 -0
- data/test/new_relic/control_test.rb +4 -3
- data/test/new_relic/fake_collector.rb +7 -2
- data/test/new_relic/http_client_test_cases.rb +4 -4
- data/test/new_relic/latest_changes_test.rb +3 -3
- data/test/new_relic/transaction_sample/segment_test.rb +0 -1
- data/test/new_relic/transaction_sample_test.rb +19 -2
- data/test/performance/lib/performance/runner.rb +4 -4
- data/test/performance/suites/marshalling.rb +46 -30
- data/test/performance/suites/sql_obfuscation.rb +30 -0
- data/test/test_helper.rb +1 -1
- data/ui/helpers/developer_mode_helper.rb +2 -2
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/java.rb +1 -1
- data/vendor/gems/metric_parser-0.1.0.pre1/lib/new_relic/metric_parser/view.rb +1 -1
- metadata +84 -3
- metadata.gz.sig +0 -0
- data/test/environments/rails23/config/environments/development.rb +0 -11
@@ -0,0 +1,52 @@
|
|
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/configuration'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Configuration
|
10
|
+
class DottedHash < ::Hash
|
11
|
+
def initialize(hash, keep_nesting=false)
|
12
|
+
# Add the hash keys to our collection explicitly so they survive the
|
13
|
+
# dot flattening. This is typical for full config source instances,
|
14
|
+
# but not for uses of DottedHash serializing for transmission.
|
15
|
+
self.merge!(hash) if keep_nesting
|
16
|
+
|
17
|
+
self.merge!(dot_flattened(hash))
|
18
|
+
DottedHash.symbolize(self)
|
19
|
+
end
|
20
|
+
|
21
|
+
def inspect
|
22
|
+
"#<#{self.class.name}:#{object_id} #{super}>"
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_hash
|
26
|
+
{}.replace(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
def self.symbolize(hash)
|
30
|
+
hash.keys.each do |key|
|
31
|
+
hash[key.to_sym] = hash.delete(key)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
protected
|
36
|
+
# turns {'a' => {'b' => 'c'}} into {'a.b' => 'c'}
|
37
|
+
def dot_flattened(nested_hash, names=[], result={})
|
38
|
+
nested_hash.each do |key, val|
|
39
|
+
next if val == nil
|
40
|
+
if val.respond_to?(:has_key?)
|
41
|
+
dot_flattened(val, names + [key], result)
|
42
|
+
else
|
43
|
+
result[(names + [key]).join('.')] = val
|
44
|
+
end
|
45
|
+
end
|
46
|
+
result
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -189,6 +189,101 @@ module NewRelic
|
|
189
189
|
end
|
190
190
|
end
|
191
191
|
|
192
|
+
MALFORMED_LABELS_WARNING = "Skipping malformed labels configuration"
|
193
|
+
PARSING_LABELS_FAILURE = "Failure during parsing labels. Ignoring and carrying on with connect."
|
194
|
+
|
195
|
+
MAX_LABEL_COUNT = 64
|
196
|
+
MAX_LABEL_LENGTH = 255
|
197
|
+
|
198
|
+
def parsed_labels
|
199
|
+
case NewRelic::Agent.config[:labels]
|
200
|
+
when String
|
201
|
+
parse_labels_from_string
|
202
|
+
else
|
203
|
+
parse_labels_from_dictionary
|
204
|
+
end
|
205
|
+
rescue => e
|
206
|
+
NewRelic::Agent.logger.error(PARSING_LABELS_FAILURE, e)
|
207
|
+
[]
|
208
|
+
end
|
209
|
+
|
210
|
+
def parse_labels_from_string
|
211
|
+
labels = NewRelic::Agent.config[:labels]
|
212
|
+
label_pairs = break_label_string_into_pairs(labels)
|
213
|
+
make_label_hash(label_pairs, labels)
|
214
|
+
end
|
215
|
+
|
216
|
+
def break_label_string_into_pairs(labels)
|
217
|
+
# Strip whitespaces immediately before and after colons or semicolons
|
218
|
+
stripped_labels = labels.gsub(/\s*(:|;)\s*/, '\1')
|
219
|
+
stripped_labels.split(';').map do |pair|
|
220
|
+
pair.split(':')
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
def valid_label_pairs?(label_pairs)
|
225
|
+
label_pairs.all? do |pair|
|
226
|
+
pair.length == 2 &&
|
227
|
+
valid_label_item?(pair.first) &&
|
228
|
+
valid_label_item?(pair.last)
|
229
|
+
end
|
230
|
+
end
|
231
|
+
|
232
|
+
def valid_label_item?(item)
|
233
|
+
case item
|
234
|
+
when String then !item.empty?
|
235
|
+
when Numeric then true
|
236
|
+
when true then true
|
237
|
+
when false then true
|
238
|
+
else false
|
239
|
+
end
|
240
|
+
end
|
241
|
+
|
242
|
+
def make_label_hash(pairs, labels = nil)
|
243
|
+
# This can accept a hash, so force it down to an array of pairs first
|
244
|
+
pairs = Array(pairs)
|
245
|
+
|
246
|
+
unless valid_label_pairs?(pairs)
|
247
|
+
NewRelic::Agent.logger.warn("#{MALFORMED_LABELS_WARNING}: #{labels||pairs}")
|
248
|
+
return []
|
249
|
+
end
|
250
|
+
|
251
|
+
pairs = limit_number_of_labels(pairs)
|
252
|
+
pairs.map do |key, value|
|
253
|
+
{
|
254
|
+
'label_type' => truncate(key),
|
255
|
+
'label_value' => truncate(value.to_s, key)
|
256
|
+
}
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def truncate(text, key=nil)
|
261
|
+
if text.length > MAX_LABEL_LENGTH
|
262
|
+
if key
|
263
|
+
msg = "The value for the label '#{key}' is longer than the allowed #{MAX_LABEL_LENGTH} and will be truncated. Value = '#{text}'"
|
264
|
+
else
|
265
|
+
msg = "Label name longer than the allowed #{MAX_LABEL_LENGTH} will be truncated. Name = '#{text}'"
|
266
|
+
end
|
267
|
+
NewRelic::Agent.logger.warn(msg)
|
268
|
+
text[0..MAX_LABEL_LENGTH-1]
|
269
|
+
else
|
270
|
+
text
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
274
|
+
def limit_number_of_labels(pairs)
|
275
|
+
if pairs.length > MAX_LABEL_COUNT
|
276
|
+
NewRelic::Agent.logger.warn("Too many labels defined. Only taking first #{MAX_LABEL_COUNT}")
|
277
|
+
pairs[0...64]
|
278
|
+
else
|
279
|
+
pairs
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
def parse_labels_from_dictionary
|
284
|
+
make_label_hash(NewRelic::Agent.config[:labels])
|
285
|
+
end
|
286
|
+
|
192
287
|
# Generally only useful during initial construction and tests
|
193
288
|
def reset_to_defaults
|
194
289
|
@high_security_source = nil
|
@@ -247,8 +342,12 @@ module NewRelic
|
|
247
342
|
|
248
343
|
stack.compact!
|
249
344
|
|
250
|
-
@configs_for_testing.each do |config,
|
251
|
-
|
345
|
+
@configs_for_testing.each do |config, at_start|
|
346
|
+
if at_start
|
347
|
+
stack.insert(0, config)
|
348
|
+
else
|
349
|
+
stack.push(config)
|
350
|
+
end
|
252
351
|
end
|
253
352
|
|
254
353
|
stack
|
@@ -0,0 +1,17 @@
|
|
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/configuration/dotted_hash'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module Agent
|
9
|
+
module Configuration
|
10
|
+
class ManualSource < DottedHash
|
11
|
+
def initialize(hash)
|
12
|
+
super(hash, true)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -12,7 +12,8 @@ module NewRelic
|
|
12
12
|
# when value is "apdex_f" remove the config and defer to default
|
13
13
|
hash['agent_config'].delete('transaction_tracer.transaction_threshold')
|
14
14
|
end
|
15
|
-
|
15
|
+
|
16
|
+
hoist_agent_config(hash)
|
16
17
|
end
|
17
18
|
|
18
19
|
if hash['web_transactions_apdex']
|
@@ -38,15 +39,22 @@ module NewRelic
|
|
38
39
|
gated_features.each do |feature, gate_key|
|
39
40
|
if server_config.has_key?(gate_key)
|
40
41
|
allowed_by_server = server_config[gate_key]
|
41
|
-
requested_value = ungated_value(feature, existing_config)
|
42
|
+
requested_value = ungated_value(feature, server_config, existing_config)
|
42
43
|
effective_value = (allowed_by_server && requested_value)
|
43
44
|
server_config[feature] = effective_value
|
44
45
|
end
|
45
46
|
end
|
46
47
|
end
|
47
48
|
|
48
|
-
def ungated_value(key, existing_config)
|
49
|
-
|
49
|
+
def ungated_value(key, server_config, existing_config)
|
50
|
+
server_config.has_key?(key) ? server_config[key] : existing_config[key]
|
51
|
+
end
|
52
|
+
|
53
|
+
# Move agent_config subkey to top level of hash, symbolizing it too
|
54
|
+
def hoist_agent_config(hash)
|
55
|
+
agent_config = hash.delete('agent_config')
|
56
|
+
DottedHash.symbolize(agent_config)
|
57
|
+
hash.merge!(agent_config)
|
50
58
|
end
|
51
59
|
end
|
52
60
|
end
|
@@ -17,33 +17,18 @@ module NewRelic
|
|
17
17
|
@file_path = validate_config_file_path(path)
|
18
18
|
return unless @file_path
|
19
19
|
|
20
|
-
::NewRelic::Agent.logger.info("Reading configuration from #{path}")
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
# when using the default newrelic.yml file
|
25
|
-
generated_for_user = ''
|
26
|
-
license_key = ''
|
27
|
-
|
28
|
-
erb = ERB.new(file).result(binding)
|
29
|
-
confighash = with_yaml_engine { YAML.load(erb) }
|
30
|
-
::NewRelic::Agent.logger.error("Config (#{path}) doesn't include a '#{env}' environment!") unless
|
31
|
-
confighash.key?(env)
|
32
|
-
|
33
|
-
config = merge!(confighash[env] || {})
|
20
|
+
::NewRelic::Agent.logger.info("Reading configuration from #{path} (#{Dir.pwd})")
|
21
|
+
raw_file = File.read(@file_path)
|
22
|
+
erb_file = process_erb(raw_file)
|
23
|
+
config = process_yaml(erb_file, env, config)
|
34
24
|
rescue ScriptError, StandardError => e
|
35
|
-
::NewRelic::Agent.logger.error("Failed to read or parse configuration file at #{path}
|
36
|
-
end
|
37
|
-
|
38
|
-
if config['transaction_tracer'] &&
|
39
|
-
config['transaction_tracer']['transaction_threshold'] =~ /apdex_f/i
|
40
|
-
# when value is "apdex_f" remove the config and defer to default
|
41
|
-
config['transaction_tracer'].delete('transaction_threshold')
|
25
|
+
::NewRelic::Agent.logger.error("Failed to read or parse configuration file at #{path}", e)
|
42
26
|
end
|
43
27
|
|
28
|
+
substitute_transaction_threshold(config)
|
44
29
|
booleanify_values(config, 'agent_enabled', 'enabled', 'monitor_daemons')
|
45
30
|
|
46
|
-
super(config)
|
31
|
+
super(config, true)
|
47
32
|
end
|
48
33
|
|
49
34
|
protected
|
@@ -82,6 +67,44 @@ module NewRelic
|
|
82
67
|
)
|
83
68
|
end
|
84
69
|
|
70
|
+
def process_erb(file)
|
71
|
+
begin
|
72
|
+
# Exclude lines that are commented out so failing Ruby code in an
|
73
|
+
# ERB template commented at the YML level is fine. Leave the line,
|
74
|
+
# though, so ERB line numbers remain correct.
|
75
|
+
file.gsub!(/^\s*#.*$/, '#')
|
76
|
+
|
77
|
+
# Next two are for populating the newrelic.yml via erb binding, necessary
|
78
|
+
# when using the default newrelic.yml file
|
79
|
+
generated_for_user = ''
|
80
|
+
license_key = ''
|
81
|
+
|
82
|
+
ERB.new(file).result(binding)
|
83
|
+
rescue ScriptError, StandardError => e
|
84
|
+
::NewRelic::Agent.logger.error("Failed ERB processing configuration file. This is typically caused by a Ruby error in <% %> templating blocks in your newrelic.yml file.", e)
|
85
|
+
nil
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def process_yaml(file, env, config)
|
90
|
+
if file
|
91
|
+
confighash = with_yaml_engine { YAML.load(file) }
|
92
|
+
::NewRelic::Agent.logger.error("Config (#{path}) doesn't include a '#{env}' environment!") unless confighash.key?(env)
|
93
|
+
|
94
|
+
config = confighash[env] || {}
|
95
|
+
end
|
96
|
+
|
97
|
+
config
|
98
|
+
end
|
99
|
+
|
100
|
+
def substitute_transaction_threshold(config)
|
101
|
+
if config['transaction_tracer'] &&
|
102
|
+
config['transaction_tracer']['transaction_threshold'] =~ /apdex_f/i
|
103
|
+
# when value is "apdex_f" remove the config and defer to default
|
104
|
+
config['transaction_tracer'].delete('transaction_threshold')
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
85
108
|
def with_yaml_engine
|
86
109
|
return yield unless NewRelic::LanguageSupport.needs_syck?
|
87
110
|
|
@@ -92,6 +115,7 @@ module NewRelic
|
|
92
115
|
result
|
93
116
|
end
|
94
117
|
|
118
|
+
|
95
119
|
def booleanify_values(config, *keys)
|
96
120
|
# auto means defer ro default
|
97
121
|
keys.each do |option|
|
@@ -59,7 +59,7 @@ module NewRelic
|
|
59
59
|
end
|
60
60
|
end
|
61
61
|
|
62
|
-
events.subscribe(:after_call) do |env, (
|
62
|
+
events.subscribe(:after_call) do |env, (_status_code, headers, _body)| #THREAD_LOCAL_ACCESS
|
63
63
|
state = NewRelic::Agent::TransactionState.tl_get
|
64
64
|
|
65
65
|
insert_response_header(state, env, headers)
|
@@ -249,7 +249,7 @@ module NewRelic
|
|
249
249
|
# Return the set of metric objects appropriate for the given cross app
|
250
250
|
# +response+.
|
251
251
|
def metrics_for_crossapp_response( request, response )
|
252
|
-
xp_id, txn_name,
|
252
|
+
xp_id, txn_name, _q_time, _r_time, _req_len, _ = extract_appdata( response )
|
253
253
|
|
254
254
|
check_crossapp_id( xp_id )
|
255
255
|
check_transaction_name( txn_name )
|
@@ -6,30 +6,71 @@ module NewRelic
|
|
6
6
|
module Agent
|
7
7
|
module Database
|
8
8
|
module ObfuscationHelpers
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
# Note that the following two regexes are applied to a reversed version
|
10
|
+
# of the query. This is why the backslash escape sequences (\' and \")
|
11
|
+
# appear reversed within them.
|
12
|
+
#
|
13
|
+
# Note that some database adapters (notably, PostgreSQL with
|
14
|
+
# standard_conforming_strings on and MySQL with NO_BACKSLASH_ESCAPES on)
|
15
|
+
# do not apply special treatment to backslashes within quoted string
|
16
|
+
# literals. We don't have an easy way of determining whether the
|
17
|
+
# database connection from which a query was captured was operating in
|
18
|
+
# one of these modes, but the obfuscation is done in such a way that it
|
19
|
+
# should not matter.
|
20
|
+
#
|
21
|
+
# Reversing the query string before obfuscation allows us to get around
|
22
|
+
# the fact that a \' appearing within a string may or may not terminate
|
23
|
+
# the string, because we know that a string cannot *start* with a \'.
|
24
|
+
REVERSE_SINGLE_QUOTES_REGEX = /'(?:''|'\\|[^'])*'/
|
25
|
+
REVERSE_ANY_QUOTES_REGEX = /'(?:''|'\\|[^'])*'|"(?:""|"\\|[^"])*"/
|
12
26
|
|
13
|
-
|
14
|
-
|
15
|
-
|
27
|
+
NUMERICS_REGEX = /\b\d+\b/
|
28
|
+
|
29
|
+
# We take a conservative, overly-aggressive approach to obfuscating
|
30
|
+
# comments, and drop everything from the query after encountering any
|
31
|
+
# character sequence that could be a comment initiator. We do this after
|
32
|
+
# removal of string literals to avoid accidentally over-obfuscating when
|
33
|
+
# a string literal contains a comment initiator.
|
34
|
+
SQL_COMMENT_REGEX = Regexp.new('(?:/\*|--|#).*', Regexp::MULTILINE).freeze
|
35
|
+
|
36
|
+
# We use these to check whether the query contains any quote characters
|
37
|
+
# after obfuscation. If so, that's a good indication that the original
|
38
|
+
# query was malformed, and so our obfuscation can't reliabily find
|
39
|
+
# literals. In such a case, we'll replace the entire query with a
|
40
|
+
# placeholder.
|
41
|
+
LITERAL_SINGLE_QUOTE = "'".freeze
|
42
|
+
LITERAL_DOUBLE_QUOTE = '"'.freeze
|
43
|
+
|
44
|
+
PLACEHOLDER = '?'.freeze
|
16
45
|
|
17
46
|
def obfuscate_single_quote_literals(sql)
|
18
|
-
sql.
|
47
|
+
obfuscated = sql.reverse
|
48
|
+
obfuscated.gsub!(REVERSE_SINGLE_QUOTES_REGEX, PLACEHOLDER)
|
49
|
+
obfuscated.reverse!
|
50
|
+
obfuscated
|
19
51
|
end
|
20
52
|
|
21
|
-
def
|
22
|
-
sql.
|
53
|
+
def obfuscate_quoted_literals(sql)
|
54
|
+
obfuscated = sql.reverse
|
55
|
+
obfuscated.gsub!(REVERSE_ANY_QUOTES_REGEX, PLACEHOLDER)
|
56
|
+
obfuscated.reverse!
|
57
|
+
obfuscated
|
23
58
|
end
|
24
59
|
|
25
60
|
def obfuscate_numeric_literals(sql)
|
26
|
-
sql.gsub(
|
61
|
+
sql.gsub(NUMERICS_REGEX, PLACEHOLDER)
|
62
|
+
end
|
63
|
+
|
64
|
+
def remove_comments(sql)
|
65
|
+
sql.gsub(SQL_COMMENT_REGEX, PLACEHOLDER)
|
66
|
+
end
|
67
|
+
|
68
|
+
def contains_single_quotes?(str)
|
69
|
+
str.include?(LITERAL_SINGLE_QUOTE)
|
27
70
|
end
|
28
71
|
|
29
|
-
def
|
30
|
-
|
31
|
-
literals << sql.scan(SINGLE_QUOTES)
|
32
|
-
literals.flatten
|
72
|
+
def contains_quotes?(str)
|
73
|
+
str.include?(LITERAL_SINGLE_QUOTE) || str.include?(LITERAL_DOUBLE_QUOTE)
|
33
74
|
end
|
34
75
|
end
|
35
76
|
end
|
@@ -13,6 +13,9 @@ module NewRelic
|
|
13
13
|
|
14
14
|
attr_reader :obfuscator
|
15
15
|
|
16
|
+
QUERY_TOO_LARGE_MESSAGE = "Query too large (over 16k characters) to safely obfuscate"
|
17
|
+
FAILED_TO_OBFUSCATE_MESSAGE = "Failed to obfuscate SQL query - quote characters remained after obfuscation"
|
18
|
+
|
16
19
|
def initialize
|
17
20
|
reset
|
18
21
|
end
|
@@ -46,17 +49,29 @@ module NewRelic
|
|
46
49
|
|
47
50
|
def default_sql_obfuscator(sql)
|
48
51
|
if sql[-3,3] == '...'
|
49
|
-
return
|
52
|
+
return QUERY_TOO_LARGE_MESSAGE
|
50
53
|
end
|
51
54
|
|
52
55
|
stmt = sql.kind_of?(Statement) ? sql : Statement.new(sql)
|
53
|
-
|
54
|
-
|
55
|
-
obfuscated =
|
56
|
-
|
57
|
-
|
56
|
+
obfuscate_double_quotes = stmt.adapter.to_s !~ /postgres|sqlite/
|
57
|
+
|
58
|
+
obfuscated = obfuscate_numeric_literals(stmt)
|
59
|
+
|
60
|
+
if obfuscate_double_quotes
|
61
|
+
obfuscated = obfuscate_quoted_literals(obfuscated)
|
62
|
+
obfuscated = remove_comments(obfuscated)
|
63
|
+
if contains_quotes?(obfuscated)
|
64
|
+
obfuscated = FAILED_TO_OBFUSCATE_MESSAGE
|
65
|
+
end
|
66
|
+
else
|
67
|
+
obfuscated = obfuscate_single_quote_literals(obfuscated)
|
68
|
+
obfuscated = remove_comments(obfuscated)
|
69
|
+
if contains_single_quotes?(obfuscated)
|
70
|
+
obfuscated = FAILED_TO_OBFUSCATE_MESSAGE
|
71
|
+
end
|
58
72
|
end
|
59
|
-
|
73
|
+
|
74
|
+
|
60
75
|
obfuscated.to_s # return back to a regular String
|
61
76
|
end
|
62
77
|
end
|