scout_apm 1.2.3 → 1.2.4.pre

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: 02dd0f4a1c88164e5406dbdb596137fc8c86f82a
4
- data.tar.gz: f2eef64f0f21280c47dacb09ba81feecb321db1d
3
+ metadata.gz: fa64d725755deae00527598cd770bf40a773fcf8
4
+ data.tar.gz: 17b868c65b2b6bd7749fb14dd7164a773248a26b
5
5
  SHA512:
6
- metadata.gz: fc319d3d9733ccf56548f09ddbce8e180849a6f8b2efd2e47524b0f4f68f23f6ec7d93f607409c9285d9294dffe91e025b21c2339d862a58d40589612d1f7fc0
7
- data.tar.gz: e5739f804d6fa5abd2a29a4786dbb21f890fe63322a66999001b0a275cbe8aaed631d53295eabbd2d575ff1eb52aebbe1479372ae2d15343a4960977ef3f02b4
6
+ metadata.gz: 0ba12e4e11843ef25e3005d51c6e7e9f0d38a3db2a15f3c2e5bce014bc7ceaadf68e33f1b5443535cb938936232800755e5b20f3e21e3183d26598062fc9f018
7
+ data.tar.gz: eaf8da676edae1147d935594e7ffdfa070bfcbd7fcf3c7bce18c835262a9e98121ae21e5fd916bd391325f4d85f8fcc4975b6f18949b7dac54e246b8d24a9f8d
data/.gitignore CHANGED
@@ -4,4 +4,5 @@
4
4
  Gemfile.lock
