scout_apm 5.0.0 → 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: f9a94a38d6b06a02e34ce7923e8084976739cc8d0fba1adfbc606f88b0bdf4d7
4
- data.tar.gz: aebe73f5379911e8691be2771b3a3fc3f5fbdd4779f2038f6a6f6e0ed38e1e20
3
+ metadata.gz: 3a569967a27143fe36a506e8757eeda10f2de6cf85567cb2af8c08993b558abb
4
+ data.tar.gz: 49a5277948f6dab053268af7f912f8905b78d2173c79cfb1c3e9a87288e33113
5
5
  SHA512:
6
- metadata.gz: d8850b1365747879effcfe383d0b438070069d2b625365dc8ea61db7c72cf6840cdf73675c95aea7a7688750dbcb41efec1b7320232312172bc49be9b207d421
7
- data.tar.gz: f3d389aa73f8b4090627843410c610edc1c5fa88740587136dbd8277d3ddfa5360e61d0d256ae23db7cf53f20b482d3f283541c077efcd2d12032e5f3f72f4e2
6
+ metadata.gz: 523767ea43b634748ff16ee974fd6bb659ddced673fbd9106e6f3a07ed8e9d78ec30b88094dac2aff4a374af719691249534aa471a7fc993813018d92bf71333
7
+ data.tar.gz: f67a78084a1280b497422f4dc35ea3ed5afb1cfbde55c79c4020b11e407674f803ea8d1dec8803bb6bf1fcc8a4e11ac728621cf2f45b8d2d35956497d55a78d7
data/CHANGELOG.markdown CHANGED
@@ -1,3 +1,19 @@
1
+ # Unreleased
2
+
3
+ # 5.1.0
4
+
5
+ * Specify correct (MIT) license in Gemspec (#430)
6
+ * Install HTTP::Client instruments (#420)
7
+ * Sanitize FROM jsonb_as_recordset AS correctly in Postgres (#332)
8
+ * Call to_h on `ActiveRecord::Base.configurations` (#434)
9
+ * Allow loading of trusted `config/scout_apm.yml` via `YAML.unsafe_load` if available (#435)
10
+ * Better exception handling when loading config (#436)
11
+ * Check for nil other_metric_set in merge_external_service_metrics (#437)
12
+ * Log `warn` in InstructionSequence only if SCOUT_LOG_LEVEL is debug (#438)
13
+ * Check for Parser::TreeRewriter before loading AutoInstruments to avoid LoadError (#440)
14
+ * Fall back to STDERR upon exception in build_logger (#441)
15
+
16
+
1
17
  # 5.0.0
2
18
 
3
19
  * Add External Service metrics reporting (#403)
@@ -10,10 +10,10 @@ module ScoutApm
10
10
  new_code = Rails.rewrite(path)
11
11
  return self.compile(new_code, path, path)
12
12
  rescue
13
- warn "Failed to apply auto-instrumentation to #{path}: #{$!}"
13
+ warn "Failed to apply auto-instrumentation to #{path}: #{$!}" if ENV['SCOUT_LOG_LEVEL'].to_s.downcase == "debug"
14
14
  end
15
15
  elsif Rails.ignore?(path)
16
- warn "AutoInstruments are ignored for path=#{path}."
16
+ warn "AutoInstruments are ignored for path=#{path}." if ENV['SCOUT_LOG_LEVEL'].to_s.downcase == "debug"
17
17
  end
18
18
 
19
19
  return self.compile_file(path)
@@ -432,7 +432,7 @@ module ScoutApm
432
432
  begin
433
433
  raw_file = File.read(@resolved_file_path)
434
434
  erb_file = ERB.new(raw_file).result(binding)
435
- parsed_yaml = YAML.load(erb_file)
435
+ parsed_yaml = YAML.respond_to?(:unsafe_load) ? YAML.unsafe_load(erb_file) : YAML.load(erb_file)
436
436
  file_settings = parsed_yaml[app_environment]
437
437
 
438
438
  if file_settings.is_a? Hash
@@ -443,8 +443,8 @@ module ScoutApm
443
443
  logger.info("Couldn't find configuration in #{@resolved_file_path} for environment: #{app_environment}. Configuration in ENV will still be applied.")
444
444
  @file_loaded = false
445
445
  end
446
- rescue Exception => e # Explicit `Exception` handling to catch SyntaxError and anything else that ERB or YAML may throw
447
- logger.info("Failed loading configuration file (#{@resolved_file_path}): #{e.message}. ScoutAPM will continue starting with configuration from ENV and defaults")
446
+ rescue ScoutApm::AllExceptionsExceptOnesWeMustNotRescue => e # Everything except the most important exceptions we should never interfere with
447
+ logger.info("Failed loading configuration file (#{@resolved_file_path}): ScoutAPM will continue starting with configuration from ENV and defaults. Exception was #{e.class}: #{e.message}#{e.backtrace.map { |bt| "\n #{bt}" }.join('')}")
448
448
  @file_loaded = false
449
449
  end
450
450
  end
@@ -0,0 +1,12 @@
1
+ module ScoutApm
2
+ module AllExceptionsExceptOnesWeMustNotRescue
3
+ # Borrowed from https://github.com/rspec/rspec-support/blob/v3.8.0/lib/rspec/support.rb#L132-L140
4
+ # These exceptions are dangerous to rescue as rescuing them
5
+ # would interfere with things we should not interfere with.
6
+ AVOID_RESCUING = [NoMemoryError, SignalException, Interrupt, SystemExit]
7
+
8
+ def self.===(exception)
9
+ AVOID_RESCUING.none? { |ar| ar === exception }
10
+ end
11
+ end
12
+ end
@@ -78,7 +78,7 @@ module ScoutApm
78
78
  end
79
79
 
80
80
  if adapter.nil?
81
- adapter = ActiveRecord::Base.configurations[env]["adapter"]
81
+ adapter = ActiveRecord::Base.configurations.to_h[env]["adapter"]
82
82
  end
83
83
 
84
84
  return adapter
@@ -32,6 +32,7 @@ module ScoutApm
32
32
  install_instrument(ScoutApm::Instruments::NetHttp)
33
33
  install_instrument(ScoutApm::Instruments::Typhoeus)
34
34
  install_instrument(ScoutApm::Instruments::HttpClient)
35
+ install_instrument(ScoutApm::Instruments::HTTP)
35
36
  install_instrument(ScoutApm::Instruments::Memcached)
36
37
  install_instrument(ScoutApm::Instruments::Redis)
37
38
  install_instrument(ScoutApm::Instruments::InfluxDB)
@@ -69,7 +69,11 @@ module ScoutApm
69
69
  private
70
70
 
71
71
  def build_logger
72
- logger_class.new(@log_destination) rescue logger_class.new
72
+ logger_class.new(@log_destination)
73
+ rescue => e
74
+ logger = ::Logger.new(STDERR)
75
+ logger.error("Error while building ScoutApm logger: #{e.message}. Falling back to STDERR")
76
+ logger
73
77
  end
74
78
 
75
79
  def logger_class
@@ -266,7 +266,11 @@ module ScoutApm
266
266
  end
267
267
 
268
268
  def merge_external_service_metrics!(other_metric_set)
269
- external_service_metric_set.combine!(other_metric_set)
269
+ if other_metric_set.nil?
270
+ logger.debug("Missing other_metric_set for merge_external_service_metrics - skipping.")
271
+ else
272
+ external_service_metric_set.combine!(other_metric_set)
273
+ end
270
274
  self
271
275
  end
272
276
 
@@ -12,11 +12,13 @@ module ScoutApm
12
12
 
13
13
  PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*\z|.freeze
14
14
  PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
15
+ PSQL_REMOVE_JSON_STRINGS = /:"(?:[^"]|"")*"/.freeze
15
16
  PSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
16
17
  PSQL_AFTER_SELECT = /(?:SELECT\s+).*?(?:WHERE|FROM\z)/im.freeze # Should be everything between a FROM and a WHERE
17
18
  PSQL_PLACEHOLDER = /\$\d+/.freeze
18
19
  PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
19
20
  PSQL_AFTER_FROM = /(?:FROM\s+).*?(?:WHERE|\z)/im.freeze # Should be everything between a FROM and a WHERE
21
+ PSQL_AFTER_FROM_AS = /(?:FROM\s+).*?(?:AS|\z)/im.freeze # Should be everything between a FROM and AS without WHERE
20
22
  PSQL_AFTER_JOIN = /(?:JOIN\s+).*?\z/im.freeze
21
23
  PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|\z)/im.freeze
22
24
  PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|\z)/im.freeze
@@ -76,6 +78,7 @@ module ScoutApm
76
78
  sql.gsub!(PSQL_VAR_INTERPOLATION, '')
77
79
  # sql.gsub!(PSQL_REMOVE_STRINGS, '?')
78
80
  sql.gsub!(PSQL_AFTER_WHERE) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
81
+ sql.gsub!(PSQL_AFTER_FROM_AS) {|c| c.gsub(PSQL_REMOVE_JSON_STRINGS, ':"?"')}
79
82
  sql.gsub!(PSQL_AFTER_JOIN) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
80
83
  sql.gsub!(PSQL_AFTER_SET) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
81
84
  sql.gsub!(PSQL_REMOVE_INTEGERS, '?')
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "5.0.0"
2
+ VERSION = "5.1.0"
3
3
  end
data/lib/scout_apm.rb CHANGED
@@ -27,6 +27,7 @@ require 'rusage'
27
27
  #####################################
28
28
  require 'scout_apm/version'
29
29
 
30
+ require 'scout_apm/exceptions'
30
31
  require 'scout_apm/debug'
31
32
  require 'scout_apm/tracked_request'
32
33
  require 'scout_apm/layer'
@@ -80,6 +81,7 @@ require 'scout_apm/histogram'
80
81
 
81
82
  require 'scout_apm/instruments/net_http'
82
83
  require 'scout_apm/instruments/http_client'
84
+ require 'scout_apm/instruments/http'
83
85
  require 'scout_apm/instruments/typhoeus'
84
86
  require 'scout_apm/instruments/moped'
85
87
  require 'scout_apm/instruments/mongoid'
@@ -221,8 +223,12 @@ if defined?(Rails) && defined?(Rails::VERSION) && defined?(Rails::VERSION::MAJOR
221
223
  ScoutApm::Agent.instance.install
222
224
 
223
225
  if ScoutApm::Agent.instance.context.config.value("auto_instruments")
224
- ScoutApm::Agent.instance.context.logger.debug("AutoInstruments is enabled.")
225
- require 'scout_apm/auto_instrument'
226
+ if defined?(Parser::TreeRewriter)
227
+ ScoutApm::Agent.instance.context.logger.debug("AutoInstruments is enabled.")
228
+ require 'scout_apm/auto_instrument'
229
+ else # AutoInstruments is turned on, but we don't he the prerequisites to use it
230
+ ScoutApm::Agent.instance.context.logger.debug("AutoInstruments is enabled, but Parser::TreeRewriter is missing. Update 'parser' gem to >= 2.5.0.")
231
+ end
226
232
  else
227
233
  ScoutApm::Agent.instance.context.logger.debug("AutoInstruments is disabled.")
228
234
  end
data/scout_apm.gemspec CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |s|
10
10
  s.homepage = "https://github.com/scoutapp/scout_apm_ruby"
11
11
  s.summary = "Ruby application performance monitoring"
12
12
  s.description = "Monitors Ruby apps and reports detailed metrics on performance to Scout."
13
- s.license = "Proprietary (See LICENSE.md)"
13
+ s.license = "MIT"
14
14
 
15
15
  s.files = `git ls-files`.split("\n")
16
16
  s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
@@ -194,6 +194,17 @@ module ScoutApm
194
194
  WHERE (title = ?)|, ss.to_s
195
195
  end
196
196
 
197
+ def test_postgres_insert_select_from_jsonb_to_recordset_with_as
198
+ sql = %q|
199
+ INSERT INTO foos(foo_id, bar_id, external_id, email_address, created_at, updated_at)
200
+ SELECT 123, 456, external_id, email_address, NOW(), NOW()
201
+ FROM jsonb_to_recordset($${"items":[{"external_id":1234,"email_address":"test@domain.com"}]}$$::jsonb->'items')
202
+ AS t(external_id integer, email_address varchar)
203
+ |
204
+ ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
205
+ assert_equal %q|INSERT INTO foos(foo_id, bar_id, external_id, email_address, created_at, updated_at) SELECT ?, ?, external_id, email_address, NOW(), NOW() FROM jsonb_to_recordset($${"items":[{"external_id":?,"email_address":"?"}]}$$::jsonb->'items') AS t(external_id integer, email_address varchar)|, ss.to_s
206
+ end
207
+
197
208
  def assert_faster_than(target_seconds)
198
209
  t1 = ::Time.now
199
210
  yield
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: 5.0.0
4
+ version: 5.1.0
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: 2021-11-02 00:00:00.000000000 Z
12
+ date: 2021-11-18 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest
@@ -280,6 +280,7 @@ files:
280
280
  - lib/scout_apm/error_service/periodic_work.rb
281
281
  - lib/scout_apm/error_service/railtie.rb
282
282
  - lib/scout_apm/error_service/sidekiq.rb
283
+ - lib/scout_apm/exceptions.rb
283
284
  - lib/scout_apm/extensions/config.rb
284
285
  - lib/scout_apm/extensions/transaction_callback_payload.rb
285
286
  - lib/scout_apm/external_service_metric_set.rb
@@ -469,7 +470,7 @@ files:
469
470
  - test/unit/utils/scm.rb
470
471
  homepage: https://github.com/scoutapp/scout_apm_ruby
471
472
  licenses:
472
- - Proprietary (See LICENSE.md)
473
+ - MIT
473
474
  metadata: {}
474
475
  post_install_message:
475
476
  rdoc_options: []