scout_apm 5.0.0 → 5.1.0

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
  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: []