scout_apm 3.0.0.pre21 → 3.0.0.pre22

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: eb5a7880c0007cdc98449e7598022481be64b83f
4
- data.tar.gz: b195f2ea2a704b97be089d38af6cb84145d96856
3
+ metadata.gz: f13b4a3f3c661a398f9a56edb12b5eb4d3c4bdd9
4
+ data.tar.gz: 0804ece9bc0b33ab297e2d6f36bdcd1059b98853
5
5
  SHA512:
6
- metadata.gz: 3d181d12bf746066430840488485e2e96370a33ebfc6db4b7e6c25d9cb07763d380867bf6aabf3595044451ba1a657a6d03b1d739b567e430da431f2de854a59
7
- data.tar.gz: f4149e4757f16f481ca9e9d4a3ababc1ec9ba3cb66718bffe2de207ae12b01f56fa81d0f14cf0d1b3348d7c8cf97d28809a6ec75ad6bdbb1a3af573a2de684bd
6
+ metadata.gz: a4a861ec81684ff469f17d806c781368411671e098e3ca97c383e55492160c56a9fb7a56a653248f4985fa7ddde4abfed7bdaeed96cebe092655c302761ae466
7
+ data.tar.gz: 6c3d47bb26bf70e6a1523f9d25ae948278f7ae2e89380a9d404f5b3a11f5e6fbdff518215b707703250802fc0c03e517816553d2ff121258a8ccb5a543c71bde
data/.travis.yml CHANGED
@@ -7,6 +7,9 @@ rvm:
7
7
  - "2.4"
8
8
  - "2.5"
9
9
  cache: bundler
10
+ before_install:
11
+ - gem update --system
12
+ - gem install bundler
10
13
  jobs:
11
14
  include:
12
15
  - script: bundle exec rake test
data/CHANGELOG.markdown CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  * ScoutProf BETA
4
4
 
5
+ # 2.4.10
6
+
7
+ * Improve ActiveRecord instrumentation across Rails 3.2+, and adding support
8
+ for the newly released Rails 5.2
9
+
5
10
  # 2.4.9
6
11
 
7
12
  * ScoutApm::Transaction#rename and #ignore API
data/README.markdown CHANGED
@@ -2,10 +2,19 @@
2
2
 
