newrelic_rpm 3.7.0.177 → 3.7.1.180
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +0 -0
- data/CHANGELOG +28 -1
- data/lib/new_relic/agent.rb +1 -2
- data/lib/new_relic/agent/agent.rb +28 -10
- data/lib/new_relic/agent/agent_logger.rb +4 -3
- data/lib/new_relic/agent/audit_logger.rb +5 -8
- data/lib/new_relic/agent/configuration/default_source.rb +24 -0
- data/lib/new_relic/agent/cross_app_tracing.rb +21 -15
- data/lib/new_relic/agent/datastores/mongo.rb +25 -0
- data/lib/new_relic/agent/datastores/mongo/metric_generator.rb +25 -0
- data/lib/new_relic/agent/datastores/mongo/metric_translator.rb +189 -0
- data/lib/new_relic/agent/datastores/mongo/obfuscator.rb +39 -0
- data/lib/new_relic/agent/datastores/mongo/statement_formatter.rb +52 -0
- data/lib/new_relic/agent/harvester.rb +55 -0
- data/lib/new_relic/agent/instrumentation/mongo.rb +139 -0
- data/lib/new_relic/agent/instrumentation/net.rb +6 -11
- data/lib/new_relic/agent/supported_versions.rb +9 -5
- data/lib/new_relic/agent/transaction_sampler.rb +4 -0
- data/lib/new_relic/version.rb +1 -1
- data/lib/tasks/versions.rake +1 -1
- data/test/agent_helper.rb +4 -0
- data/test/environments/norails/Gemfile +3 -0
- data/test/environments/rails40/Gemfile +5 -1
- data/test/flaky_proxy/Gemfile +3 -0
- data/test/flaky_proxy/README.md +82 -0
- data/test/flaky_proxy/lib/flaky_proxy.rb +22 -0
- data/test/flaky_proxy/lib/flaky_proxy/connection.rb +45 -0
- data/test/flaky_proxy/lib/flaky_proxy/http_message.rb +105 -0
- data/test/flaky_proxy/lib/flaky_proxy/proxy.rb +42 -0
- data/test/flaky_proxy/lib/flaky_proxy/rule.rb +75 -0
- data/test/flaky_proxy/lib/flaky_proxy/rule_set.rb +37 -0
- data/test/flaky_proxy/lib/flaky_proxy/server.rb +22 -0
- data/test/flaky_proxy/script/flaky_proxy +39 -0
- data/test/helpers/exceptions.rb +16 -0
- data/test/helpers/mongo_metric_builder.rb +29 -0
- data/test/multiverse/lib/multiverse/suite.rb +1 -0
- data/test/multiverse/suites/curb/curb_test.rb +0 -1
- data/test/multiverse/suites/deferred_instrumentation/sinatra_test.rb +4 -3
- data/test/multiverse/suites/excon/excon_test.rb +0 -1
- data/test/multiverse/suites/httpclient/httpclient_test.rb +0 -1
- data/test/multiverse/suites/mongo/Envfile +66 -0
- data/test/multiverse/suites/mongo/config/newrelic.yml +19 -0
- data/test/multiverse/suites/mongo/mongo_instrumentation_test.rb +418 -0
- data/test/multiverse/suites/mongo/mongo_unsupported_version_test.rb +36 -0
- data/test/multiverse/suites/net_http/net_http_test.rb +2 -4
- data/test/multiverse/suites/rails/Envfile +4 -4
- data/test/multiverse/suites/rails/config/newrelic.yml +1 -1
- data/test/multiverse/suites/rails/error_tracing_test.rb +7 -7
- data/test/multiverse/suites/sidekiq/Envfile +1 -1
- data/test/multiverse/suites/sidekiq/sidekiq_instrumentation_test.rb +0 -1
- data/test/multiverse/suites/sinatra/sinatra_classic_test.rb +5 -3
- data/test/multiverse/suites/sinatra/sinatra_modular_test.rb +5 -3
- data/test/multiverse/suites/typhoeus/typhoeus_test.rb +0 -1
- data/test/new_relic/agent/agent_logger_test.rb +9 -1
- data/test/new_relic/agent/agent_test.rb +66 -1
- data/test/new_relic/agent/agent_test_controller.rb +1 -2
- data/test/new_relic/agent/audit_logger_test.rb +12 -4
- data/test/new_relic/agent/configuration/orphan_configuration_test.rb +11 -2
- data/test/new_relic/agent/cpu_sampler_test.rb +1 -0
- data/test/new_relic/agent/cross_app_tracing_test.rb +60 -0
- data/test/new_relic/agent/datastores/mongo/metric_generator_test.rb +43 -0
- data/test/new_relic/agent/datastores/mongo/metric_translator_test.rb +301 -0
- data/test/new_relic/agent/datastores/mongo/obfuscator_test.rb +91 -0
- data/test/new_relic/agent/datastores/mongo/statement_formatter_test.rb +71 -0
- data/test/new_relic/agent/harvester_test.rb +85 -0
- data/test/new_relic/agent/transaction_sampler_test.rb +5 -0
- data/test/new_relic/agent/worker_loop_test.rb +3 -5
- data/test/new_relic/http_client_test_cases.rb +65 -81
- data/test/new_relic/noticed_error_test.rb +14 -16
- data/test/performance/lib/performance.rb +1 -0
- data/test/performance/lib/performance/console_reporter.rb +6 -2
- data/test/performance/lib/performance/instrumentor.rb +1 -15
- data/test/performance/lib/performance/platform.rb +35 -0
- data/test/performance/lib/performance/test_case.rb +16 -1
- data/test/performance/suites/marshalling.rb +73 -0
- metadata +48 -19
- metadata.gz.sig +1 -2
@@ -0,0 +1,22 @@
|
|
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
|
+
$: << File.expand_path(File.dirname(__FILE__))
|
6
|
+
|
7
|
+
require 'logger'
|
8
|
+
|
9
|
+
require 'flaky_proxy/server'
|
10
|
+
require 'flaky_proxy/connection'
|
11
|
+
require 'flaky_proxy/http_message'
|
12
|
+
require 'flaky_proxy/rule'
|
13
|
+
require 'flaky_proxy/rule_set'
|
14
|
+
require 'flaky_proxy/proxy'
|
15
|
+
|
16
|
+
module FlakyProxy
|
17
|
+
@logger = Logger.new($stderr)
|
18
|
+
|
19
|
+
def self.logger
|
20
|
+
@logger
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
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
|
+
module FlakyProxy
|
6
|
+
class Connection
|
7
|
+
def initialize(client_socket, server, rules)
|
8
|
+
@client_socket = client_socket
|
9
|
+
@server_socket = nil
|
10
|
+
@server = server
|
11
|
+
@rules = rules
|
12
|
+
end
|
13
|
+
|
14
|
+
def client_socket
|
15
|
+
@client_socket
|
16
|
+
end
|
17
|
+
|
18
|
+
def server_socket
|
19
|
+
@server_socket ||= @server.open_socket
|
20
|
+
end
|
21
|
+
|
22
|
+
def shutdown
|
23
|
+
@client_socket.close if @client_socket && !@client_socket.closed?
|
24
|
+
@server_socket.close if @server_socket && !@server_socket.closed?
|
25
|
+
@shutdown = true
|
26
|
+
end
|
27
|
+
|
28
|
+
def service
|
29
|
+
loop do
|
30
|
+
service_one
|
31
|
+
break if @shutdown
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def service_one
|
36
|
+
request = Request.read_from(client_socket)
|
37
|
+
if request.complete?
|
38
|
+
rule = @rules.match(request)
|
39
|
+
rule.evaluate(request, self)
|
40
|
+
else
|
41
|
+
shutdown
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,105 @@
|
|
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 'http/parser'
|
6
|
+
require 'webrick'
|
7
|
+
|
8
|
+
module FlakyProxy
|
9
|
+
MAXBUF = 10 * 4096 # 40KB
|
10
|
+
|
11
|
+
class HttpMessage
|
12
|
+
def self.read_from(io)
|
13
|
+
msg = self.new
|
14
|
+
msg.read(io)
|
15
|
+
msg
|
16
|
+
end
|
17
|
+
|
18
|
+
attr_reader :raw_data
|
19
|
+
|
20
|
+
def initialize
|
21
|
+
@parser = Http::Parser.new
|
22
|
+
@raw_data = ''
|
23
|
+
@complete = false
|
24
|
+
@parser.on_message_complete = proc do |env|
|
25
|
+
@complete = true
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def request_url
|
30
|
+
@parser.request_url if complete?
|
31
|
+
end
|
32
|
+
|
33
|
+
def request_path
|
34
|
+
@parser.request_path if complete?
|
35
|
+
end
|
36
|
+
|
37
|
+
def <<(data)
|
38
|
+
@raw_data << data
|
39
|
+
@parser << data
|
40
|
+
end
|
41
|
+
|
42
|
+
def read(io)
|
43
|
+
loop do
|
44
|
+
return if complete? || io.closed?
|
45
|
+
ready = select([io])
|
46
|
+
if ready && ready.first.include?(io)
|
47
|
+
if io.eof?
|
48
|
+
return
|
49
|
+
else
|
50
|
+
self << io.readpartial(MAXBUF)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def complete?
|
57
|
+
@complete
|
58
|
+
end
|
59
|
+
|
60
|
+
def relay_to(io)
|
61
|
+
io.write(@raw_data)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
class Request < HttpMessage
|
66
|
+
def request_method
|
67
|
+
@parser.http_method
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
class Response < HttpMessage
|
72
|
+
def self.build(options={})
|
73
|
+
defaults = {
|
74
|
+
:status => 200,
|
75
|
+
:headers => {},
|
76
|
+
:body => ''
|
77
|
+
}
|
78
|
+
options = defaults.merge(options)
|
79
|
+
status_line = build_status_line(options[:status])
|
80
|
+
headers = build_headers(options[:body], options[:headers])
|
81
|
+
|
82
|
+
rsp = self.new
|
83
|
+
rsp << status_line
|
84
|
+
rsp << headers
|
85
|
+
rsp << "\r\n"
|
86
|
+
rsp << options[:body]
|
87
|
+
rsp
|
88
|
+
end
|
89
|
+
|
90
|
+
def self.build_status_line(status)
|
91
|
+
status_text = WEBrick::HTTPStatus::StatusMessage[status]
|
92
|
+
"HTTP/1.1 #{status} #{status_text}\r\n"
|
93
|
+
end
|
94
|
+
|
95
|
+
def self.build_headers(body, headers)
|
96
|
+
default_headers = {
|
97
|
+
'Content-Length' => body.bytesize
|
98
|
+
}
|
99
|
+
headers = default_headers.merge(headers)
|
100
|
+
headers.map do |key, value|
|
101
|
+
"#{key}: #{value}\r\n"
|
102
|
+
end.join
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,42 @@
|
|
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 'socket'
|
6
|
+
|
7
|
+
module FlakyProxy
|
8
|
+
class Proxy
|
9
|
+
def initialize(options)
|
10
|
+
@listen_host = options.fetch(:listen_host)
|
11
|
+
@listen_port = options.fetch(:listen_port)
|
12
|
+
@backend_server = Server.new(options.fetch(:target_host), options.fetch(:target_port))
|
13
|
+
@rules = RuleSet.build('')
|
14
|
+
@rules_path = options[:rules_path]
|
15
|
+
@listen_socket = nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def reload_rules_file
|
19
|
+
if @rules_path
|
20
|
+
mtime = File.stat(@rules_path).mtime
|
21
|
+
if @last_rules_mtime.nil? || mtime > @last_rules_mtime
|
22
|
+
FlakyProxy.logger.info("Reloading rules file at #{@rules_path}")
|
23
|
+
@rules = RuleSet.build(File.read(@rules_path))
|
24
|
+
@last_rules_mtime = mtime
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def run
|
30
|
+
FlakyProxy.logger.info("Starting FlakyProxy on #{@listen_host}:#{@listen_port} -> #{@backend_server.to_s}")
|
31
|
+
@listen_socket = TCPServer.new(@listen_host, @listen_port)
|
32
|
+
loop do
|
33
|
+
client_socket = @listen_socket.accept
|
34
|
+
reload_rules_file
|
35
|
+
FlakyProxy.logger.info("Accepted connection from #{client_socket}")
|
36
|
+
connection = Connection.new(client_socket, @backend_server, @rules)
|
37
|
+
connection.service
|
38
|
+
FlakyProxy.logger.info("Finished servicing connection from #{client_socket}")
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -0,0 +1,75 @@
|
|
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
|
+
module FlakyProxy
|
6
|
+
class Rule
|
7
|
+
class ActionBuilder
|
8
|
+
def initialize(rule)
|
9
|
+
@actions = []
|
10
|
+
@rule = rule
|
11
|
+
end
|
12
|
+
|
13
|
+
def pass
|
14
|
+
@rule.actions << [:pass]
|
15
|
+
end
|
16
|
+
|
17
|
+
def respond(response_spec)
|
18
|
+
@rule.actions << [:respond, response_spec]
|
19
|
+
end
|
20
|
+
|
21
|
+
def delay(amount)
|
22
|
+
@rule.actions << [:delay, amount]
|
23
|
+
end
|
24
|
+
|
25
|
+
def close
|
26
|
+
@rule.actions << [:close]
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
attr_reader :actions
|
31
|
+
|
32
|
+
def initialize(url_regex=nil, &blk)
|
33
|
+
@url_regex = url_regex
|
34
|
+
@actions = []
|
35
|
+
ActionBuilder.new(self).instance_eval(&blk)
|
36
|
+
end
|
37
|
+
|
38
|
+
def match?(request)
|
39
|
+
@url_regex.nil? || @url_regex.match(request.request_url)
|
40
|
+
end
|
41
|
+
|
42
|
+
def next_action
|
43
|
+
if @actions.size > 1
|
44
|
+
@actions.shift
|
45
|
+
else
|
46
|
+
@actions.last
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def relay(request, connection)
|
51
|
+
request.relay_to(connection.server_socket)
|
52
|
+
response = Response.read_from(connection.server_socket)
|
53
|
+
response.relay_to(connection.client_socket)
|
54
|
+
end
|
55
|
+
|
56
|
+
def evaluate(request, connection)
|
57
|
+
action, *params = next_action
|
58
|
+
FlakyProxy.logger.info(" [#{action.upcase}] #{request.request_method} #{request.request_url}")
|
59
|
+
case action
|
60
|
+
when :pass
|
61
|
+
relay(request, connection)
|
62
|
+
when :respond
|
63
|
+
response_spec = params.first
|
64
|
+
response = Response.build(response_spec)
|
65
|
+
response.relay_to(connection.client_socket)
|
66
|
+
when :delay
|
67
|
+
amount = params.first
|
68
|
+
sleep(amount)
|
69
|
+
relay(request, connection)
|
70
|
+
when :close
|
71
|
+
connection.client_socket.close
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,37 @@
|
|
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
|
+
module FlakyProxy
|
6
|
+
class RuleSet
|
7
|
+
class Builder
|
8
|
+
attr_reader :rules
|
9
|
+
|
10
|
+
def initialize(ruleset, &blk)
|
11
|
+
@ruleset = ruleset
|
12
|
+
@rules = []
|
13
|
+
end
|
14
|
+
|
15
|
+
def match(criteria, &blk)
|
16
|
+
@ruleset.rules << Rule.new(criteria, &blk)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.build(text=nil, &blk)
|
21
|
+
ruleset = self.new
|
22
|
+
Builder.new(ruleset).instance_eval(text, &blk)
|
23
|
+
ruleset
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_accessor :rules
|
27
|
+
|
28
|
+
def initialize
|
29
|
+
@rules = []
|
30
|
+
@default_rule = Rule.new { pass }
|
31
|
+
end
|
32
|
+
|
33
|
+
def match(request)
|
34
|
+
@rules.detect { |rule| rule.match?(request) } || @default_rule
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
@@ -0,0 +1,22 @@
|
|
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
|
+
module FlakyProxy
|
6
|
+
class Server
|
7
|
+
attr_reader :host, :port
|
8
|
+
|
9
|
+
def initialize(host, port)
|
10
|
+
@host = host
|
11
|
+
@port = port
|
12
|
+
end
|
13
|
+
|
14
|
+
def open_socket
|
15
|
+
TCPSocket.new(@host, @port)
|
16
|
+
end
|
17
|
+
|
18
|
+
def to_s
|
19
|
+
"#{@host}:#{@port}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'optparse'
|
4
|
+
require File.join(File.dirname(__FILE__), '..', 'lib', 'flaky_proxy')
|
5
|
+
|
6
|
+
DEFAULTS = {
|
7
|
+
:listen_host => 'localhost',
|
8
|
+
:listen_port => 8888,
|
9
|
+
:target_host => 'localhost',
|
10
|
+
:target_port => 8081
|
11
|
+
}
|
12
|
+
|
13
|
+
options = DEFAULTS.dup
|
14
|
+
parser = OptionParser.new do |opts|
|
15
|
+
opts.banner = "Usage: #{$0} [options] [<rules file>]"
|
16
|
+
|
17
|
+
opts.on("-l", "--listen [<HOST>:]<PORT>", "Specify the host and port to listen on") do |listen_spec|
|
18
|
+
if listen_spec =~ /^([^:]+):(\d+)$/
|
19
|
+
options[:listen_host] = $1
|
20
|
+
options[:listen_port] = $2.to_i
|
21
|
+
else
|
22
|
+
options[:listen_port] = listen_spec.to_i
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
opts.on("-t", "--target [<HOST>:]<PORT>", "Specify the host and port to forward to") do |target_spec|
|
27
|
+
if target_spec =~ /^([^:]+):(\d+)$/
|
28
|
+
options[:target_host] = $1
|
29
|
+
options[:target_port] = $2
|
30
|
+
else
|
31
|
+
options[:target_port] = target_spec.to_i
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
parser.parse!
|
36
|
+
|
37
|
+
options[:rules_path] = ARGV[0] if ARGV[0]
|
38
|
+
|
39
|
+
FlakyProxy::Proxy.new(options).run
|
@@ -0,0 +1,16 @@
|
|
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
|
+
module NewRelic
|
6
|
+
module TestHelpers
|
7
|
+
module Exceptions
|
8
|
+
class TestError < StandardError; end
|
9
|
+
class IgnoredError < StandardError; end
|
10
|
+
class ServerIgnoredError < StandardError; end
|
11
|
+
class TestRuntimeError < RuntimeError; end
|
12
|
+
class ParentException < Exception; end
|
13
|
+
class ChildException < ParentException; end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,29 @@
|
|
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/datastores/mongo/metric_translator'
|
6
|
+
|
7
|
+
module NewRelic
|
8
|
+
module TestHelpers
|
9
|
+
module MongoMetricBuilder
|
10
|
+
def build_test_metrics(name, request_type = :web)
|
11
|
+
NewRelic::Agent::Datastores::Mongo::MetricTranslator.build_metrics(
|
12
|
+
name,
|
13
|
+
@collection_name,
|
14
|
+
request_type
|
15
|
+
)
|
16
|
+
end
|
17
|
+
|
18
|
+
def metrics_with_attributes(metrics, attributes)
|
19
|
+
metric_attributes = {}
|
20
|
+
|
21
|
+
metrics.each do |metric|
|
22
|
+
metric_attributes[metric] = attributes
|
23
|
+
end
|
24
|
+
|
25
|
+
metric_attributes
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|