newrelic_rpm 3.1.0 → 3.1.1.beta1
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/CHANGELOG +3 -0
- data/lib/new_relic/agent.rb +29 -12
- data/lib/new_relic/agent/agent.rb +355 -78
- data/lib/new_relic/agent/beacon_configuration.rb +49 -7
- data/lib/new_relic/agent/browser_monitoring.rb +20 -1
- data/lib/new_relic/agent/busy_calculator.rb +11 -3
- data/lib/new_relic/agent/chained_call.rb +2 -2
- data/lib/new_relic/agent/error_collector.rb +229 -183
- data/lib/new_relic/agent/instrumentation.rb +2 -2
- data/lib/new_relic/agent/instrumentation/active_merchant.rb +5 -1
- data/lib/new_relic/agent/instrumentation/acts_as_solr.rb +5 -1
- data/lib/new_relic/agent/instrumentation/authlogic.rb +4 -0
- data/lib/new_relic/agent/instrumentation/controller_instrumentation.rb +16 -5
- data/lib/new_relic/agent/instrumentation/data_mapper.rb +5 -1
- data/lib/new_relic/agent/instrumentation/delayed_job_instrumentation.rb +5 -1
- data/lib/new_relic/agent/instrumentation/memcache.rb +5 -1
- data/lib/new_relic/agent/instrumentation/merb/controller.rb +5 -1
- data/lib/new_relic/agent/instrumentation/merb/errors.rb +5 -1
- data/lib/new_relic/agent/instrumentation/metric_frame/pop.rb +0 -5
- data/lib/new_relic/agent/instrumentation/net.rb +5 -1
- data/lib/new_relic/agent/instrumentation/rails/action_controller.rb +7 -3
- data/lib/new_relic/agent/instrumentation/rails/action_web_service.rb +5 -1
- data/lib/new_relic/agent/instrumentation/rails/active_record_instrumentation.rb +5 -1
- data/lib/new_relic/agent/instrumentation/rails/errors.rb +4 -0
- data/lib/new_relic/agent/instrumentation/rails3/action_controller.rb +4 -0
- data/lib/new_relic/agent/instrumentation/rails3/active_record_instrumentation.rb +13 -6
- data/lib/new_relic/agent/instrumentation/rails3/errors.rb +4 -0
- data/lib/new_relic/agent/instrumentation/sinatra.rb +4 -0
- data/lib/new_relic/agent/instrumentation/sunspot.rb +4 -0
- data/lib/new_relic/agent/instrumentation/unicorn_instrumentation.rb +5 -1
- data/lib/new_relic/agent/method_tracer.rb +205 -99
- data/lib/new_relic/agent/shim_agent.rb +0 -1
- data/lib/new_relic/agent/stats_engine.rb +1 -0
- data/lib/new_relic/agent/stats_engine/metric_stats.rb +23 -7
- data/lib/new_relic/agent/stats_engine/samplers.rb +8 -2
- data/lib/new_relic/agent/stats_engine/transactions.rb +26 -12
- data/lib/new_relic/agent/transaction_sampler.rb +3 -1
- data/lib/new_relic/agent/worker_loop.rb +13 -5
- data/lib/new_relic/collection_helper.rb +6 -3
- data/lib/new_relic/control.rb +1 -3
- data/lib/new_relic/control/class_methods.rb +8 -3
- data/lib/new_relic/control/configuration.rb +24 -5
- data/lib/new_relic/control/frameworks.rb +10 -0
- data/lib/new_relic/control/frameworks/external.rb +4 -4
- data/lib/new_relic/control/frameworks/merb.rb +1 -0
- data/lib/new_relic/control/frameworks/rails.rb +5 -5
- data/lib/new_relic/control/frameworks/rails3.rb +5 -3
- data/lib/new_relic/control/frameworks/ruby.rb +5 -5
- data/lib/new_relic/control/frameworks/sinatra.rb +1 -4
- data/lib/new_relic/control/instance_methods.rb +23 -7
- data/lib/new_relic/control/instrumentation.rb +22 -3
- data/lib/new_relic/control/logging_methods.rb +25 -7
- data/lib/new_relic/control/server_methods.rb +16 -6
- data/lib/new_relic/data_serialization.rb +83 -14
- data/lib/new_relic/delayed_job_injection.rb +7 -1
- data/lib/new_relic/local_environment.rb +55 -25
- data/lib/new_relic/metric_data.rb +7 -2
- data/lib/new_relic/metric_spec.rb +5 -3
- data/lib/new_relic/stats.rb +16 -7
- data/lib/new_relic/transaction_analysis.rb +2 -1
- data/lib/new_relic/transaction_analysis/segment_summary.rb +4 -2
- data/lib/new_relic/transaction_sample.rb +33 -7
- data/lib/new_relic/transaction_sample/segment.rb +21 -3
- data/lib/new_relic/version.rb +2 -2
- data/newrelic_rpm.gemspec +7 -11
- data/test/config/newrelic.yml +1 -1
- data/test/new_relic/agent/agent/start_worker_thread_test.rb +1 -4
- data/test/new_relic/agent/agent_test.rb +16 -0
- data/test/new_relic/agent/agent_test_controller.rb +1 -1
- data/test/new_relic/agent/agent_test_controller_test.rb +14 -19
- data/test/new_relic/agent/beacon_configuration_test.rb +2 -2
- data/test/new_relic/agent/browser_monitoring_test.rb +7 -3
- data/test/new_relic/agent/instrumentation/active_record_instrumentation_test.rb +13 -4
- data/test/new_relic/agent/instrumentation/metric_frame/pop_test.rb +0 -10
- data/test/new_relic/agent/method_tracer/instance_methods/trace_execution_scoped_test.rb +1 -1
- data/test/new_relic/agent_test.rb +168 -0
- data/test/new_relic/collection_helper_test.rb +21 -3
- data/test/new_relic/control/configuration_test.rb +25 -0
- data/test/new_relic/data_serialization_test.rb +58 -3
- data/test/new_relic/delayed_job_injection_test.rb +17 -0
- data/test/new_relic/transaction_analysis/segment_summary_test.rb +14 -0
- data/test/new_relic/transaction_analysis_test.rb +3 -3
- data/test/new_relic/transaction_sample/segment_test.rb +11 -0
- data/test/test_helper.rb +1 -1
- data/vendor/gems/dependency_detection-0.0.1.build/LICENSE +4 -18
- metadata +13 -13
- data/lib/new_relic/histogram.rb +0 -91
- data/lib/new_relic/rack/metric_app.rb +0 -65
- data/lib/new_relic/rack/mongrel_rpm.ru +0 -28
- data/lib/new_relic/rack/newrelic.yml +0 -27
- data/lib/new_relic/rack_app.rb +0 -6
- data/vendor/gems/dependency_detection-0.0.1.build/README +0 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/LICENSE +0 -0
- data/vendor/gems/metric_parser-0.1.0.pre1/README +0 -0
@@ -1,10 +1,10 @@
|
|
1
|
-
# Control subclass instantiated when Rails is detected. Contains
|
2
|
-
# Rails specific configuration, instrumentation, environment values,
|
3
|
-
# etc.
|
4
1
|
require 'new_relic/control/frameworks/ruby'
|
5
2
|
module NewRelic
|
6
3
|
class Control
|
7
4
|
module Frameworks
|
5
|
+
# Control subclass instantiated when Rails is detected. Contains
|
6
|
+
# Rails specific configuration, instrumentation, environment values,
|
7
|
+
# etc.
|
8
8
|
class Rails < NewRelic::Control::Frameworks::Ruby
|
9
9
|
|
10
10
|
def env
|
@@ -139,8 +139,8 @@ module NewRelic
|
|
139
139
|
|
140
140
|
def _install_instrumentation
|
141
141
|
super
|
142
|
-
if defined?(Rails) && Rails.respond_to?(:configuration) && Rails.configuration.respond_to?(:after_initialize)
|
143
|
-
Rails.configuration.after_initialize do
|
142
|
+
if defined?(::Rails) && ::Rails.respond_to?(:configuration) && ::Rails.configuration.respond_to?(:after_initialize)
|
143
|
+
::Rails.configuration.after_initialize do
|
144
144
|
DependencyDetection.detect!
|
145
145
|
end
|
146
146
|
end
|
@@ -1,10 +1,12 @@
|
|
1
|
-
# Control subclass instantiated when Rails is detected. Contains
|
2
|
-
# Rails specific configuration, instrumentation, environment values,
|
3
|
-
# etc.
|
4
1
|
require 'new_relic/control/frameworks/rails'
|
5
2
|
module NewRelic
|
6
3
|
class Control
|
7
4
|
module Frameworks
|
5
|
+
# Control subclass instantiated when Rails is detected. Contains
|
6
|
+
# Rails 3.0+ specific configuration, instrumentation, environment values,
|
7
|
+
# etc. Many methods are inherited from the
|
8
|
+
# NewRelic::Control::Frameworks::Rails class, where the two do
|
9
|
+
# not differ
|
8
10
|
class Rails3 < NewRelic::Control::Frameworks::Rails
|
9
11
|
|
10
12
|
def env
|
@@ -1,11 +1,11 @@
|
|
1
|
-
# A control used when no framework is detected.
|
2
|
-
# Looks for a newrelic.yml file in several locations
|
3
|
-
# including ./, ./config, $HOME/.newrelic and $HOME/.
|
4
|
-
# It loads the settings from the newrelic.yml section
|
5
|
-
# based on the value of RUBY_ENV or RAILS_ENV.
|
6
1
|
module NewRelic
|
7
2
|
class Control
|
8
3
|
module Frameworks
|
4
|
+
# A control used when no framework is detected - the default.
|
5
|
+
# Looks for a newrelic.yml file in several locations including
|
6
|
+
# ./, ./config, $HOME/.newrelic and $HOME/. It loads the
|
7
|
+
# settings from the newrelic.yml section based on the value of
|
8
|
+
# RUBY_ENV or RAILS_ENV.
|
9
9
|
class Ruby < NewRelic::Control
|
10
10
|
|
11
11
|
def env
|
@@ -3,16 +3,13 @@ require 'new_relic/control/frameworks/ruby'
|
|
3
3
|
module NewRelic
|
4
4
|
class Control
|
5
5
|
module Frameworks
|
6
|
+
# Contains basic control logic for Sinatra
|
6
7
|
class Sinatra < NewRelic::Control::Frameworks::Ruby
|
7
8
|
|
8
9
|
def env
|
9
10
|
@env ||= ENV['RACK_ENV'] || ENV['RAILS_ENV'] || 'development'
|
10
11
|
end
|
11
12
|
|
12
|
-
# This is the control used when starting up in the context of
|
13
|
-
# The New Relic Infrastructure Agent. We want to call this
|
14
|
-
# out specifically because in this context we are not monitoring
|
15
|
-
# the running process, but actually external things.
|
16
13
|
def init_config(options={})
|
17
14
|
super
|
18
15
|
end
|
@@ -1,11 +1,18 @@
|
|
1
1
|
module NewRelic
|
2
2
|
class Control
|
3
|
+
# Contains methods that relate to the runtime usage of the control
|
4
|
+
# object. Note that these are subject to override in the
|
5
|
+
# NewRelic::Control::Framework classes that are actually instantiated
|
3
6
|
module InstanceMethods
|
4
7
|
# The env is the setting used to identify which section of the newrelic.yml
|
5
8
|
# to load. This defaults to a framework specific value, such as ENV['RAILS_ENV']
|
6
9
|
# but can be overridden as long as you set it before calling #init_plugin
|
7
10
|
attr_writer :env
|
8
11
|
|
12
|
+
# The local environment contains all the information we report
|
13
|
+
# to the server about what kind of application this is, what
|
14
|
+
# gems and plugins it uses, and many other kinds of
|
15
|
+
# machine-dependent information useful in debugging
|
9
16
|
attr_reader :local_env
|
10
17
|
|
11
18
|
|
@@ -90,13 +97,14 @@ module NewRelic
|
|
90
97
|
# dispatcher running
|
91
98
|
return true if @local_env.dispatcher != nil
|
92
99
|
end
|
93
|
-
|
100
|
+
|
101
|
+
# Asks the LocalEnvironment instance which framework should be loaded
|
94
102
|
def app
|
95
103
|
@local_env.framework
|
96
104
|
end
|
97
105
|
alias framework app
|
98
|
-
|
99
|
-
def to_s
|
106
|
+
|
107
|
+
def to_s #:nodoc:
|
100
108
|
"Control[#{self.app}]"
|
101
109
|
end
|
102
110
|
|
@@ -105,7 +113,9 @@ module NewRelic
|
|
105
113
|
# Append framework specific environment information for uploading to
|
106
114
|
# the server for change detection. Override in subclasses
|
107
115
|
def append_environment_info; end
|
108
|
-
|
116
|
+
|
117
|
+
# Asks bundler to tell us which gemspecs are loaded in the
|
118
|
+
# current process
|
109
119
|
def bundler_gem_list
|
110
120
|
if defined?(Bundler) && Bundler.instance_eval do @load end
|
111
121
|
Bundler.load.specs.map do | spec |
|
@@ -116,11 +126,15 @@ module NewRelic
|
|
116
126
|
[]
|
117
127
|
end
|
118
128
|
end
|
119
|
-
|
129
|
+
|
130
|
+
# path to the config file, defaults to the "#{root}/config/newrelic.yml"
|
120
131
|
def config_file
|
121
132
|
File.expand_path(File.join(root,"config","newrelic.yml"))
|
122
133
|
end
|
123
|
-
|
134
|
+
|
135
|
+
# initializes the control instance with a local environment and
|
136
|
+
# an optional config file override. Checks for the config file
|
137
|
+
# and loads it.
|
124
138
|
def initialize local_env, config_file_override=nil
|
125
139
|
@local_env = local_env
|
126
140
|
@instrumentation_files = []
|
@@ -140,11 +154,13 @@ module NewRelic
|
|
140
154
|
puts e.backtrace.join("\n")
|
141
155
|
raise "Error reading newrelic.yml file: #{e}"
|
142
156
|
end
|
143
|
-
|
157
|
+
|
144
158
|
def root
|
145
159
|
'.'
|
146
160
|
end
|
147
161
|
|
162
|
+
# Delegates to the class method newrelic_root, implemented by
|
163
|
+
# each subclass
|
148
164
|
def newrelic_root
|
149
165
|
self.class.newrelic_root
|
150
166
|
end
|
@@ -1,6 +1,17 @@
|
|
1
1
|
module NewRelic
|
2
2
|
class Control
|
3
|
+
# Contains methods that relate to adding and executing files that
|
4
|
+
# contain instrumentation for the Ruby Agent
|
3
5
|
module Instrumentation
|
6
|
+
|
7
|
+
# Adds a list of files in Dir.glob format
|
8
|
+
# (e.g. '/app/foo/**/*_instrumentation.rb')
|
9
|
+
# This requires the files within a rescue block, so that any
|
10
|
+
# errors within instrumentation files do not affect the overall
|
11
|
+
# agent or application in which it runs.
|
12
|
+
#
|
13
|
+
# Logs at debug level for each file loaded, and logs errors in
|
14
|
+
# file loading at error level
|
4
15
|
def load_instrumentation_files pattern
|
5
16
|
Dir.glob(pattern) do |file|
|
6
17
|
begin
|
@@ -23,8 +34,11 @@ module NewRelic
|
|
23
34
|
|
24
35
|
# Add instrumentation. Don't call this directly. Use NewRelic::Agent#add_instrumentation.
|
25
36
|
# This will load the file synchronously if we've already loaded the default
|
26
|
-
# instrumentation
|
37
|
+
# instrumentation, otherwise instrumentation files specified
|
38
|
+
# here will be deferred until all instrumentation is run
|
27
39
|
#
|
40
|
+
# This happens after the agent has loaded and all dependencies
|
41
|
+
# are ready to be instrumented
|
28
42
|
def add_instrumentation pattern
|
29
43
|
if @instrumented
|
30
44
|
load_instrumentation_files pattern
|
@@ -32,11 +46,16 @@ module NewRelic
|
|
32
46
|
@instrumentation_files << pattern
|
33
47
|
end
|
34
48
|
end
|
35
|
-
|
49
|
+
|
50
|
+
# Signals the agent that it's time to actually load the
|
51
|
+
# instrumentation files. May be overridden by subclasses
|
36
52
|
def install_instrumentation
|
37
53
|
_install_instrumentation
|
38
54
|
end
|
39
|
-
|
55
|
+
|
56
|
+
# adds samplers to the stats engine so that they run every
|
57
|
+
# minute. This is dynamically recognized by any class that
|
58
|
+
# subclasses NewRelic::Agent::Sampler
|
40
59
|
def load_samplers
|
41
60
|
agent = NewRelic::Agent.instance
|
42
61
|
NewRelic::Agent::Sampler.sampler_classes.each do | subclass |
|
@@ -1,12 +1,16 @@
|
|
1
1
|
|
2
2
|
module NewRelic
|
3
3
|
class Control
|
4
|
+
# Contains methods that relate to locating, creating, and writing
|
5
|
+
# to the log file and/or standard out
|
4
6
|
module LoggingMethods
|
5
7
|
|
6
8
|
attr_accessor :log_file
|
7
|
-
|
9
|
+
|
10
|
+
# returns either the log set up with setup_log or else a new
|
11
|
+
# logger pointing to standard out, if we're trying to log before
|
12
|
+
# a log exists
|
8
13
|
def log
|
9
|
-
# If we try to get a log before one has been set up, return a stdout log
|
10
14
|
unless @log
|
11
15
|
l = Logger.new(STDOUT)
|
12
16
|
l.level = Logger::INFO
|
@@ -24,12 +28,18 @@ module NewRelic
|
|
24
28
|
return unless should_log?
|
25
29
|
log.send level, msg if @log
|
26
30
|
end
|
27
|
-
|
31
|
+
|
32
|
+
# true if the agent has settings, and the agent is enabled,
|
33
|
+
# otherwise false
|
28
34
|
def should_log?
|
29
35
|
@settings && agent_enabled?
|
30
36
|
end
|
31
37
|
|
32
38
|
# set the log level as specified in the config file
|
39
|
+
#
|
40
|
+
# Possible values are from the Logger class: debug, info, warn,
|
41
|
+
#error, and fatal
|
42
|
+
# Defaults to info
|
33
43
|
def set_log_level!(logger)
|
34
44
|
case fetch("log_level","info").downcase
|
35
45
|
when "debug" then logger.level = Logger::DEBUG
|
@@ -42,7 +52,7 @@ module NewRelic
|
|
42
52
|
logger
|
43
53
|
end
|
44
54
|
|
45
|
-
# change the format just for our logger
|
55
|
+
# patches the logger's format_message method to change the format just for our logger
|
46
56
|
def set_log_format!(logger)
|
47
57
|
def logger.format_message(severity, timestamp, progname, msg)
|
48
58
|
"[#{timestamp.strftime("%m/%d/%y %H:%M:%S %z")} #{Socket.gethostname} (#{$$})] #{severity} : #{msg}\n"
|
@@ -65,11 +75,17 @@ module NewRelic
|
|
65
75
|
# above
|
66
76
|
log
|
67
77
|
end
|
68
|
-
|
78
|
+
|
79
|
+
# simply puts a message to standard out, prepended with the
|
80
|
+
# '** [NewRelic]' sigil to make sure people know where the message
|
81
|
+
# comes from. This should be used sparingly
|
69
82
|
def to_stdout(msg)
|
70
83
|
STDOUT.puts "** [NewRelic] " + msg
|
71
84
|
end
|
72
|
-
|
85
|
+
|
86
|
+
# sets up and caches the log path, attempting to create it if it
|
87
|
+
#does not exist. this comes from the configuration variable
|
88
|
+
#'log_file_path' in the configuration file.
|
73
89
|
def log_path
|
74
90
|
return @log_path if @log_path
|
75
91
|
@log_path = File.expand_path(fetch('log_file_path', 'log/'))
|
@@ -78,7 +94,9 @@ module NewRelic
|
|
78
94
|
end
|
79
95
|
@log_path
|
80
96
|
end
|
81
|
-
|
97
|
+
|
98
|
+
# Retrieves the log file's name from the config file option
|
99
|
+
#'log_file_name', defaulting to 'newrelic_agent.log'
|
82
100
|
def log_file_name
|
83
101
|
fetch('log_file_name', 'newrelic_agent.log')
|
84
102
|
end
|
@@ -7,13 +7,16 @@ module NewRelic
|
|
7
7
|
end
|
8
8
|
|
9
9
|
ProxyServer = Struct.new :name, :port, :user, :password #:nodoc:
|
10
|
-
|
10
|
+
|
11
|
+
# Contains methods that deal with connecting to the server
|
11
12
|
module ServerMethods
|
12
|
-
|
13
|
+
|
13
14
|
def server
|
14
15
|
@remote_server ||= server_from_host(nil)
|
15
16
|
end
|
16
|
-
|
17
|
+
|
18
|
+
# the server we should contact for api requests, like uploading
|
19
|
+
# deployments and the like
|
17
20
|
def api_server
|
18
21
|
api_host = self['api_host'] || 'rpm.newrelic.com'
|
19
22
|
@api_server ||=
|
@@ -22,12 +25,17 @@ module NewRelic
|
|
22
25
|
(self['api_port'] || self['port'] || (use_ssl? ? 443 : 80)).to_i,
|
23
26
|
nil
|
24
27
|
end
|
25
|
-
|
28
|
+
|
29
|
+
# a new instances of the proxy server - this passes through if
|
30
|
+
# there is no proxy, otherwise it has proxy configuration
|
31
|
+
# information pulled from the config file
|
26
32
|
def proxy_server
|
27
33
|
@proxy_server ||=
|
28
34
|
NewRelic::Control::ProxyServer.new self['proxy_host'], self['proxy_port'], self['proxy_user'], self['proxy_pass']
|
29
35
|
end
|
30
|
-
|
36
|
+
|
37
|
+
# turns a hostname into an ip address and returns a
|
38
|
+
# NewRelic::Control::Server that contains the configuration info
|
31
39
|
def server_from_host(hostname=nil)
|
32
40
|
host = hostname || self['host'] || 'collector.newrelic.com'
|
33
41
|
|
@@ -66,7 +74,9 @@ module NewRelic
|
|
66
74
|
nil
|
67
75
|
end
|
68
76
|
end
|
69
|
-
|
77
|
+
|
78
|
+
# The path to the certificate file used to verify the SSL
|
79
|
+
# connection if verify_peer is enabled
|
70
80
|
def cert_file_path
|
71
81
|
File.expand_path(File.join(newrelic_root, 'cert', 'cacert.pem'))
|
72
82
|
end
|
@@ -1,26 +1,68 @@
|
|
1
1
|
require 'fileutils'
|
2
2
|
module NewRelic
|
3
|
+
# Handles serialization of data to disk, to save on contacting the
|
4
|
+
# server. Lowers both server and client overhead, if the disk is not overloaded
|
3
5
|
class DataSerialization
|
4
6
|
module ClassMethods
|
7
|
+
# Check whether the store is too large, too old, or the
|
8
|
+
# semaphore file is too old. If so, we should send the data
|
9
|
+
# right away. If not, we presumably store it for later sending
|
10
|
+
# (handled elsewhere)
|
5
11
|
def should_send_data?
|
6
|
-
|
7
|
-
rescue Exception => e
|
12
|
+
NewRelic::Control.instance.disable_serialization? || store_too_large? || store_too_old? || semaphore_too_old?
|
13
|
+
rescue (ENV['CATCH_EXCEPTION'] ? Exception : Class.new) => e
|
8
14
|
# This is not what we really should do here, but the fail-safe
|
9
15
|
# behavior is to do what the older agent did: send data every
|
10
16
|
# time we think we might want to send data.
|
11
17
|
true
|
12
18
|
end
|
13
|
-
|
19
|
+
|
20
|
+
# A combined locked read/write from the store file - reduces
|
21
|
+
# contention by not acquiring the lock and file handle twice
|
14
22
|
def read_and_write_to_file
|
15
23
|
with_locked_store do |f|
|
16
24
|
result = (yield get_data_from_file(f))
|
17
25
|
f.rewind
|
18
|
-
f.
|
26
|
+
f.truncate(0)
|
27
|
+
write_contents_nonblockingly(f, dump(result)) if result
|
19
28
|
end
|
20
29
|
end
|
21
|
-
|
30
|
+
|
31
|
+
# touches the age file that determines whether we should send
|
32
|
+
# data now or not
|
33
|
+
def update_last_sent!
|
34
|
+
FileUtils.touch(semaphore_path)
|
35
|
+
end
|
36
|
+
|
22
37
|
private
|
23
38
|
|
39
|
+
def store_too_large?
|
40
|
+
size = File.size(file_path) > max_size
|
41
|
+
NewRelic::Control.instance.log.debug("Store was oversize, sending data") if size
|
42
|
+
size
|
43
|
+
rescue Errno::ENOENT
|
44
|
+
FileUtils.touch(file_path)
|
45
|
+
retry
|
46
|
+
end
|
47
|
+
|
48
|
+
def store_too_old?
|
49
|
+
age = (Time.now.to_i - File.mtime(file_path).to_i)
|
50
|
+
NewRelic::Control.instance.log.debug("Store was #{age} seconds old, sending data") if age > 60
|
51
|
+
age > 50
|
52
|
+
rescue Errno::ENOENT
|
53
|
+
FileUtils.touch(file_path)
|
54
|
+
retry
|
55
|
+
end
|
56
|
+
|
57
|
+
def semaphore_too_old?
|
58
|
+
age = (Time.now.to_i - File.mtime(semaphore_path).to_i)
|
59
|
+
NewRelic::Control.instance.log.debug("Pid was #{age} seconds old, sending data") if age > 60
|
60
|
+
age > 60
|
61
|
+
rescue Errno::ENOENT
|
62
|
+
FileUtils.touch(semaphore_path)
|
63
|
+
retry
|
64
|
+
end
|
65
|
+
|
24
66
|
def open_arguments
|
25
67
|
if defined?(Encoding)
|
26
68
|
[file_path, File::RDWR | File::CREAT, {:internal_encoding => nil}]
|
@@ -44,38 +86,65 @@ module NewRelic
|
|
44
86
|
end
|
45
87
|
|
46
88
|
def get_data_from_file(f)
|
47
|
-
data = f
|
89
|
+
data = read_until_eof_error(f)
|
48
90
|
result = load(data)
|
49
91
|
f.truncate(0)
|
50
92
|
result
|
51
93
|
end
|
94
|
+
|
95
|
+
def write_contents_nonblockingly(f, string)
|
96
|
+
result = 0
|
97
|
+
while(result < string.length)
|
98
|
+
result += f.write_nonblock(string)
|
99
|
+
end
|
100
|
+
rescue Errno::EAGAIN, Errno::EINTR
|
101
|
+
IO.select(nil, [f])
|
102
|
+
retry
|
103
|
+
end
|
104
|
+
|
105
|
+
def read_until_eof_error(f)
|
106
|
+
accumulator = ""
|
107
|
+
while(true)
|
108
|
+
accumulator << f.read_nonblock(10_000)
|
109
|
+
end
|
110
|
+
rescue Errno::EAGAIN, Errno::EINTR
|
111
|
+
IO.select([f])
|
112
|
+
retry
|
113
|
+
rescue EOFError
|
114
|
+
accumulator
|
115
|
+
end
|
52
116
|
|
53
117
|
def max_size
|
54
118
|
10_000
|
55
119
|
end
|
56
120
|
|
57
|
-
def create_file_if_needed
|
58
|
-
FileUtils.touch(file_path) unless File.exists?(file_path)
|
59
|
-
end
|
60
|
-
|
61
121
|
def dump(object)
|
62
122
|
Marshal.dump(object)
|
63
123
|
end
|
64
124
|
|
65
125
|
def load(dump)
|
126
|
+
if dump.size == 0
|
127
|
+
NewRelic::Control.instance.log.debug("Spool file empty.")
|
128
|
+
return nil
|
129
|
+
end
|
66
130
|
Marshal.load(dump)
|
67
|
-
rescue ArgumentError => e
|
131
|
+
rescue ArgumentError, TypeError => e
|
132
|
+
NewRelic::Control.instance.log.error("Error loading data from newrelic_agent_store.db: #{e.inspect}")
|
133
|
+
NewRelic::Control.instance.log.debug(e.backtrace.inspect)
|
68
134
|
nil
|
69
135
|
end
|
70
136
|
|
71
137
|
def truncate_file
|
72
|
-
|
138
|
+
FileUtils.touch(file_path)
|
73
139
|
File.truncate(file_path, 0)
|
74
140
|
end
|
75
141
|
|
76
142
|
def file_path
|
77
|
-
#
|
78
|
-
|
143
|
+
"#{NewRelic::Control.instance.log_file_path}/newrelic_agent_store.db"
|
144
|
+
end
|
145
|
+
|
146
|
+
def semaphore_path
|
147
|
+
"#{NewRelic::Control.instance.log_file_path}/newrelic_agent_store.age"
|
79
148
|
end
|
80
149
|
end
|
81
150
|
extend ClassMethods
|