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.

@@ -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 VALIDATE_BACKGROUND_THREAD_LOADING
361
+ if config['check_bg_loading']
362
362
  require 'new_relic/agent/patch_const_missing'
363
- self.class.newrelic_enable_warning
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 VALIDATE_BACKGROUND_THREAD_LOADING
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: false
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
- class Module
4
- @@newrelic_agent_thread = nil
5
- def new_relic_const_missing(*args)
6
- if Thread.current == @@newrelic_agent_thread
7
- msg = "Agent background thread shouldn't be calling const_missing (#{args.inspect}) \n"
8
- msg << caller[0..4].join(" \n")
9
- NewRelic::Config.instance.log.warn msg
10
- end
11
- original_const_missing(*args)
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 newrelic_enable_warning
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?(original_const_missing)
17
- alias_method :original_const_missing, :const_missing
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
- def newrelic_disable_warning
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
- alias_method :const_missing, :original_const_missing if defined?(original_const_missing)
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 newrelic_set_agent_thread(thread)
29
- @@newrelic_agent_thread = thread
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
@@ -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": @log.level = Logger::DEBUG
152
- when "info": @log.level = Logger::INFO
153
- when "warn": @log.level = Logger::WARN
154
- when "error": @log.level = Logger::ERROR
155
- when "fatal": @log.level = Logger::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
 
@@ -329,7 +329,7 @@ module NewRelic
329
329
  next if k == :path
330
330
  s << " #{k}: " <<
331
331
  case v
332
- when Enumerable: v.map(&:to_s).sort.join("; ")
332
+ when Enumerable; v.map(&:to_s).sort.join("; ")
333
333
  else
334
334
  v
335
335
  end << "\n"
@@ -3,7 +3,7 @@ module NewRelic
3
3
  module VERSION #:nodoc:
4
4
  MAJOR = 2
5
5
  MINOR = 8
6
- TINY = 1
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
@@ -1,7 +1,7 @@
1
1
  # Initialization script for the gem.
2
2
  # Add
3
- # #require 'new_relic'
4
- # to your initialization sequence, as late as possible.
3
+ # config.gem 'newrelic_rpm'
4
+ # to your initialization sequence.
5
5
  #
6
6
  require 'new_relic/config'
7
7
 
@@ -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
- NewRelic::Agent::Agent.newrelic_set_agent_thread(Thread.current)
63
- # try loading some non-existent class
64
- NewRelic::Config.instance.log.expects(:warn).at_least_once.with{|args| args =~ /calling const_missing.*:FooBar/}
65
- NewRelic::Config.instance.log.expects(:warn).with{|args| args =~ /calling const_missing.*:FooBaz/}.never
66
- NewRelic::Agent::Agent.newrelic_enable_warning
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
- NewRelic::Agent::Agent.newrelic_disable_warning
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.1
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-01-29 00:00:00 -08:00
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.0
178
+ rubygems_version: 1.3.1
179
179
  signing_key:
180
180
  specification_version: 2
181
181
  summary: New Relic Ruby Performance Monitoring Agent