newrelic_rpm 2.8.1 → 2.8.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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
|