scout_apm 3.0.0.pre5 → 3.0.0.pre6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +4 -0
- data/lib/scout_apm/agent/reporting.rb +2 -2
- data/lib/scout_apm/agent.rb +7 -0
- data/lib/scout_apm/config.rb +71 -11
- data/lib/scout_apm/layaway.rb +48 -23
- data/lib/scout_apm/layer_converters/converter_base.rb +4 -4
- data/lib/scout_apm/reporter.rb +0 -1
- data/lib/scout_apm/server_integrations/puma.rb +5 -2
- data/lib/scout_apm/store.rb +4 -2
- data/lib/scout_apm/version.rb +1 -1
- data/test/unit/config_test.rb +11 -0
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: a17bfe8d072cc469eafdaf6f5d9a53e29282ea6a
|
4
|
+
data.tar.gz: 39707f4cfacb744879297744928c038fe1a1c8aa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e9d208abf69daf67b5ca3bf487117e58cd434b445cd43126d9ec6ba90242b2179b1f4913aff3e3d8a38d89c6e0c2940d559059509baab072b7d0aac1899a936f
|
7
|
+
data.tar.gz: 91e4143528147d48c5eec703002cfd783579e89fca9c48806e0ec9745a57b622f660f9a7acd5186e6fc0ac5aef0c61f3e69bcc8a1bd5e29fd6ed94c5270e90d2
|
data/CHANGELOG.markdown
CHANGED
@@ -24,7 +24,7 @@ module ScoutApm
|
|
24
24
|
report_to_server
|
25
25
|
end
|
26
26
|
|
27
|
-
# In a running app, one process will get
|
27
|
+
# In a running app, one process will get the period ready for delivery, the others will see 0.
|
28
28
|
def report_to_server
|
29
29
|
period_to_report = ScoutApm::StoreReportingPeriodTimestamp.minutes_ago(2)
|
30
30
|
|
@@ -101,7 +101,7 @@ module ScoutApm
|
|
101
101
|
histogram_clause = "#{histograms.length} Histograms"
|
102
102
|
|
103
103
|
logger.info "#{time_clause} Delivering #{metrics_clause} and #{slow_trans_clause} and #{job_clause}, #{process_log_str}."
|
104
|
-
# logger.debug("
|
104
|
+
# logger.debug("\n\nMetrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{metadata.inspect.pretty_inspect}\n\n")
|
105
105
|
end
|
106
106
|
|
107
107
|
# TODO: Move this into PayloadSerializer?
|
data/lib/scout_apm/agent.rb
CHANGED
@@ -113,6 +113,7 @@ module ScoutApm
|
|
113
113
|
def start(options = {})
|
114
114
|
@options.merge!(options)
|
115
115
|
|
116
|
+
|
116
117
|
@config = ScoutApm::Config.with_file(@config.value("config_file"))
|
117
118
|
layaway.config = config
|
118
119
|
|
@@ -123,6 +124,12 @@ module ScoutApm
|
|
123
124
|
|
124
125
|
load_instruments if should_load_instruments?(options)
|
125
126
|
|
127
|
+
if !@config.any_keys_found?
|
128
|
+
logger.info("No configuration file loaded, and no configuration found in ENV. " +
|
129
|
+
"For assistance configuring Scout, visit " +
|
130
|
+
"http://help.apm.scoutapp.com/#configuration-options")
|
131
|
+
end
|
132
|
+
|
126
133
|
return false unless preconditions_met?(options)
|
127
134
|
@started = true
|
128
135
|
logger.info "Starting monitoring for [#{environment.application_name}]. Framework [#{environment.framework}] App Server [#{environment.app_server}] Background Job Framework [#{environment.background_job_name}]."
|
data/lib/scout_apm/config.rb
CHANGED
@@ -5,25 +5,55 @@ require 'scout_apm/environment'
|
|
5
5
|
|
6
6
|
# Valid Config Options:
|
7
7
|
#
|
8
|
+
# This list is complete, but some are old and unused, or for developers of
|
9
|
+
# scout_apm itself. See the documentation at http://help.apm.scoutapp.com for
|
10
|
+
# customer-focused documentation.
|
11
|
+
#
|
8
12
|
# application_root - override the detected directory of the application
|
13
|
+
# compress_payload - true/false to enable gzipping of payload
|
9
14
|
# data_file - override the default temporary storage location. Must be a location in a writable directory
|
10
|
-
#
|
15
|
+
# dev_trace - true or false. Enables always-on tracing in development environmen only
|
11
16
|
# direct_host - override the default "direct" host. The direct_host bypasses the ingestion pipeline and goes directly to the webserver, and is primarily used for features under development.
|
17
|
+
# enable_background_jobs - true or false
|
18
|
+
# host - configuration used in development
|
19
|
+
# hostname - override the default hostname detection. Default varies by environment - either system hostname, or PAAS hostname
|
12
20
|
# key - the account key with Scout APM. Found in Settings in the Web UI
|
13
21
|
# log_file_path - either a directory or "STDOUT".
|
14
22
|
# log_level - DEBUG / INFO / WARN as usual
|
15
23
|
# monitor - true or false. False prevents any instrumentation from starting
|
16
24
|
# name - override the name reported to APM. This is the name that shows in the Web UI
|
17
|
-
#
|
25
|
+
# profile - turn on/off scoutprof (only applicable in Gem versions including scoutprof)
|
26
|
+
# proxy - an http proxy
|
18
27
|
# report_format - 'json' or 'marshal'. Marshal is legacy and will be removed.
|
19
|
-
#
|
20
|
-
# enable_background_jobs - true or false
|
28
|
+
# uri_reporting - 'path' or 'full_path' default is 'full_path', which reports URL params as well as the path.
|
21
29
|
#
|
22
30
|
# Any of these config settings can be set with an environment variable prefixed
|
23
31
|
# by SCOUT_ and uppercasing the key: SCOUT_LOG_LEVEL for instance.
|
24
32
|
|
25
33
|
module ScoutApm
|
26
34
|
class Config
|
35
|
+
KNOWN_CONFIG_OPTIONS = [
|
36
|
+
'application_root',
|
37
|
+
'compress_payload',
|
38
|
+
'config_file',
|
39
|
+
'data_file',
|
40
|
+
'dev_trace',
|
41
|
+
'direct_host',
|
42
|
+
'disabled_instruments',
|
43
|
+
'enable_background_jobs',
|
44
|
+
'host',
|
45
|
+
'hostname',
|
46
|
+
'ignore',
|
47
|
+
'key',
|
48
|
+
'log_level',
|
49
|
+
'log_file_path',
|
50
|
+
'monitor',
|
51
|
+
'name',
|
52
|
+
'profile',
|
53
|
+
'proxy',
|
54
|
+
'report_format',
|
55
|
+
'uri_reporting',
|
56
|
+
]
|
27
57
|
|
28
58
|
################################################################################
|
29
59
|
# Coersions
|
@@ -136,6 +166,10 @@ module ScoutApm
|
|
136
166
|
end
|
137
167
|
|
138
168
|
def value(key)
|
169
|
+
if ! KNOWN_CONFIG_OPTIONS.include?(key)
|
170
|
+
ScoutApm::Agent.instance.logger.debug("Requested looking up a unknown configuration key: #{key} (not a problem. Evaluate and add to config.rb)")
|
171
|
+
end
|
172
|
+
|
139
173
|
o = @overlays.detect{ |overlay| overlay.has_key?(key) }
|
140
174
|
raw_value = if o
|
141
175
|
o.value(key)
|
@@ -148,19 +182,24 @@ module ScoutApm
|
|
148
182
|
coercion.coerce(raw_value)
|
149
183
|
end
|
150
184
|
|
185
|
+
# Did we load anything for configuration?
|
186
|
+
def any_keys_found?
|
187
|
+
@overlays.any? { |overlay| overlay.any_keys_found? }
|
188
|
+
end
|
189
|
+
|
151
190
|
class ConfigDefaults
|
152
191
|
DEFAULTS = {
|
153
|
-
'
|
192
|
+
'compress_payload' => true,
|
193
|
+
'dev_trace' => false,
|
154
194
|
'direct_host' => 'https://apm.scoutapp.com',
|
155
|
-
'log_level' => 'info',
|
156
|
-
'uri_reporting' => 'full_path',
|
157
|
-
'report_format' => 'json',
|
158
195
|
'disabled_instruments' => [],
|
159
196
|
'enable_background_jobs' => true,
|
197
|
+
'host' => 'https://checkin.scoutapp.com',
|
160
198
|
'ignore' => [],
|
161
|
-
'
|
199
|
+
'log_level' => 'info',
|
162
200
|
'profile' => true, # for scoutprof
|
163
|
-
'
|
201
|
+
'report_format' => 'json',
|
202
|
+
'uri_reporting' => 'full_path',
|
164
203
|
}.freeze
|
165
204
|
|
166
205
|
def value(key)
|
@@ -170,6 +209,11 @@ module ScoutApm
|
|
170
209
|
def has_key?(key)
|
171
210
|
DEFAULTS.has_key?(key)
|
172
211
|
end
|
212
|
+
|
213
|
+
# Defaults are here, but not counted as user specified.
|
214
|
+
def any_keys_found?
|
215
|
+
false
|
216
|
+
end
|
173
217
|
end
|
174
218
|
|
175
219
|
|
@@ -184,6 +228,10 @@ module ScoutApm
|
|
184
228
|
def has_key?(*)
|
185
229
|
true
|
186
230
|
end
|
231
|
+
|
232
|
+
def any_keys_found?
|
233
|
+
false
|
234
|
+
end
|
187
235
|
end
|
188
236
|
|
189
237
|
class ConfigEnvironment
|
@@ -199,6 +247,12 @@ module ScoutApm
|
|
199
247
|
def key_to_env_key(key)
|
200
248
|
'SCOUT_' + key.upcase
|
201
249
|
end
|
250
|
+
|
251
|
+
def any_keys_found?
|
252
|
+
KNOWN_CONFIG_OPTIONS.any? { |option|
|
253
|
+
ENV.has_key?(key_to_env_key(option))
|
254
|
+
}
|
255
|
+
end
|
202
256
|
end
|
203
257
|
|
204
258
|
# Attempts to load a configuration file, and parse it as YAML. If the file
|
@@ -224,6 +278,12 @@ module ScoutApm
|
|
224
278
|
@settings.has_key?(key)
|
225
279
|
end
|
226
280
|
|
281
|
+
def any_keys_found?
|
282
|
+
KNOWN_CONFIG_OPTIONS.any? { |option|
|
283
|
+
@settings.has_key?(option)
|
284
|
+
}
|
285
|
+
end
|
286
|
+
|
227
287
|
private
|
228
288
|
|
229
289
|
def load_file(file)
|
@@ -255,7 +315,7 @@ module ScoutApm
|
|
255
315
|
@file_loaded = false
|
256
316
|
end
|
257
317
|
rescue Exception => e # Explicit `Exception` handling to catch SyntaxError and anything else that ERB or YAML may throw
|
258
|
-
logger.
|
318
|
+
logger.info("Failed loading configuration file (#{@resolved_file_path}): #{e.message}. ScoutAPM will continue starting with configuration from ENV and defaults")
|
259
319
|
@file_loaded = false
|
260
320
|
end
|
261
321
|
end
|
data/lib/scout_apm/layaway.rb
CHANGED
@@ -7,9 +7,6 @@
|
|
7
7
|
#
|
8
8
|
module ScoutApm
|
9
9
|
class Layaway
|
10
|
-
# How old a file needs to be in Seconds before it gets reported.
|
11
|
-
REPORTING_AGE = 120
|
12
|
-
|
13
10
|
# How long to let a stale file sit before deleting it.
|
14
11
|
# Letting it sit a bit may be useful for debugging
|
15
12
|
STALE_AGE = 10 * 60
|
@@ -60,7 +57,6 @@ module ScoutApm
|
|
60
57
|
def with_claim(timestamp)
|
61
58
|
coordinator_file = glob_pattern(timestamp, :coordinator)
|
62
59
|
|
63
|
-
|
64
60
|
begin
|
65
61
|
# This file gets deleted only by a process that successfully created and obtained the exclusive lock
|
66
62
|
f = File.open(coordinator_file, File::RDWR | File::CREAT | File::EXCL | File::NONBLOCK)
|
@@ -70,25 +66,35 @@ module ScoutApm
|
|
70
66
|
|
71
67
|
begin
|
72
68
|
if f
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
69
|
+
begin
|
70
|
+
ScoutApm::Agent.instance.logger.debug("Obtained Reporting Lock")
|
71
|
+
|
72
|
+
log_layaway_file_information
|
73
|
+
|
74
|
+
files = all_files_for(timestamp).reject{|l| l.to_s == coordinator_file.to_s }
|
75
|
+
rps = files.map{ |layaway| LayawayFile.new(layaway).load }.compact
|
76
|
+
if rps.any?
|
77
|
+
yield rps
|
78
|
+
|
79
|
+
ScoutApm::Agent.instance.logger.debug("Deleting the now-reported layaway files for #{timestamp.to_s}")
|
80
|
+
delete_files_for(timestamp) # also removes the coodinator_file
|
81
|
+
|
82
|
+
ScoutApm::Agent.instance.logger.debug("Checking for any Stale layaway files")
|
83
|
+
delete_stale_files(timestamp.to_time - STALE_AGE)
|
84
|
+
else
|
85
|
+
File.unlink(coordinator_file)
|
86
|
+
ScoutApm::Agent.instance.logger.debug("No layaway files to report")
|
87
|
+
end
|
88
|
+
|
89
|
+
true
|
90
|
+
rescue Exception => e
|
91
|
+
ScoutApm::Agent.instance.logger.debug("Caught an exception in with_claim, with the coordination file locked: #{e.message}, #{e.backtrace.inspect}")
|
92
|
+
raise
|
93
|
+
ensure
|
94
|
+
# Unlock the file when done!
|
95
|
+
f.flock(File::LOCK_UN | File::LOCK_NB)
|
96
|
+
f.close
|
86
97
|
end
|
87
|
-
|
88
|
-
# Unlock the file when done!
|
89
|
-
f.flock(File::LOCK_UN | File::LOCK_NB)
|
90
|
-
f.close
|
91
|
-
true
|
92
98
|
else
|
93
99
|
# Didn't obtain lock, another process is reporting. Return false from this function, but otherwise no work
|
94
100
|
false
|
@@ -97,7 +103,10 @@ module ScoutApm
|
|
97
103
|
end
|
98
104
|
|
99
105
|
def delete_files_for(timestamp)
|
100
|
-
all_files_for(timestamp).each { |layaway|
|
106
|
+
all_files_for(timestamp).each { |layaway|
|
107
|
+
ScoutApm::Agent.instance.logger.debug("Deleting layaway file: #{layaway}")
|
108
|
+
File.unlink(layaway)
|
109
|
+
}
|
101
110
|
end
|
102
111
|
|
103
112
|
def delete_stale_files(older_than)
|
@@ -108,6 +117,8 @@ module ScoutApm
|
|
108
117
|
select { |timestamp| timestamp.to_i < older_than.strftime(TIME_FORMAT).to_i }.
|
109
118
|
tap { |timestamps| ScoutApm::Agent.instance.logger.debug("Deleting stale layaway files with timestamps: #{timestamps.inspect}") }.
|
110
119
|
map { |timestamp| delete_files_for(timestamp) }
|
120
|
+
rescue => e
|
121
|
+
ScoutApm::Agent.instance.logger.debug("Problem deleting stale files: #{e.message}, #{e.backtrace.inspect}")
|
111
122
|
end
|
112
123
|
|
113
124
|
private
|
@@ -158,6 +169,20 @@ module ScoutApm
|
|
158
169
|
nil
|
159
170
|
end
|
160
171
|
end
|
172
|
+
|
173
|
+
def log_layaway_file_information
|
174
|
+
files_in_temp = Dir["#{directory}/*"].count
|
175
|
+
|
176
|
+
all_filenames = all_files_for(:all)
|
177
|
+
count_per_timestamp = Hash[
|
178
|
+
all_filenames.
|
179
|
+
group_by {|f| timestamp_from_filename(f) }.
|
180
|
+
map{ |timestamp, list| [timestamp, list.length] }
|
181
|
+
]
|
182
|
+
|
183
|
+
|
184
|
+
ScoutApm::Agent.instance.logger.debug("Total in #{directory}: #{files_in_temp}. Total Layaway Files: #{all_filenames.size}. By Timestamp: #{count_per_timestamp.inspect}")
|
185
|
+
end
|
161
186
|
end
|
162
187
|
end
|
163
188
|
|
@@ -88,8 +88,6 @@ module ScoutApm
|
|
88
88
|
if bt.any?
|
89
89
|
meta.backtrace = bt
|
90
90
|
@backtraces << meta
|
91
|
-
else
|
92
|
-
ScoutApm::Agent.instance.logger.debug { "Unable to capture an app-specific backtrace for #{meta.inspect}\n#{layer.backtrace}" }
|
93
91
|
end
|
94
92
|
end
|
95
93
|
|
@@ -157,9 +155,11 @@ module ScoutApm
|
|
157
155
|
end
|
158
156
|
end
|
159
157
|
|
160
|
-
def make_meta_options_desc_hash(layer)
|
158
|
+
def make_meta_options_desc_hash(layer, max_desc_length=1000)
|
161
159
|
if layer.desc
|
162
|
-
|
160
|
+
desc_s = layer.desc.to_s
|
161
|
+
trimmed_desc = desc_s[0 .. max_desc_length]
|
162
|
+
{:desc => trimmed_desc}
|
163
163
|
else
|
164
164
|
{}
|
165
165
|
end
|
data/lib/scout_apm/reporter.rb
CHANGED
@@ -27,7 +27,6 @@ module ScoutApm
|
|
27
27
|
headers.merge!(compression_headers)
|
28
28
|
|
29
29
|
compress_payload_size = payload.length
|
30
|
-
ScoutApm::Agent.instance.logger.debug("Compressed Payload: #{payload.inspect}")
|
31
30
|
ScoutApm::Agent.instance.logger.debug("Original Size: #{original_payload_size} Compressed Size: #{compress_payload_size}")
|
32
31
|
end
|
33
32
|
|
@@ -24,10 +24,13 @@ module ScoutApm
|
|
24
24
|
end
|
25
25
|
|
26
26
|
def install
|
27
|
-
::Puma.cli_config.options[:before_worker_boot]
|
27
|
+
old = ::Puma.cli_config.options[:before_worker_boot] || []
|
28
|
+
new = Array(old) + [Proc.new do
|
28
29
|
logger.info "Installing Puma worker loop."
|
29
30
|
ScoutApm::Agent.instance.start_background_worker
|
30
|
-
end
|
31
|
+
end]
|
32
|
+
|
33
|
+
::Puma.cli_config.options[:before_worker_boot] = new
|
31
34
|
rescue
|
32
35
|
logger.warn "Unable to install Puma worker loop: #{$!.message}"
|
33
36
|
end
|
data/lib/scout_apm/store.rb
CHANGED
@@ -83,7 +83,7 @@ module ScoutApm
|
|
83
83
|
def write_to_layaway(layaway, force=false)
|
84
84
|
ScoutApm::Agent.instance.logger.debug("Writing to layaway#{" (Forced)" if force}")
|
85
85
|
|
86
|
-
reporting_periods.select { |time, rp| force || time.timestamp < current_timestamp.timestamp }.
|
86
|
+
reporting_periods.select { |time, rp| force || (time.timestamp < current_timestamp.timestamp) }.
|
87
87
|
each { |time, rp| collect_samplers(rp) }.
|
88
88
|
each { |time, rp| write_reporting_period(layaway, time, rp) }
|
89
89
|
end
|
@@ -95,7 +95,9 @@ module ScoutApm
|
|
95
95
|
rescue => e
|
96
96
|
ScoutApm::Agent.instance.logger.warn("Failed writing data to layaway file: #{e.message} / #{e.backtrace}")
|
97
97
|
ensure
|
98
|
-
reporting_periods.
|
98
|
+
ScoutApm::Agent.instance.logger.debug("Before delete, reporting periods length: #{reporting_periods.size}")
|
99
|
+
deleted_items = reporting_periods.delete(time)
|
100
|
+
ScoutApm::Agent.instance.logger.debug("After delete, reporting periods length: #{reporting_periods.size}. Did delete #{deleted_items}")
|
99
101
|
end
|
100
102
|
|
101
103
|
######################################
|
data/lib/scout_apm/version.rb
CHANGED
data/test/unit/config_test.rb
CHANGED
@@ -67,4 +67,15 @@ class ConfigTest < Minitest::Test
|
|
67
67
|
assert_equal 10, coercion.coerce(10)
|
68
68
|
assert_equal ["a"], coercion.coerce(["a"])
|
69
69
|
end
|
70
|
+
|
71
|
+
def test_any_keys_found
|
72
|
+
ENV.stubs(:has_key?).returns(nil)
|
73
|
+
|
74
|
+
conf = ScoutApm::Config.with_file("a_file_that_doesnt_exist.yml")
|
75
|
+
assert ! conf.any_keys_found?
|
76
|
+
|
77
|
+
ENV.stubs(:has_key?).with("SCOUT_MONITOR").returns("true")
|
78
|
+
conf = ScoutApm::Config.with_file("a_file_that_doesnt_exist.yml")
|
79
|
+
assert conf.any_keys_found?
|
80
|
+
end
|
70
81
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: scout_apm
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 3.0.0.
|
4
|
+
version: 3.0.0.pre6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Derek Haynes
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-12-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -293,7 +293,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
293
293
|
version: 1.3.1
|
294
294
|
requirements: []
|
295
295
|
rubyforge_project: scout_apm
|
296
|
-
rubygems_version: 2.
|
296
|
+
rubygems_version: 2.5.1
|
297
297
|
signing_key:
|
298
298
|
specification_version: 4
|
299
299
|
summary: Ruby application performance monitoring
|