Skip to content

Commit

Permalink
Merge branch 'dev' into RUBY-1093-rails4
Browse files Browse the repository at this point in the history
  • Loading branch information
jasonrclark committed Feb 3, 2014
2 parents 7cc223b + 2d14901 commit 254b67c
Show file tree
Hide file tree
Showing 9 changed files with 139 additions and 86 deletions.
14 changes: 14 additions & 0 deletions CHANGELOG
Expand Up @@ -8,6 +8,9 @@
including support for some operations that were not previously captured, and
separation of aggregate metrics for web transactions from background jobs.

An issue with ensure_index when passed a symbol or string was also fixed.
Thanks Maxime RETY for the report!

* More accurate error tracing in Rails 4

Traced errors in Rails 4 applications will now be correctly associated with
Expand All @@ -34,6 +37,17 @@
A potential crash with Typhoeus 0.6.4+ when passing a URI object instead of a
String instance to one of Typhoeus's HTTP request methods has been fixed.

* Sequel single threaded mode fix

The agent will no longer attempt to run EXPLAIN queries for slow SQL
statements issued using the Sequel gem in single-threaded mode, since
doing so could potentially cause crashes.

* Additional functionality for add_custom_parameters

Calling add_custom_parameters adds parameters to the system codenamed
Rubicon. For more information, see http://newrelic.com/software-analytics

## v3.7.1 ##

* MongoDB support
Expand Down
32 changes: 21 additions & 11 deletions lib/new_relic/agent/instrumentation/controller_instrumentation.rb
Expand Up @@ -418,22 +418,32 @@ def ignore_enduser?
def perform_action_with_newrelic_profile(args)
txn = _start_transaction(block_given? ? args : [])
val = nil
NewRelic::Agent.trace_execution_scoped txn.metric_name do
NewRelic::Agent.disable_all_tracing do
# turn on profiling
profile = RubyProf.profile do
if block_given?
val = yield
else
val = perform_action_without_newrelic_trace(*args)
end
options = { :metric => true }

_, expected_scope = NewRelic::Agent::MethodTracer::TraceExecutionScoped.trace_execution_scoped_header(options, txn.start_time.to_f)

NewRelic::Agent.disable_all_tracing do
# turn on profiling
profile = RubyProf.profile do
if block_given?
val = yield
else
val = perform_action_without_newrelic_trace(*args)
end
NewRelic::Agent.instance.transaction_sampler.notice_profile profile
end
NewRelic::Agent.instance.transaction_sampler.notice_profile profile
end

return val
ensure
txn.pop
end_time = Time.now
txn.freeze_name
metric_names = Array(recorded_metrics(txn))
txn_name = metric_names.shift

NewRelic::Agent::MethodTracer::TraceExecutionScoped.trace_execution_scoped_footer(txn.start_time.to_f, txn_name, metric_names, expected_scope, options, end_time.to_f)

txn = Transaction.stop(txn_name, end_time)
end

# Write a transaction onto a thread local if there isn't already one there.
Expand Down
42 changes: 42 additions & 0 deletions test/multiverse/suites/mongo/Envfile
Expand Up @@ -13,3 +13,45 @@ gemfile <<-RB
gem 'mongo', '~>1.7.1'
gem 'bson_ext', :platforms => :ruby
RB

require 'timeout'
require 'socket'

class PreExistingMongo
attr_reader :host, :port

def initialize(host, port)
@host = host
@port = port
end

def stop(*_)
end
end

$mongo = PreExistingMongo.new("localhost", 27017)

def mongo_running?
Timeout::timeout(1) do
begin
TCPSocket.new($mongo.host, $mongo.port).close
true
rescue Errno::ECONNREFUSED, Errno::EHOSTUNREACH
false
end
end
rescue Timeout::Error
false
end

before_suite do
if !mongo_running?
require File.join(File.dirname(__FILE__), 'helpers', 'mongo_server')
$mongo = MongoServer.new
$mongo.start(false)
end
end

after_suite do
$mongo.stop
end
65 changes: 29 additions & 36 deletions test/multiverse/suites/mongo/helpers/mongo_operation_tests.rb
Expand Up @@ -213,36 +213,40 @@ def test_records_metrics_for_reindex
end

def test_rename_collection
with_unique_collection do
@collection.rename("renamed_#{@collection_name}")
ensure_collection_exists

metrics = build_test_metrics(:renameCollection)
expected = metrics_with_attributes(metrics)
@collection.rename("renamed_#{@collection_name}")

assert_metrics_recorded(expected)
end
metrics = build_test_metrics(:renameCollection)
expected = metrics_with_attributes(metrics)

assert_metrics_recorded(expected)
ensure
@collection_name = "renamed_#{@collection_name}"
end

def test_rename_collection_via_db
with_unique_collection do
@database.rename_collection(@collection_name, "renamed_#{@collection_name}")
ensure_collection_exists

metrics = build_test_metrics(:renameCollection)
expected = metrics_with_attributes(metrics)
@database.rename_collection(@collection_name, "renamed_#{@collection_name}")

assert_metrics_recorded(expected)
end
metrics = build_test_metrics(:renameCollection)
expected = metrics_with_attributes(metrics)

assert_metrics_recorded(expected)
ensure
@collection_name = "renamed_#{@collection_name}"
end

def test_drop_collection
with_unique_collection do
@database.drop_collection(@collection_name)
ensure_collection_exists

metrics = build_test_metrics(:drop)
expected = metrics_with_attributes(metrics)
@database.drop_collection(@collection_name)

assert_metrics_recorded(expected)
end
metrics = build_test_metrics(:drop)
expected = metrics_with_attributes(metrics)

assert_metrics_recorded(expected)
end

