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 +4 -4
- data/.gitignore +2 -1
- data/CHANGELOG.markdown +5 -0
- data/lib/scout_apm/agent.rb +20 -20
- data/lib/scout_apm/agent/reporting.rb +3 -3
- data/lib/scout_apm/layaway.rb +3 -19
- data/lib/scout_apm/store.rb +5 -1
- data/lib/scout_apm/version.rb +1 -1
- data/test/test_helper.rb +8 -0
- data/test/unit/agent_test.rb +58 -0
- data/test/unit/layaway_test.rb +32 -0
- data/test/unit/serializers/payload_serializer_test.rb +2 -2
- metadata +8 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fa64d725755deae00527598cd770bf40a773fcf8
|
4
|
+
data.tar.gz: 17b868c65b2b6bd7749fb14dd7164a773248a26b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 0ba12e4e11843ef25e3005d51c6e7e9f0d38a3db2a15f3c2e5bce014bc7ceaadf68e33f1b5443535cb938936232800755e5b20f3e21e3183d26598062fc9f018
|
7
|
+
data.tar.gz: eaf8da676edae1147d935594e7ffdfa070bfcbd7fcf3c7bce18c835262a9e98121ae21e5fd916bd391325f4d85f8fcc4975b6f18949b7dac54e246b8d24a9f8d
|
data/.gitignore
CHANGED
data/CHANGELOG.markdown
CHANGED
data/lib/scout_apm/agent.rb
CHANGED
@@ -47,23 +47,28 @@ module ScoutApm
|
|
47
47
|
end
|
48
48
|
|
49
49
|
def apm_enabled?
|
50
|
-
config.value('monitor')
|
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
|
164
|
-
|
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
|
-
#
|
18
|
+
# Write the previous minute's data to the shared-across-process layaway file.
|
19
19
|
store.write_to_layaway(layaway)
|
20
20
|
|
21
|
-
#
|
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
|
|
data/lib/scout_apm/layaway.rb
CHANGED
@@ -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.
|
30
|
+
existing_data.reject {|k, v| ready_for_delivery.map(&:first).include?(k) }
|
47
31
|
end
|
48
32
|
|
49
|
-
return ready_for_delivery.
|
33
|
+
return ready_for_delivery.map(&:last)
|
50
34
|
end
|
51
35
|
|
52
36
|
# We just want to send anything older than X
|
data/lib/scout_apm/store.rb
CHANGED
data/lib/scout_apm/version.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -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
|
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
|
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.
|
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-
|
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:
|
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
|