scout_apm 2.1.16 → 2.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 29e9f474f0b675658b415e0d23a1f498217b1edd
4
- data.tar.gz: 870419ac7831ba6bed3fe631b86cab7858125f70
3
+ metadata.gz: 66a4cffa0669e1689fd354ca6cc1334917268580
4
+ data.tar.gz: 07b7b35f971caaecce344a6a637a945df0c8523a
5
5
  SHA512:
6
- metadata.gz: dd9b7433c16697e9a5757f7f5839a48ea5ddd5dfe7f8ea69e7eca137020f90a7670d2ee7bd0395e2b66787f9328884d3087cc09628c17cb2c52bb9813b165f4a
7
- data.tar.gz: 3e77160ad682754733aefe1a6d8be67b3a70274f3685c006fdad8c37834d3a45263724255cdab3407b4c50e7ebe7da5748085895dbd1762969dc6f798ebfd06e
6
+ metadata.gz: 4c3f3e587c1b98fd7c679b9a40fa79970c38085dda00c7524021c1caa5d51e174ada700ee2f8401292b3497b52af99e600e8cefc2e6d88e26128791e4c06dc9f
7
+ data.tar.gz: 1d36607a77b765fe849e7a554db6811d3e6db22e6460862141d1ffd83d6faa20bb44fff08c52894ce2ae71fbe5ff9cbd803dc5b69138fdee62f836e6b0a0a09a
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,7 @@
1
+ # 2.1.17
2
+
3
+ * Additional logging around file system usage
4
+
1
5
  # 2.1.16
2
6
 
3
7
  * Extract the name correctly for DelayedJob workers run via ActiveJob
@@ -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 one period ready for delivery, the others will see 0.
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
 
@@ -72,7 +72,7 @@ module ScoutApm
72
72
  log_deliver(metrics, slow_transactions, metadata, slow_jobs, histograms)
73
73
 
74
74
  payload = ScoutApm::Serializers::PayloadSerializer.serialize(metadata, metrics, slow_transactions, jobs, slow_jobs, histograms)
75
- logger.debug("Payload: #{payload}")
75
+ # logger.debug("Payload: #{payload}")
76
76
 
77
77
  reporter.report(payload, headers)
78
78
  rescue => e
@@ -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("Metrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{metadata.inspect.pretty_inspect}")
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?
@@ -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}]."
@@ -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
- # host - override the default hostname detection. Default varies by environment - either system hostname, or PAAS hostname
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
- # uri_reporting - 'path' or 'full_path' default is 'full_path', which reports URL params as well as the path.
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
- # dev_trace - true or false. Enables always-on tracing in development environmen only
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
- 'host' => 'https://checkin.scoutapp.com',
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
- 'dev_trace' => false,
199
+ 'log_level' => 'info',
162
200
  'profile' => true, # for scoutprof
163
- 'compress_payload' => true,
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.debug("Failed loading configuration file: #{e.message}. ScoutAPM will continue starting with configuration from ENV and defaults")
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
@@ -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
- ScoutApm::Agent.instance.logger.debug("Obtained Reporting Lock")
75
-
76
- files = all_files_for(timestamp).reject{|l| l.to_s == coordinator_file.to_s }
77
- rps = files.map{ |layaway| LayawayFile.new(layaway).load }.compact
78
- if rps.any?
79
- yield rps
80
-
81
- delete_files_for(timestamp) # also removes the coodinator_file
82
- delete_stale_files(timestamp.to_time - STALE_AGE)
83
- else
84
- File.unlink(coordinator_file)
85
- ScoutApm::Agent.instance.logger.debug("No layaway files to report")
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| File.unlink(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
- {:desc => layer.desc.to_s}
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
@@ -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] << Proc.new do
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
@@ -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.delete(time)
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
  ######################################
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "2.1.16"
2
+ VERSION = "2.1.17"
3
3
  end
4
4
 
@@ -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: 2.1.16
4
+ version: 2.1.17
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-11-29 00:00:00.000000000 Z
12
+ date: 2016-12-13 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -286,7 +286,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
286
286
  version: '0'
287
287
  requirements: []
288
288
  rubyforge_project: scout_apm
289
- rubygems_version: 2.4.8
289
+ rubygems_version: 2.5.1
290
290
  signing_key:
291
291
  specification_version: 4
292
292
  summary: Ruby application performance monitoring