def test_collstats
Expand All @@ -264,8 +268,8 @@ def test_notices_nosql
segment = find_last_transaction_segment
end

expected = { :database => 'multiverse',
:collection => 'tribbles',
expected = { :database => @database_name,
:collection => @collection_name,
:operation => :insert}

result = segment.params[:statement]
Expand Down Expand Up @@ -421,24 +425,13 @@ def test_ensure_index_records_instance_metric
assert_metrics_recorded(["Datastore/instance/MongoDB/localhost:#{@client.port}/#{@database_name}"])
end

def with_unique_collection
original_collection_name = @collection_name
original_collection = @collection

@collection_name = "coll#{SecureRandom.hex(10)}"
@collection = @database.collection(@collection_name)
def unique_field_name
"field#{SecureRandom.hex(10)}"
end

# Insert to make sure the collection actually exists...
@collection.insert({:junk => "data"})
def ensure_collection_exists
@collection.insert(:junk => "data")
NewRelic::Agent.drop_buffered_data

yield
ensure
@collection_name = original_collection_name
@collection = original_collection
end

def unique_field_name
"field#{SecureRandom.hex(10)}"
end
end
30 changes: 18 additions & 12 deletions test/multiverse/suites/mongo/helpers/mongo_server.rb
Expand Up @@ -4,11 +4,9 @@

require 'fileutils'
require 'timeout'
require 'mongo'
require File.expand_path(File.join(File.dirname(__FILE__), '..', '..', '..', '..', 'helpers', 'file_searching'))

class MongoServer
include Mongo
extend NewRelic::TestHelpers::FileSearching

attr_reader :type
Expand All @@ -28,7 +26,7 @@ def self.count(type = :all)
end

def self.tmp_directory
File.join(gem_root, 'tmp')
ENV["MULTIVERSE_TMP"] || File.join(gem_root, 'tmp')
end

def self.port_lock_directory
Expand Down Expand Up @@ -87,7 +85,7 @@ def log_path
File.join(MongoServer.log_directory, "#{self.port}.log")
end

def start
def start(wait_for_startup = true)
lock_port

unless running?
Expand All @@ -97,17 +95,18 @@ def start
running?
end

create_client

wait_until do
pingable?
if wait_for_startup
create_client
wait_until do
pingable?
end
end
end

self
end

def wait_until(seconds = 1)
def wait_until(seconds = 10)
Timeout.timeout(seconds) do
sleep 0.1 until yield
end
Expand All @@ -132,6 +131,7 @@ def startup_command
end

def create_client(client_class = nil)
require 'mongo'
if defined? MongoClient
client_class ||= MongoClient
else
Expand All @@ -151,14 +151,14 @@ def stop
begin
Process.kill('TERM', pid)
rescue Errno::ESRCH => e
raise e unless e.message == 'No such process'
# fine if we're already gone...
end

wait_until do
!running?
end

FileUtils.rm(pid_path)
cleanup_files
self.client = nil
end

Expand All @@ -170,7 +170,6 @@ def running?
return false unless pid
Process.kill(0, pid) == 1
rescue Errno::ESRCH => e
raise e unless e.message == 'No such process'
false
end

Expand Down Expand Up @@ -230,4 +229,11 @@ def release_port
FileUtils.rm port_lock_path, :force => true
self.port = nil
end

# PID file needs to be cleaned up for our process checking logic
# DB needs to get cleaned up because it's massive
def cleanup_files
FileUtils.rm(pid_path)
FileUtils.rm_rf(db_path)
end
end
12 changes: 4 additions & 8 deletions test/multiverse/suites/mongo/mongo_connection_test.rb
Expand Up @@ -19,15 +19,11 @@ class NewRelic::Agent::Instrumentation::MongoConnectionTest
include ::NewRelic::TestHelpers::MongoMetricBuilder
include ::MongoOperationTests

@@server = MongoServer.new
@@server.start
at_exit { @@server.stop }

def setup
@client = Mongo::Connection.new('localhost', @@server.port)
@database_name = 'multiverse'
@client = Mongo::Connection.new($mongo.host, $mongo.port)
@database_name = "multiverse"
@database = @client.db(@database_name)
@collection_name = 'tribbles'
@collection_name = "tribbles-#{SecureRandom.hex(16)}"
@collection = @database.collection(@collection_name)

@tribble = {'name' => 'soterios johnson'}
Expand All @@ -38,7 +34,7 @@ def setup

def teardown
NewRelic::Agent.drop_buffered_data
@client.drop_database(@database_name)
@database.drop_collection(@collection_name)
end
end
end
12 changes: 4 additions & 8 deletions test/multiverse/suites/mongo/mongo_instrumentation_test.rb
Expand Up @@ -19,15 +19,11 @@ class NewRelic::Agent::Instrumentation::MongoInstrumentationTest < MiniTest::Uni
include ::NewRelic::TestHelpers::MongoMetricBuilder
include ::MongoOperationTests

@@server = MongoServer.new
@@server.start
at_exit { @@server.stop }

def setup
@client = @@server.client
@database_name = 'multiverse'
@client = Mongo::MongoClient.new($mongo.host, $mongo.port)
@database_name = "multiverse"
@database = @client.db(@database_name)
@collection_name = 'tribbles'
@collection_name = "tribbles-#{SecureRandom.hex(16)}"
@collection = @database.collection(@collection_name)

@tribble = {'name' => 'soterios johnson'}
Expand All @@ -38,7 +34,7 @@ def setup

def teardown
NewRelic::Agent.drop_buffered_data
@client.drop_database(@database_name)
@database.drop_collection(@collection_name)
end
end
end

0 comments on commit 254b67c

Please sign in to comment.