3
3
  [![Build Status](https://travis-ci.org/scoutapp/scout_apm_ruby.svg?branch=master)](https://travis-ci.org/scoutapp/scout_apm_ruby)
4
4
 
5
- A Ruby gem for detailed Rails application performance analysis. Metrics are
5
+ A Ruby gem for detailed Rails application performance monitoring 📈. Metrics and transaction traces are
6
6
  reported to [Scout](https://scoutapp.com), a hosted application monitoring
7
7
  service.
8
8
 
9
+ ## What's the special sauce? 🤔
10
+
11
+ The Scout agent is engineered to do some wonderful things:
12
+
13
+ * A unique focus on identifying those hard-to-investigate outliers like memory bloat, N+1s, and user-specific problems. [See an example workflow](http://scoutapp.com/newrelic-alternative).
14
+ * [Low-overhead](http://blog.scoutapp.com/articles/2016/02/07/overhead-benchmarks-new-relic-vs-scout)
15
+ * View your performance metrics during development with [DevTrace](http://help.apm.scoutapp.com/#devtrace) and in production via [server_timing](https://github.com/scoutapp/ruby_server_timing).
16
+ * Production-Safe profiling of custom code via [ScoutProf](http://help.apm.scoutapp.com/#scoutprof) (BETA).
17
+
9
18
  ## Getting Started
10
19
 
11
20
  Add the gem to your Gemfile
@@ -112,10 +112,22 @@ module ScoutApm
112
112
  end
113
113
  end
114
114
 
115
- if Utils::KlassHelper.defined?("ActiveRecord::FinderMethods")
116
- ::ActiveRecord::FinderMethods.module_eval do
117
- include ::ScoutApm::Tracer
118
- include ::ScoutApm::Instruments::ActiveRecordFinderMethodsInstruments
115
+ rails_3_2_or_above = defined?(::ActiveRecord::VERSION::MAJOR) &&
116
+ defined?(::ActiveRecord::VERSION::MINOR) &&
117
+ (::ActiveRecord::VERSION::MAJOR.to_i > 3 ||
118
+ (::ActiveRecord::VERSION::MAJOR.to_i == 3 && ::ActiveRecord::VERSION::MINOR.to_i >= 2))
119
+ if rails_3_2_or_above
120
+ if Utils::KlassHelper.defined?("ActiveRecord::Relation")
121
+ ::ActiveRecord::Relation.module_eval do
122
+ include ::ScoutApm::Instruments::ActiveRecordRelationQueryInstruments
123
+ end
124
+ end
125
+ else
126
+ if Utils::KlassHelper.defined?("ActiveRecord::FinderMethods")
127
+ ::ActiveRecord::FinderMethods.module_eval do
128
+ include ::ScoutApm::Tracer
129
+ include ::ScoutApm::Instruments::ActiveRecordFinderMethodsInstruments
130
+ end
119
131
  end
120
132
  end
121
133
 
@@ -207,12 +219,21 @@ module ScoutApm
207
219
  ################################################################################
208
220
  # Entry-point of instruments.
209
221
  #
210
- # We instrument both ActiveRecord::Querying#find_by_sql and
211
- # ActiveRecord::FinderMethods#find_with_associations. These are early in
212
- # the chain of calls when you're using ActiveRecord.
222
+ # Instrumentation starts in ActiveRecord::Relation#exec_queries (Rails >=
223
+ # 3.2.0) or ActiveRecord::FinderMethods#find_with_assocations (previous
224
+ # Rails versions).
225
+ #
226
+ # ActiveRecord::Querying#find_by_sql is instrumented in all Rails versions
227
+ # even though it is also invoked by #exec_queries/#find_by_associations
228
+ # because it can be invoked directly from user code (e.g.,
229
+ # Post.find_by_sql("SELECT * FROM posts")). The layer started by
230
+ # #exec_queries/#find_by_assocations is marked to ignore children, so it
231
+ # will not cause duplicate layers in the former case.
213
232
  #
214
- # Later on, they will call into #log, which we also instrument, at which
215
- # point, we can fill in additional data gathered at that point (name, sql)
233
+ # These methods are early in the chain of calls invoked when executing an
234
+ # ActiveRecord query, before the cache is consulted. If the query is later
235
+ # determined to be a cache miss, `#log` will be invoked, which we also
236
+ # instrument, and more details will be filled in (name, sql).
216
237
  #
217
238
  # Caveats:
218
239
  # * We don't have a name for the query yet.
@@ -276,6 +297,33 @@ module ScoutApm
276
297
  end
277
298
  end
278
299
 
300
+ module ActiveRecordRelationQueryInstruments
301
+ def self.included(instrumented_class)
302
+ ScoutApm::Agent.instance.context.logger.info "Instrumenting ActiveRecord::Relation#exec_queries - #{instrumented_class.inspect}"
303
+ instrumented_class.class_eval do
304
+ unless instrumented_class.method_defined?(:exec_queries_without_scout_instruments)
305
+ alias_method :exec_queries_without_scout_instruments, :exec_queries
306
+ alias_method :exec_queries, :exec_queries_with_scout_instruments
307
+ end
308
+ end
309
+ end
310
+
311
+ def exec_queries_with_scout_instruments(*args, &block)
312
+ req = ScoutApm::RequestManager.lookup
313
+ layer = ScoutApm::Layer.new("ActiveRecord", Utils::ActiveRecordMetricName::DEFAULT_METRIC)
314
+ layer.annotate_layer(:ignorable => true)
315
+ layer.desc = SqlList.new
316
+ req.start_layer(layer)
317
+ req.ignore_children!
318
+ begin
319
+ exec_queries_without_scout_instruments(*args, &block)
320
+ ensure
321
+ req.acknowledge_children!
322
+ req.stop_layer
323
+ end
324
+ end
325
+ end
326
+
279
327
  module ActiveRecordUpdateInstruments
280
328
  def save(*args, &block)
281
329
  model = self.class.name
@@ -188,7 +188,7 @@ module ScoutApm
188
188
  end
189
189
 
190
190
  def timestamp_from_filename(filename)
191
- match = filename.match(%r{scout_(.*)_.*\.data})
191
+ match = filename.match(%r{scout_(\d+)_\d+\.data\z})
192
192
  if match
193
193
  match[1]
194
194
  else
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "3.0.0.pre21"
2
+ VERSION = "3.0.0.pre22"
3
3
  end
@@ -46,4 +46,39 @@ class LayawayTest < Minitest::Test
46
46
 
47
47
  layaway.delete_files_for(:all)
48
48
  end
49
+
50
+ def test_layaway_stale_regex_pattern
51
+ data_dir = '/tmp/scout_apm_test/shared/scout_apm'
52
+ FileUtils.mkdir_p data_dir
53
+ # Clean out files
54
+ FileUtils.safe_unlink(Dir.glob("#{data_dir}/scout_*_*.data"))
55
+
56
+ config = make_fake_config({'data_file' => data_dir})
57
+ env = make_fake_environment(:root => '/tmp/scout_apm_test')
58
+ context = ScoutApm::AgentContext.new().tap{|c| c.config = config; c.environment = env }
59
+ layaway = ScoutApm::Layaway.new(context)
60
+
61
+
62
+ not_stale_time = Time.now
63
+ not_stale_time_formatted = not_stale_time.strftime(ScoutApm::Layaway::TIME_FORMAT)
64
+
65
+ stale_time = not_stale_time - (ScoutApm::Layaway::STALE_AGE + 120) # ScoutApm::Layaway::STALE_AGE is in seconds. Add another 2 minutes to STALE_AGE
66
+ stale_time_formatted = stale_time.strftime(ScoutApm::Layaway::TIME_FORMAT)
67
+
68
+ not_stale_file_names = [File.join(data_dir, "scout_#{not_stale_time_formatted}_1.data"),
69
+ File.join(data_dir, "scout_#{not_stale_time_formatted}_20.data")]
70
+ stale_file_names = [File.join(data_dir, "scout_#{stale_time_formatted}_1.data"),
71
+ File.join(data_dir, "scout_#{stale_time_formatted}_20.data")]
72
+ all_file_names = not_stale_file_names + stale_file_names
73
+
74
+ (all_file_names).each do |filename|
75
+ File.new(filename, 'w').close
76
+ end
77
+
78
+ assert_equal Pathname.new("/tmp/scout_apm_test/shared/scout_apm"), ScoutApm::Layaway.new(context).directory
79
+ assert_equal all_file_names.sort, Dir.glob("#{data_dir}/*data").sort
80
+
81
+ layaway.delete_stale_files(not_stale_time - ScoutApm::Layaway::STALE_AGE)
82
+ assert_equal not_stale_file_names.sort, Dir.glob("#{data_dir}/*data").sort
83
+ end
49
84
  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.pre21
4
+ version: 3.0.0.pre22
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: 2018-03-06 00:00:00.000000000 Z
12
+ date: 2018-04-11 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest