newrelic_rpm 2.8.1 → 2.8.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of newrelic_rpm might be problematic. Click here for more details.
- data/lib/new_relic/agent/agent.rb +23 -32
- data/lib/new_relic/agent/collection_helper.rb +4 -4
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +1 -1
- data/lib/new_relic/agent/patch_const_missing.rb +91 -17
- data/lib/new_relic/config.rb +9 -9
- data/lib/new_relic/transaction_sample.rb +1 -1
- data/lib/new_relic/version.rb +5 -1
- data/lib/newrelic_rpm.rb +2 -2
- data/test/new_relic/agent/tc_agent.rb +42 -6
- metadata +3 -3
@@ -6,10 +6,6 @@ require 'singleton'
|
|
6
6
|
require 'zlib'
|
7
7
|
require 'stringio'
|
8
8
|
|
9
|
-
|
10
|
-
# This must be turned off before we ship
|
11
|
-
VALIDATE_BACKGROUND_THREAD_LOADING = false
|
12
|
-
|
13
9
|
# The NewRelic Agent collects performance data from ruby applications in realtime as the
|
14
10
|
# application runs, and periodically sends that data to the NewRelic server.
|
15
11
|
module NewRelic::Agent
|
@@ -24,6 +20,8 @@ module NewRelic::Agent
|
|
24
20
|
# Reserved for future use
|
25
21
|
class ServerError < StandardError; end
|
26
22
|
|
23
|
+
class BackgroundLoadingError < StandardError; end
|
24
|
+
|
27
25
|
# add some convenience methods for easy access to the Agent singleton.
|
28
26
|
# the following static methods all point to the same Agent instance:
|
29
27
|
#
|
@@ -171,13 +169,15 @@ module NewRelic::Agent
|
|
171
169
|
def start(environment, identifier, force=false)
|
172
170
|
|
173
171
|
if @started
|
174
|
-
log! "Agent Started Already!"
|
172
|
+
config.log! "Agent Started Already!"
|
175
173
|
return
|
176
174
|
end
|
177
175
|
@environment = environment
|
178
176
|
@identifier = identifier && identifier.to_s
|
179
177
|
if @identifier
|
180
178
|
start_reporting(force)
|
179
|
+
config.log! "New Relic RPM Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
|
180
|
+
config.log! "Agent Log is found in #{NewRelic::Config.instance.log_file}"
|
181
181
|
return true
|
182
182
|
else
|
183
183
|
return false
|
@@ -323,7 +323,7 @@ module NewRelic::Agent
|
|
323
323
|
# note if the agent attempts to report more frequently than the specified
|
324
324
|
# report data, then it will be ignored.
|
325
325
|
|
326
|
-
log! "Reporting performance data every #{@report_period} seconds"
|
326
|
+
config.log! "Reporting performance data every #{@report_period} seconds"
|
327
327
|
@worker_loop.add_task(@report_period) do
|
328
328
|
harvest_and_send_timeslice_data
|
329
329
|
end
|
@@ -358,22 +358,21 @@ module NewRelic::Agent
|
|
358
358
|
|
359
359
|
@worker_loop = WorkerLoop.new(log)
|
360
360
|
|
361
|
-
if
|
361
|
+
if config['check_bg_loading']
|
362
362
|
require 'new_relic/agent/patch_const_missing'
|
363
|
-
|
363
|
+
log.warn "Agent background loading checking turned on"
|
364
|
+
ClassLoadingWatcher.enable_warning
|
364
365
|
end
|
365
366
|
|
366
367
|
@worker_thread = Thread.new do
|
367
368
|
begin
|
368
|
-
if
|
369
|
-
self.class.newrelic_set_agent_thread(Thread.current)
|
370
|
-
end
|
369
|
+
ClassLoadingWatcher.set_background_thread(Thread.current) if config['check_bg_loading']
|
371
370
|
run_worker_loop
|
372
371
|
rescue IgnoreSilentlyException
|
373
|
-
log! "Unable to establish connection with the server. Run with log level set to debug for more information."
|
372
|
+
config.log! "Unable to establish connection with the server. Run with log level set to debug for more information."
|
374
373
|
rescue StandardError => e
|
375
|
-
log! e
|
376
|
-
log! e.backtrace.join("\n")
|
374
|
+
config.log! e
|
375
|
+
config.log! e.backtrace.join("\n")
|
377
376
|
end
|
378
377
|
end
|
379
378
|
|
@@ -381,7 +380,7 @@ module NewRelic::Agent
|
|
381
380
|
# by stopping the foreground thread after the background thread is created. Turn on dependency loading logging
|
382
381
|
# and make sure that no loading occurs.
|
383
382
|
#
|
384
|
-
# log! "FINISHED AGENT INIT"
|
383
|
+
# config.log! "FINISHED AGENT INIT"
|
385
384
|
# while true
|
386
385
|
# sleep 1
|
387
386
|
# end
|
@@ -438,7 +437,7 @@ module NewRelic::Agent
|
|
438
437
|
# make sure the license key exists and is likely to be really a license key
|
439
438
|
# by checking it's string length (license keys are 40 character strings.)
|
440
439
|
if @prod_mode_enabled && (!@license_key || @license_key.length != 40)
|
441
|
-
log! "No license key found. Please edit your newrelic.yml file and insert your license key"
|
440
|
+
config.log! "No license key found. Please edit your newrelic.yml file and insert your license key"
|
442
441
|
return
|
443
442
|
end
|
444
443
|
|
@@ -504,7 +503,7 @@ module NewRelic::Agent
|
|
504
503
|
config.settings
|
505
504
|
@report_period = invoke_remote :get_data_report_period, @agent_id
|
506
505
|
|
507
|
-
log! "Connected to NewRelic Service at #{config.server}"
|
506
|
+
config.log! "Connected to NewRelic Service at #{config.server}"
|
508
507
|
log.debug "Agent ID = #{@agent_id}."
|
509
508
|
|
510
509
|
# Ask the server for permission to send transaction samples. determined by subscription license.
|
@@ -519,8 +518,8 @@ module NewRelic::Agent
|
|
519
518
|
@connected = true
|
520
519
|
|
521
520
|
rescue LicenseException => e
|
522
|
-
log! e.message, :error
|
523
|
-
log! "Visit NewRelic.com to obtain a valid license key, or to upgrade your account."
|
521
|
+
config.log! e.message, :error
|
522
|
+
config.log! "Visit NewRelic.com to obtain a valid license key, or to upgrade your account."
|
524
523
|
@invalid_license = true
|
525
524
|
return false
|
526
525
|
|
@@ -576,12 +575,12 @@ module NewRelic::Agent
|
|
576
575
|
@harvest_thread ||= Thread.current
|
577
576
|
|
578
577
|
if @harvest_thread != Thread.current
|
579
|
-
log! "ERROR - two harvest threads are running (current=#{Thread.current}, havest=#{@harvest_thread}"
|
578
|
+
config.log! "ERROR - two harvest threads are running (current=#{Thread.current}, havest=#{@harvest_thread}"
|
580
579
|
@harvest_thread = Thread.current
|
581
580
|
end
|
582
581
|
|
583
582
|
# Fixme: remove this check
|
584
|
-
log! "Agent sending data too frequently - #{now - @last_harvest_time} seconds" if (now.to_f - @last_harvest_time.to_f) < 45
|
583
|
+
config.log! "Agent sending data too frequently - #{now - @last_harvest_time} seconds" if (now.to_f - @last_harvest_time.to_f) < 45
|
585
584
|
|
586
585
|
@unsent_timeslice_data ||= {}
|
587
586
|
@unsent_timeslice_data = @stats_engine.harvest_timeslice_data(@unsent_timeslice_data, @metric_ids)
|
@@ -697,9 +696,9 @@ module NewRelic::Agent
|
|
697
696
|
raise IgnoreSilentlyException
|
698
697
|
end
|
699
698
|
rescue ForceDisconnectException => e
|
700
|
-
log! "RPM forced this agent to disconnect", :error
|
701
|
-
log! e.message, :error
|
702
|
-
log! "Restart this process to resume RPM's agent communication with NewRelic.com"
|
699
|
+
config.log! "RPM forced this agent to disconnect", :error
|
700
|
+
config.log! e.message, :error
|
701
|
+
config.log! "Restart this process to resume RPM's agent communication with NewRelic.com"
|
703
702
|
# when a disconnect is requested, stop the current thread, which is the worker thread that
|
704
703
|
# gathers data and talks to the server.
|
705
704
|
@connected = false
|
@@ -710,14 +709,6 @@ module NewRelic::Agent
|
|
710
709
|
raise IgnoreSilentlyException
|
711
710
|
end
|
712
711
|
|
713
|
-
# send the given message to STDERR as well as the agent log, so that it shows
|
714
|
-
# up in the console. This should be used for important informational messages at boot
|
715
|
-
def log!(msg, level = :info)
|
716
|
-
# only log to stderr when we are running as a mongrel process, so it doesn't
|
717
|
-
# muck with daemons and the like.
|
718
|
-
config.log!(msg, level)
|
719
|
-
end
|
720
|
-
|
721
712
|
def graceful_disconnect
|
722
713
|
if @connected && !(config.server.host == "localhost" && @identifier == '3000')
|
723
714
|
begin
|
@@ -3,19 +3,19 @@ module NewRelic::Agent::CollectionHelper
|
|
3
3
|
# strings
|
4
4
|
def normalize_params(params)
|
5
5
|
case params
|
6
|
-
when Symbol, FalseClass, TrueClass, nil
|
6
|
+
when Symbol, FalseClass, TrueClass, nil
|
7
7
|
params
|
8
8
|
when Numeric
|
9
9
|
truncate(params.to_s)
|
10
10
|
when String
|
11
11
|
truncate(params)
|
12
|
-
when Hash
|
12
|
+
when Hash
|
13
13
|
new_params = {}
|
14
14
|
params.each do | key, value |
|
15
15
|
new_params[truncate(normalize_params(key),32)] = normalize_params(value)
|
16
16
|
end
|
17
17
|
new_params
|
18
|
-
when Enumerable
|
18
|
+
when Enumerable
|
19
19
|
# We only want the first 20 values of any enumerable. Invoking to_a.first(20) works but
|
20
20
|
# the to_a call might be expensive, so we'll just build it manually, even though it's
|
21
21
|
# more verbose.
|
@@ -78,4 +78,4 @@ module NewRelic::Agent::CollectionHelper
|
|
78
78
|
truncate(flatten(string), len)
|
79
79
|
end
|
80
80
|
end
|
81
|
-
end
|
81
|
+
end
|
@@ -73,7 +73,7 @@ module NewRelic::Agent::Instrumentation
|
|
73
73
|
# Skip instrumentation based on the value of 'do_not_trace' and if
|
74
74
|
# we aren't calling directly with a block.
|
75
75
|
should_skip = !block_given? && case ignore_actions
|
76
|
-
when nil
|
76
|
+
when nil; false
|
77
77
|
when Hash
|
78
78
|
only_actions = Array(ignore_actions[:only])
|
79
79
|
except_actions = Array(ignore_actions[:except])
|
@@ -1,31 +1,105 @@
|
|
1
1
|
# This class is for debugging purposes only.
|
2
|
-
#
|
3
|
-
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
2
|
+
# It inserts instrumentation into class loading to verify
|
3
|
+
# that no classes are being loaded on the new relic thread,
|
4
|
+
# which can cause problems in the class loader code.
|
5
|
+
|
6
|
+
module ClassLoadingWatcher
|
7
|
+
|
8
|
+
extend self
|
9
|
+
@@background_thread = nil
|
10
|
+
|
11
|
+
def background_thread
|
12
|
+
@@background_thread
|
12
13
|
end
|
13
14
|
|
14
|
-
def
|
15
|
+
def set_background_thread(thread)
|
16
|
+
@@background_thread = thread
|
17
|
+
|
18
|
+
# these tests that check is working...
|
19
|
+
# begin
|
20
|
+
# bad = Bad
|
21
|
+
# rescue
|
22
|
+
# end
|
23
|
+
|
24
|
+
# require 'new_relic/agent/patch_const_missing'
|
25
|
+
# load 'new_relic/agent/patch_const_missing.rb'
|
26
|
+
end
|
27
|
+
module SanityCheck
|
28
|
+
def new_relic_check_for_badness(*args)
|
29
|
+
|
30
|
+
if Thread.current == ClassLoadingWatcher.background_thread
|
31
|
+
msg = "Agent background thread shouldn't be loading classes (#{args.inspect})\n"
|
32
|
+
|
33
|
+
exception = NewRelic::Agent::BackgroundLoadingError.new(msg.clone)
|
34
|
+
exception.set_backtrace(caller)
|
35
|
+
|
36
|
+
NewRelic::Agent.instance.error_collector.notice_error(nil, nil, [], exception)
|
37
|
+
msg << caller.join("\n")
|
38
|
+
|
39
|
+
NewRelic::Config.instance.log.error msg
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
def enable_warning
|
44
|
+
Object.class_eval do
|
45
|
+
if !defined?(non_new_relic_require)
|
46
|
+
alias_method :non_new_relic_require, :require
|
47
|
+
alias_method :require, :new_relic_require
|
48
|
+
end
|
49
|
+
|
50
|
+
if !defined?(non_new_relic_load)
|
51
|
+
alias_method :non_new_relic_load, :load
|
52
|
+
alias_method :load, :new_relic_load
|
53
|
+
end
|
54
|
+
end
|
15
55
|
Module.class_eval do
|
16
|
-
if !defined?(
|
17
|
-
alias_method :
|
56
|
+
if !defined?(non_new_relic_const_missing)
|
57
|
+
alias_method :non_new_relic_const_missing, :const_missing
|
18
58
|
alias_method :const_missing, :new_relic_const_missing
|
19
59
|
end
|
20
60
|
end
|
21
61
|
end
|
22
|
-
|
62
|
+
|
63
|
+
def disable_warning
|
64
|
+
Object.class_eval do
|
65
|
+
if defined?(non_new_relic_require)
|
66
|
+
alias_method :require, :non_new_relic_require
|
67
|
+
undef non_new_relic_require
|
68
|
+
end
|
69
|
+
|
70
|
+
if defined?(non_new_relic_load)
|
71
|
+
alias_method :load, :non_new_relic_load
|
72
|
+
undef non_new_relic_load
|
73
|
+
end
|
74
|
+
end
|
23
75
|
Module.class_eval do
|
24
|
-
|
76
|
+
if defined?(non_new_relic_const_missing)
|
77
|
+
alias_method :const_missing, :non_new_relic_const_missing
|
78
|
+
undef non_new_relic_const_missing
|
79
|
+
end
|
25
80
|
end
|
26
81
|
end
|
82
|
+
end
|
83
|
+
|
84
|
+
class Object
|
85
|
+
include ClassLoadingWatcher::SanityCheck
|
86
|
+
|
87
|
+
def new_relic_require(*args)
|
88
|
+
new_relic_check_for_badness("Object require", *args)
|
89
|
+
non_new_relic_require(*args)
|
90
|
+
end
|
91
|
+
|
92
|
+
def new_relic_load(*args)
|
93
|
+
new_relic_check_for_badness("Object load", *args)
|
94
|
+
non_new_relic_load(*args)
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
class Module
|
99
|
+
include ClassLoadingWatcher::SanityCheck
|
27
100
|
|
28
|
-
def
|
29
|
-
|
101
|
+
def new_relic_const_missing(*args)
|
102
|
+
new_relic_check_for_badness("Module #{self.name} const_missing", *args)
|
103
|
+
non_new_relic_const_missing(*args)
|
30
104
|
end
|
31
105
|
end
|
data/lib/new_relic/config.rb
CHANGED
@@ -11,6 +11,8 @@ require 'net/https'
|
|
11
11
|
module NewRelic
|
12
12
|
|
13
13
|
class Config
|
14
|
+
|
15
|
+
attr_accessor :log_file
|
14
16
|
|
15
17
|
# Structs holding info for the remote server and proxy server
|
16
18
|
class Server < Struct.new :host, :port
|
@@ -137,8 +139,8 @@ module NewRelic
|
|
137
139
|
end
|
138
140
|
|
139
141
|
def setup_log(identifier)
|
140
|
-
log_file = "#{log_path}/#{log_file_name(identifier)}"
|
141
|
-
@log = Logger.new log_file
|
142
|
+
@log_file = "#{log_path}/#{log_file_name(identifier)}"
|
143
|
+
@log = Logger.new @log_file
|
142
144
|
|
143
145
|
# change the format just for our logger
|
144
146
|
|
@@ -148,15 +150,13 @@ module NewRelic
|
|
148
150
|
|
149
151
|
# set the log level as specified in the config file
|
150
152
|
case fetch("log_level","info").downcase
|
151
|
-
when "debug"
|
152
|
-
when "info"
|
153
|
-
when "warn"
|
154
|
-
when "error"
|
155
|
-
when "fatal"
|
153
|
+
when "debug"; @log.level = Logger::DEBUG
|
154
|
+
when "info"; @log.level = Logger::INFO
|
155
|
+
when "warn"; @log.level = Logger::WARN
|
156
|
+
when "error"; @log.level = Logger::ERROR
|
157
|
+
when "fatal"; @log.level = Logger::FATAL
|
156
158
|
else @log.level = Logger::INFO
|
157
159
|
end
|
158
|
-
log! "New Relic RPM Agent #{NewRelic::VERSION::STRING} Initialized: pid = #{$$}"
|
159
|
-
log! "Agent Log is found in #{log_file}"
|
160
160
|
@log
|
161
161
|
end
|
162
162
|
|
data/lib/new_relic/version.rb
CHANGED
@@ -3,7 +3,7 @@ module NewRelic
|
|
3
3
|
module VERSION #:nodoc:
|
4
4
|
MAJOR = 2
|
5
5
|
MINOR = 8
|
6
|
-
TINY =
|
6
|
+
TINY = 2
|
7
7
|
STRING = [MAJOR, MINOR, TINY].join('.')
|
8
8
|
def self.changes
|
9
9
|
puts "NewRelic RPM Plugin Version: #{NewRelic::VERSION::STRING}"
|
@@ -12,6 +12,10 @@ module NewRelic
|
|
12
12
|
|
13
13
|
CHANGELOG = <<EOF
|
14
14
|
|
15
|
+
2009-02-07 version 2.8.2
|
16
|
+
* fix Ruby 1.9 syntax compatibility errors
|
17
|
+
* update the class loading sanity check, will notify server of errors
|
18
|
+
* fix agent output on script and rake task execution
|
15
19
|
2009-01-27 version 2.8.1
|
16
20
|
* Convert the deployment information upload script to an executable
|
17
21
|
and put in the bin directory. When installed as a gem this command
|
data/lib/newrelic_rpm.rb
CHANGED
@@ -59,19 +59,55 @@ class AgentTests < ActiveSupport::TestCase
|
|
59
59
|
|
60
60
|
def test_classloading_patch
|
61
61
|
require 'new_relic/agent/patch_const_missing'
|
62
|
-
|
63
|
-
|
64
|
-
NewRelic::Config.instance.log.expects(:
|
65
|
-
NewRelic::Config.instance.log.expects(:
|
66
|
-
|
62
|
+
ClassLoadingWatcher.set_background_thread(Thread.current)
|
63
|
+
|
64
|
+
NewRelic::Config.instance.log.expects(:error).at_least_once.with{|args| args =~ /Agent background thread.*:FooBar/}
|
65
|
+
NewRelic::Config.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*:FooBaz/}.never
|
66
|
+
|
67
|
+
ClassLoadingWatcher.enable_warning
|
67
68
|
assert_raise NameError do
|
68
69
|
FooBar::Bat
|
69
70
|
end
|
70
|
-
|
71
|
+
ClassLoadingWatcher.disable_warning
|
71
72
|
assert_raise NameError do
|
72
73
|
FooBaz::Bat
|
73
74
|
end
|
74
75
|
end
|
76
|
+
|
77
|
+
def test_require
|
78
|
+
require 'new_relic/agent/patch_const_missing'
|
79
|
+
ClassLoadingWatcher.set_background_thread(Thread.current)
|
80
|
+
|
81
|
+
# try loading some non-existent class
|
82
|
+
NewRelic::Config.instance.log.expects(:error).at_least_once.with{|args| args =~ /Agent background thread.*net/}
|
83
|
+
NewRelic::Config.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*net/}.never
|
84
|
+
|
85
|
+
ClassLoadingWatcher.enable_warning
|
86
|
+
|
87
|
+
require 'net/http'
|
88
|
+
|
89
|
+
ClassLoadingWatcher.disable_warning
|
90
|
+
|
91
|
+
require 'net/http'
|
92
|
+
end
|
93
|
+
|
94
|
+
def test_load
|
95
|
+
require 'new_relic/agent/patch_const_missing'
|
96
|
+
ClassLoadingWatcher.set_background_thread(Thread.current)
|
97
|
+
|
98
|
+
# try loading some non-existent class
|
99
|
+
NewRelic::Config.instance.log.expects(:error).at_least_once.with{|args| args =~ /Agent background thread.*/}
|
100
|
+
NewRelic::Config.instance.log.expects(:error).with{|args| args =~ /Agent background thread.*/}.never
|
101
|
+
|
102
|
+
ClassLoadingWatcher.enable_warning
|
103
|
+
|
104
|
+
load 'net/http.rb'
|
105
|
+
|
106
|
+
ClassLoadingWatcher.disable_warning
|
107
|
+
|
108
|
+
load 'net/http.rb'
|
109
|
+
end
|
110
|
+
|
75
111
|
def test_info
|
76
112
|
props = NewRelic::Config.instance.app_config_info
|
77
113
|
list = props.assoc('Plugin List').last.sort
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: newrelic_rpm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.8.
|
4
|
+
version: 2.8.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Bill Kayser
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-
|
12
|
+
date: 2009-02-05 00:00:00 -08:00
|
13
13
|
default_executable: newrelic_cmd
|
14
14
|
dependencies: []
|
15
15
|
|
@@ -175,7 +175,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
175
175
|
requirements: []
|
176
176
|
|
177
177
|
rubyforge_project: newrelic
|
178
|
-
rubygems_version: 1.3.
|
178
|
+
rubygems_version: 1.3.1
|
179
179
|
signing_key:
|
180
180
|
specification_version: 2
|
181
181
|
summary: New Relic Ruby Performance Monitoring Agent
|