5
5
  pkg/*
6
6
  .rvmrc
7
- .idea
7
+ .idea
8
+ test/tmp/*
@@ -1,3 +1,8 @@
1
+ # 1.2.4
2
+
3
+ * Removing layaway file validation in main thread
4
+ * Fixing :force so agent will start in tests
5
+
1
6
  # 1.2.3
2
7
 
3
8
  * Trimming metrics from slow requests if there are more than 10.
@@ -47,23 +47,28 @@ module ScoutApm
47
47
  end
48
48
 
49
49
  def apm_enabled?
50
- config.value('monitor') and !@options[:force]
50
+ config.value('monitor')
51
+ end
52
+
53
+ # If true, the agent will start regardless of safety checks. Currently just used for testing.
54
+ def force?
55
+ @options[:force]
51
56
  end
52
57
 
53
58
  def preconditions_met?(options={})
54
59
  if !apm_enabled?
55
- logger.warn "Monitoring isn't enabled for the [#{environment.env}] environment."
56
- return false
60
+ logger.warn "Monitoring isn't enabled for the [#{environment.env}] environment. #{force? ? 'Forcing agent to start' : 'Not starting agent'}"
61
+ return false unless force?
57
62
  end
58
63
 
59
64
  if !environment.application_name
60
- logger.warn "An application name could not be determined. Specify the :name value in scout_apm.yml. Not starting agent."
61
- return false
65
+ logger.warn "An application name could not be determined. Specify the :name value in scout_apm.yml. #{force? ? 'Forcing agent to start' : 'Not starting agent'}."
66
+ return false unless force?
62
67
  end
63
68
 
64
69
  if app_server_missing?(options) && background_job_missing?
65
- logger.warn "Couldn't find a supported app server or background job framework. Not starting agent."
66
- return false
70
+ logger.warn "Couldn't find a supported app server or background job framework. #{force? ? 'Forcing agent to start' : 'Not starting agent'}."
71
+ return false unless force?
67
72
  end
68
73
 
69
74
  if started?
@@ -90,18 +95,10 @@ module ScoutApm
90
95
  logger.info "Starting monitoring for [#{environment.deploy_integration.name}]]."
91
96
  return environment.deploy_integration.install
92
97
  end
93
-
94
98
  return false unless preconditions_met?(options)
95
-
96
99
  @started = true
97
-
98
100
  logger.info "Starting monitoring for [#{environment.application_name}]. Framework [#{environment.framework}] App Server [#{environment.app_server}] Background Job Framework [#{environment.background_job_name}]."
99
101
 
100
- # We need agent initialized to do this, so do it here instead.
101
- # Clean up any old data in the layaway file, allows us to change the file
102
- # structure / contents without worrying.
103
- layaway.verify_layaway_file_contents
104
-
105
102
  load_instruments if should_load_instruments?(options)
106
103
 
107
104
  @samplers = [
@@ -160,8 +157,10 @@ module ScoutApm
160
157
  # in-memory metrics would be lost and a gap would appear on restarts.
161
158
  def shutdown
162
159
  return if !started?
163
- @background_worker.stop
164
- @background_worker.run_once
160
+ if @background_worker
161
+ @background_worker.stop
162
+ @background_worker.run_once
163
+ end
165
164
  end
166
165
 
167
166
  def started?
@@ -175,6 +174,7 @@ module ScoutApm
175
174
  def start_background_worker?
176
175
  return true if environment.app_server == :thin
177
176
  return true if environment.app_server == :webrick
177
+ return true if force?
178
178
  return !environment.forking?
179
179
  end
180
180
 
@@ -264,12 +264,12 @@ module ScoutApm
264
264
  end
265
265
  end
266
266
 
267
- def app_server_missing?(options)
267
+ def app_server_missing?(options = {})
268
268
  !environment.app_server_integration(true).found? && !options[:skip_app_server_check]
269
269
  end
270
270
 
271
- def background_job_missing?
272
- environment.background_job_integration.nil?
271
+ def background_job_missing?(options = {})
272
+ environment.background_job_integration.nil? && !options[:skip_background_job_check]
273
273
  end
274
274
  end
275
275
  end
@@ -15,10 +15,10 @@ module ScoutApm
15
15
  #
16
16
  # At any given point, there is data in each of those steps, moving its way through the process
17
17
  def process_metrics
18
- # First we write the previous minute's data to the shared-across-process layaway file.
18
+ # Write the previous minute's data to the shared-across-process layaway file.
19
19
  store.write_to_layaway(layaway)
20
20
 
21
- # Then attempt to send 2 minutes ago's data up to the server. This
21
+ # Attempt to send 2 minutes ago's data up to the server. This
22
22
  # only acctually occurs if this process is the first to wake up this
23
23
  # minute.
24
24
  report_to_server
@@ -65,7 +65,7 @@ module ScoutApm
65
65
  select { |meta,stats| meta.metric_name =~ /\AController/ }.
66
66
  inject(0) {|sum, (_, stat)| sum + stat.call_count }
67
67
 
68
- logger.info "Delivering #{metrics.length} Metrics for #{total_request_count} requests and #{slow_transactions.length} Slow Transaction Traces"
68
+ logger.info "[#{Time.parse(metadata[:agent_time]).strftime("%H:%M")}] Delivering #{metrics.length} Metrics for #{total_request_count} requests and #{slow_transactions.length} Slow Transaction Traces"
69
69
  logger.debug("Metrics: #{metrics.pretty_inspect}\nSlowTrans: #{slow_transactions.pretty_inspect}\nMetadata: #{metadata.inspect.pretty_inspect}")
70
70
  end
71
71
 
@@ -8,21 +8,6 @@ module ScoutApm
8
8
  @file = ScoutApm::LayawayFile.new
9
9
  end
10
10
 
11
- # We're changing the format, so detect if we're loading an old formatted
12
- # file, and just drop it if so. There's no important data there, since it's
13
- # used mostly for just syncronizing between processes
14
- def verify_layaway_file_contents
15
- file.read_and_write do |existing_data|
16
- existing_data ||= {}
17
- if existing_data.keys.all?{|k| k.is_a? StoreReportingPeriodTimestamp } &&
18
- existing_data.values.all? {|v| v.is_a? StoreReportingPeriod }
19
- existing_data
20
- else
21
- {}
22
- end
23
- end
24
- end
25
-
26
11
  def add_reporting_period(time, reporting_period)
27
12
  file.read_and_write do |existing_data|
28
13
  existing_data ||= Hash.new
@@ -37,16 +22,15 @@ module ScoutApm
37
22
  # Returns an array of ReportingPeriod objects that are ready to be pushed to the server
38
23
  def periods_ready_for_delivery
39
24
  ready_for_delivery = []
40
-
41
25
  file.read_and_write do |existing_data|
42
26
  existing_data ||= {}
43
- ready_for_delivery = existing_data.select {|time, rp| should_send?(rp) } # Select off the values we want
27
+ ready_for_delivery = existing_data.to_a.select {|time, rp| should_send?(rp) } # Select off the values we want. to_a is needed for compatibility with Ruby 1.8.7.
44
28
 
45
29
  # Rewrite anything not plucked out back to the file
46
- existing_data.reject {|k, v| ready_for_delivery.keys.include?(k) }
30
+ existing_data.reject {|k, v| ready_for_delivery.map(&:first).include?(k) }
47
31
  end
48
32
 
49
- return ready_for_delivery.values
33
+ return ready_for_delivery.map(&:last)
50
34
  end
51
35
 
52
36
  # We just want to send anything older than X
@@ -63,7 +63,11 @@ module ScoutApm
63
63
  end
64
64
 
65
65
  def eql?(o)
66
- timestamp.eql?(o.timestamp)
66
+ self.class == o.class && timestamp.eql?(o.timestamp)
67
+ end
68
+
69
+ def ==(o)
70
+ self.eql?(o)
67
71
  end
68
72
 
69
73
  def hash
@@ -1,4 +1,4 @@
1
1
  module ScoutApm
2
- VERSION = "1.2.3"
2
+ VERSION = "1.2.4.pre"
3
3
  end
4
4
 
@@ -19,6 +19,12 @@ end
19
19
  class Minitest::Test
20
20
  def setup
21
21
  reopen_logger
22
+ ENV['SCOUT_DATA_FILE'] = DATA_FILE_PATH
23
+ end
24
+
25
+ def teardown
26
+ ScoutApm::Agent.instance.shutdown
27
+ File.delete(DATA_FILE_PATH) if File.exist?(DATA_FILE_PATH)
22
28
  end
23
29
 
24
30
  def set_rack_env(env)
@@ -31,4 +37,6 @@ class Minitest::Test
31
37
  @logger = Logger.new(@log_contents)
32
38
  ScoutApm::Agent.instance.instance_variable_set("@logger", @logger)
33
39
  end
40
+
41
+ DATA_FILE_PATH = File.dirname(__FILE__) + '/tmp/scout_apm.db'
34
42
  end
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+ require 'scout_apm/agent'
3
+ require 'scout_apm/slow_transaction'
4
+ require 'scout_apm/metric_meta'
5
+ require 'scout_apm/metric_stats'
6
+ require 'scout_apm/context'
7
+ require 'scout_apm/store'
8
+
9
+ class AgentTest < Minitest::Test
10
+
11
+ # Safeguard to ensure the main agent thread doesn't have any interaction with the layaway file. Contention on file locks can cause delays.
12
+ def test_start_with_lock_on_layaway_file
13
+ # setup the file, putting a lock on it.
14
+ File.open(DATA_FILE_PATH, "w") {}
15
+ f=File.open(DATA_FILE_PATH, File::RDWR | File::CREAT)
16
+ f.flock(File::LOCK_EX)
17
+
18
+ agent = ScoutApm::Agent.instance
19
+
20
+ no_timeout = true
21
+ begin
22
+ Timeout::timeout(3) { agent.start({:monitor => true,:force => true}) }
23
+ rescue Timeout::Error
24
+ no_timeout = false
25
+ ensure
26
+ f.flock(File::LOCK_UN)
27
+ f.close
28
+ end
29
+ assert no_timeout, "Agent took >= 3s to start. Possible file lock issue."
30
+ end
31
+
32
+ def test_reset_file_with_old_format
33
+ File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(OLD_FORMAT)) }
34
+ begin
35
+ ScoutApm::Agent.instance(:force => true).process_metrics
36
+ rescue NoMethodError
37
+ # The agent will raise an exception the first time metrics are processed for scout_apm < 1.2.
38
+ #
39
+ # NoMethodError: undefined method `values' for []:Array
40
+ # /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/layaway.rb:46:in `periods_ready_for_delivery'
41
+ # /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/agent/reporting.rb:31:in `report_to_server'
42
+ # /Users/dlite/projects/scout_apm_ruby/lib/scout_apm/agent/reporting.rb:24:in `process_metrics'
43
+ # /Users/dlite/projects/scout_apm_ruby/test/unit/layaway_test.rb:27:in `test_reset_file_with_old_format'
44
+ end
45
+ # Data will be fine the next go-around
46
+ no_error = true
47
+ begin
48
+ ScoutApm::Agent.instance(:force => true).process_metrics
49
+ rescue Exception => e
50
+ no_error = false
51
+ end
52
+ assert no_error, "Error trying to process metrics after upgrading from < 1.2 data format: #{e.message if e}"
53
+ end
54
+
55
+ ## TODO - adds tests to ensure other potentially long-running things don't sneak in, like HTTP calls.
56
+
57
+ OLD_FORMAT = {1452533280 => {:metrics => {}, :slow_transactions => {}} } # Pre 1.2 agents used a different file format to store data.
58
+ end
@@ -0,0 +1,32 @@
1
+ require 'test_helper'
2
+ require 'scout_apm/slow_transaction'
3
+ require 'scout_apm/metric_meta'
4
+ require 'scout_apm/metric_stats'
5
+ require 'scout_apm/context'
6
+ require 'scout_apm/store'
7
+
8
+ class LayawayTest < Minitest::Test
9
+ def test_add_reporting_period
10
+ File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(NEW_FORMAT)) }
11
+ ScoutApm::Agent.instance.start
12
+
13
+ data = ScoutApm::Layaway.new
14
+ t = ScoutApm::StoreReportingPeriodTimestamp.new
15
+ data.add_reporting_period(t,ScoutApm::StoreReportingPeriod.new(t))
16
+ assert_equal [TIMESTAMP,t], Marshal.load(File.read(DATA_FILE_PATH)).keys
17
+ end
18
+
19
+ def test_merge_reporting_period
20
+ File.open(DATA_FILE_PATH, 'w') { |file| file.write(Marshal.dump(NEW_FORMAT)) }
21
+ ScoutApm::Agent.instance.start
22
+
23
+ data = ScoutApm::Layaway.new
24
+ t = ScoutApm::StoreReportingPeriodTimestamp.new
25
+ data.add_reporting_period(TIMESTAMP,ScoutApm::StoreReportingPeriod.new(TIMESTAMP))
26
+ assert_equal [TIMESTAMP], Marshal.load(File.read(DATA_FILE_PATH)).keys
27
+ # TODO - add tests to verify metrics+slow transactions are merged
28
+ end
29
+
30
+ TIMESTAMP = ScoutApm::StoreReportingPeriodTimestamp.new(Time.parse("2015-01-01"))
31
+ NEW_FORMAT = {TIMESTAMP => ScoutApm::StoreReportingPeriod.new(TIMESTAMP)} # Format for 1.2+ agents
32
+ end
@@ -49,7 +49,7 @@ class PayloadSerializerTest < Minitest::Test
49
49
  metrics = {
50
50
  ScoutApm::MetricMeta.new('ActiveRecord/all').tap { |meta|
51
51
  meta.desc = "SELECT * from users where filter=?"
52
- meta.extra = {user: 'cooluser'}
52
+ meta.extra = {:user => 'cooluser'}
53
53
  meta.metric_id = nil
54
54
  meta.scope = "Controller/apps/checkin"
55
55
  } => ScoutApm::MetricStats.new.tap { |stats|
@@ -117,7 +117,7 @@ class PayloadSerializerTest < Minitest::Test
117
117
  slow_transaction_metrics = {
118
118
  ScoutApm::MetricMeta.new('ActiveRecord/all').tap { |meta|
119
119
  meta.desc = "SELECT * from users where filter=?"
120
- meta.extra = {user: 'cooluser'}
120
+ meta.extra = {:user => 'cooluser'}
121
121
  meta.metric_id = nil
122
122
  meta.scope = "Controller/apps/checkin"
123
123
  } => ScoutApm::MetricStats.new.tap { |stats|
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: 1.2.3
4
+ version: 1.2.4.pre
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-01-07 00:00:00.000000000 Z
12
+ date: 2016-01-12 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -144,9 +144,11 @@ files:
144
144
  - scout_apm.gemspec
145
145
  - test/data/config_test_1.yml
146
146
  - test/test_helper.rb
147
+ - test/unit/agent_test.rb
147
148
  - test/unit/config_test.rb
148
149
  - test/unit/environment_test.rb
149
150
  - test/unit/instruments/active_record_instruments_test.rb
151
+ - test/unit/layaway_test.rb
150
152
  - test/unit/serializers/payload_serializer_test.rb
151
153
  - test/unit/sql_sanitizer_test.rb
152
154
  homepage: https://github.com/scoutapp/scout_apm_ruby
@@ -164,9 +166,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
164
166
  version: '0'
165
167
  required_rubygems_version: !ruby/object:Gem::Requirement
166
168
  requirements:
167
- - - ">="
169
+ - - ">"
168
170
  - !ruby/object:Gem::Version
169
- version: '0'
171
+ version: 1.3.1
170
172
  requirements: []
171
173
  rubyforge_project: scout_apm
172
174
  rubygems_version: 2.4.8
@@ -176,8 +178,10 @@ summary: Ruby application performance monitoring
176
178
  test_files:
177
179
  - test/data/config_test_1.yml
178
180
  - test/test_helper.rb
181
+ - test/unit/agent_test.rb
179
182
  - test/unit/config_test.rb
180
183
  - test/unit/environment_test.rb
181
184
  - test/unit/instruments/active_record_instruments_test.rb
185
+ - test/unit/layaway_test.rb
182
186
  - test/unit/serializers/payload_serializer_test.rb
183
187
  - test/unit/sql_sanitizer_test.rb