scout_apm 4.0.4 → 4.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.markdown +16 -0
- data/lib/scout_apm.rb +1 -0
- data/lib/scout_apm/agent/preconditions.rb +3 -3
- data/lib/scout_apm/auto_instrument/rails.rb +0 -1
- data/lib/scout_apm/background_job_integrations/shoryuken.rb +2 -0
- data/lib/scout_apm/background_job_integrations/sidekiq.rb +13 -2
- data/lib/scout_apm/error_service.rb +3 -1
- data/lib/scout_apm/error_service/middleware.rb +2 -2
- data/lib/scout_apm/error_service/payload.rb +1 -1
- data/lib/scout_apm/framework_integrations/rails_3_or_4.rb +5 -1
- data/lib/scout_apm/ignored_uris.rb +3 -1
- data/lib/scout_apm/instruments/action_controller_rails_3_rails4.rb +5 -2
- data/lib/scout_apm/instruments/action_view.rb +13 -5
- data/lib/scout_apm/instruments/active_record.rb +2 -0
- data/lib/scout_apm/instruments/typhoeus.rb +8 -6
- data/lib/scout_apm/layer_converters/find_layer_by_type.rb +4 -0
- data/lib/scout_apm/logger.rb +1 -1
- data/lib/scout_apm/utils/sql_sanitizer.rb +30 -6
- data/lib/scout_apm/version.rb +1 -1
- data/test/unit/auto_instrument/anonymous_block_value.rb +7 -0
- data/test/unit/auto_instrument/hanging_method.rb +6 -0
- data/test/unit/auto_instrument_test.rb +8 -0
- data/test/unit/ignored_uris_test.rb +6 -0
- data/test/unit/remote/{test_message.rb → message_test.rb} +0 -0
- data/test/unit/remote/{test_router.rb → route_test.rb} +0 -0
- data/test/unit/remote/{test_server.rb → server_test.rb} +4 -1
- data/test/unit/sql_sanitizer_test.rb +17 -2
- metadata +7 -7
- data/lib/scout_apm/utils/sql_sanitizer_regex.rb +0 -32
- data/lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb +0 -32
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5af3fd0ff7d9f43aa8ec1b205104fb90784ba83b98250ef871d5bd1282734432
|
4
|
+
data.tar.gz: aae89c06e87f165d0ee87491fbb58253b7b38cdad29375e555e9e0c1d5607129
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 304283c6c853ce0b2421eccaf3e331c784bd97bda96014777a3a52b64212250595c8d6f7ff390ee154a090d096d1b37f93f221a5e22b2133e47b4a4e36dc4d8e
|
7
|
+
data.tar.gz: 453dd2e29eb7d8bc44ef3527a7ab8ba486d5c9c709b9be275a0223df96deb1d7628c97418a220ca0425e5c6706e1e60c1a8f750f544b223a3b3fcd6c4e924d4f
|
data/CHANGELOG.markdown
CHANGED
@@ -1,9 +1,25 @@
|
|
1
|
+
# 4.1.0
|
2
|
+
|
3
|
+
* Preload Celluloid in Shoryuken instrumentation (#331)
|
4
|
+
* Fix deprecation warning in Rails 6.1+ (#365)
|
5
|
+
* Set Typheous's desc more directly (#392)
|
6
|
+
* Delegate to ActiveRecord #log more intelligently (#394)
|
7
|
+
* Don't delay starting agent when possible (#397)
|
8
|
+
* Fix template naming issue in Rails 6+ (#399)
|
9
|
+
* Avoid double-counting issue with AutoInstruments (#405)
|
10
|
+
* Renaming test files for Remote::{Server|Route|Message} to be included in test run (#409)
|
11
|
+
* More robust naming of Sidekiq jobs (#412)
|
12
|
+
* Allow render_template instruments to work with older Rails (#413)
|
13
|
+
* Fix function to manually capture exceptions (#415)
|
14
|
+
* Enhance SQL Sanitization (#417)
|
15
|
+
|
1
16
|
# 4.0.4
|
2
17
|
|
3
18
|
* Add Faktory Support (#385)
|
4
19
|
* Remove Regexp hack for 1.8.7 (no longer supported) (#384)
|
5
20
|
* More robust DelayedJob detection (#382)
|
6
21
|
* Fix kwargs handling in Tracing module (#381)
|
22
|
+
|
7
23
|
# 4.0.3
|
8
24
|
|
9
25
|
* Handle edge case with nil Typhoeus current-layer (#380)
|
data/lib/scout_apm.rb
CHANGED
@@ -193,6 +193,7 @@ require 'scout_apm/tasks/support'
|
|
193
193
|
require 'scout_apm/extensions/config'
|
194
194
|
require 'scout_apm/extensions/transaction_callback_payload'
|
195
195
|
|
196
|
+
require 'scout_apm/error'
|
196
197
|
require 'scout_apm/error_service'
|
197
198
|
require 'scout_apm/error_service/middleware'
|
198
199
|
require 'scout_apm/error_service/notifier'
|
@@ -27,10 +27,10 @@ module ScoutApm
|
|
27
27
|
PRECONDITION_DETECTED_SERVER = {
|
28
28
|
:message => proc {|environ| "Deferring agent start. Standing by for first request" },
|
29
29
|
:check => proc { |context|
|
30
|
-
|
31
|
-
|
30
|
+
app_server_found = context.environment.app_server_integration(true).found?
|
31
|
+
background_job_integration_found = context.environment.background_job_integrations.length > 0
|
32
32
|
|
33
|
-
|
33
|
+
app_server_found || background_job_integration_found
|
34
34
|
},
|
35
35
|
:severity => :info,
|
36
36
|
},
|
@@ -37,6 +37,8 @@ module ScoutApm
|
|
37
37
|
end
|
38
38
|
|
39
39
|
def install_processor
|
40
|
+
# celluloid has not loaded by this point and older versions of `shorykuen/processor` assume that it did
|
41
|
+
require 'celluloid' if defined?(::Shoryuken::VERSION) && ::Shoryuken::VERSION < '3'
|
40
42
|
require 'shoryuken/processor' # sidekiq v4 has not loaded this file by this point
|
41
43
|
|
42
44
|
::Shoryuken::Processor.class_eval do
|
@@ -80,12 +80,23 @@ module ScoutApm
|
|
80
80
|
DELAYED_WRAPPER_KLASS = 'Sidekiq::Extensions::DelayedClass'.freeze
|
81
81
|
|
82
82
|
|
83
|
+
# Capturing the class name is a little tricky, since we need to handle several cases:
|
84
|
+
# 1. ActiveJob, with the class in the key 'wrapped'
|
85
|
+
# 2. ActiveJob, but the 'wrapped' key is wrong (due to YAJL serializing weirdly), find it in args.job_class
|
86
|
+
# 3. DelayedJob wrapper, deserializing using YAML into the real object, which can be introspected
|
87
|
+
# 4. No wrapper, just sidekiq's class
|
83
88
|
def job_class(msg)
|
84
89
|
job_class = msg.fetch('class', UNKNOWN_CLASS_PLACEHOLDER)
|
85
90
|
|
86
|
-
if job_class == ACTIVE_JOB_KLASS && msg.key?('wrapped')
|
91
|
+
if job_class == ACTIVE_JOB_KLASS && msg.key?('wrapped') && msg['wrapped'].is_a?(String)
|
87
92
|
begin
|
88
|
-
job_class = msg['wrapped']
|
93
|
+
job_class = msg['wrapped'].to_s
|
94
|
+
rescue
|
95
|
+
ACTIVE_JOB_KLASS
|
96
|
+
end
|
97
|
+
elsif job_class == ACTIVE_JOB_KLASS && msg.try(:[], 'args').try(:[], 'job_class')
|
98
|
+
begin
|
99
|
+
job_class = msg['args']['job_class'].to_s
|
89
100
|
rescue
|
90
101
|
ACTIVE_JOB_KLASS
|
91
102
|
end
|
@@ -16,7 +16,9 @@ module ScoutApm
|
|
16
16
|
# Used internally by SidekiqException
|
17
17
|
def self.capture(exception, params = {})
|
18
18
|
return if disabled?
|
19
|
-
|
19
|
+
|
20
|
+
context = ScoutApm::Agent.instance.context
|
21
|
+
return if context.ignored_exceptions.ignore?(exception)
|
20
22
|
|
21
23
|
context.errors_buffer.capture(exception, env)
|
22
24
|
end
|
@@ -9,10 +9,10 @@ module ScoutApm
|
|
9
9
|
begin
|
10
10
|
response = @app.call(env)
|
11
11
|
rescue Exception => exception
|
12
|
-
puts "[Scout Error Service] Caught Exception: #{exception.class.name}"
|
13
|
-
|
14
12
|
context = ScoutApm::Agent.instance.context
|
15
13
|
|
14
|
+
context.logger.debug "[Scout Error Service] Caught Exception: #{exception.class.name}"
|
15
|
+
|
16
16
|
# Bail out early, and reraise if the error is not interesting.
|
17
17
|
if context.ignored_exceptions.ignored?(exception)
|
18
18
|
raise
|
@@ -71,7 +71,11 @@ module ScoutApm
|
|
71
71
|
#
|
72
72
|
# We avoid this issue by not calling .respond_to? here, and instead using the less optimal `rescue nil` approach
|
73
73
|
def raw_database_adapter
|
74
|
-
adapter = ActiveRecord::Base.
|
74
|
+
adapter = ActiveRecord::Base.connection_db_config.configuration_hash[:adapter] rescue nil
|
75
|
+
|
76
|
+
if adapter.nil?
|
77
|
+
adapter = ActiveRecord::Base.connection_config[:adapter].to_s rescue nil
|
78
|
+
end
|
75
79
|
|
76
80
|
if adapter.nil?
|
77
81
|
adapter = ActiveRecord::Base.configurations[env]["adapter"]
|
@@ -4,7 +4,9 @@ module ScoutApm
|
|
4
4
|
attr_reader :regex
|
5
5
|
|
6
6
|
def initialize(prefixes)
|
7
|
-
regexes = Array(prefixes).
|
7
|
+
regexes = Array(prefixes).
|
8
|
+
reject{|prefix| prefix == ""}.
|
9
|
+
map {|prefix| %r{\A#{prefix}} }
|
8
10
|
@regex = Regexp.union(*regexes)
|
9
11
|
end
|
10
12
|
|
@@ -95,8 +95,11 @@ module ScoutApm
|
|
95
95
|
req.instant_key = instant_key
|
96
96
|
end
|
97
97
|
|
98
|
-
|
99
|
-
|
98
|
+
# Don't start a new layer if ActionController::API or
|
99
|
+
# ActionController::Base handled it already. Needs to account for
|
100
|
+
# any layers started during a around_action (most likely
|
101
|
+
# AutoInstrument, but could be another custom instrument)
|
102
|
+
if current_layer && (current_layer.type == "Controller" || current_layer.type == "AutoInstrument" || req.web?)
|
100
103
|
super
|
101
104
|
else
|
102
105
|
begin
|
@@ -83,7 +83,7 @@ module ScoutApm
|
|
83
83
|
maybe_template = args[1]
|
84
84
|
|
85
85
|
template_name = @template.virtual_path rescue nil # Works on Rails 3.2 -> end of Rails 5 series
|
86
|
-
template_name ||= maybe_template.virtual_path rescue nil # Works on Rails 6 -> 6.0.3
|
86
|
+
template_name ||= maybe_template.virtual_path rescue nil # Works on Rails 6 -> 6.0.3.5
|
87
87
|
template_name ||= "Unknown Partial"
|
88
88
|
|
89
89
|
layer_name = template_name + "/Rendering"
|
@@ -105,7 +105,10 @@ module ScoutApm
|
|
105
105
|
def collection_with_template(*args, **kwargs)
|
106
106
|
req = ScoutApm::RequestManager.lookup
|
107
107
|
|
108
|
-
|
108
|
+
maybe_template = args[1]
|
109
|
+
|
110
|
+
template_name = @template.virtual_path rescue nil # Works on Rails 3.2 -> end of Rails 5 series
|
111
|
+
template_name ||= maybe_template.virtual_path rescue nil # Works on Rails 6 -> 6.0.3.5
|
109
112
|
template_name ||= "Unknown Collection"
|
110
113
|
layer_name = template_name + "/Rendering"
|
111
114
|
|
@@ -126,10 +129,15 @@ module ScoutApm
|
|
126
129
|
end
|
127
130
|
|
128
131
|
module ActionViewTemplateRendererInstruments
|
129
|
-
|
132
|
+
# Don't forward kwargs here, since Rails 3, 4, 5, 6 don't use them, and
|
133
|
+
# it causes annoyances in the instrumentation
|
134
|
+
def render_template(*args)
|
130
135
|
req = ScoutApm::RequestManager.lookup
|
131
136
|
|
132
|
-
|
137
|
+
maybe_template = args[1]
|
138
|
+
|
139
|
+
template_name = args[0].virtual_path rescue nil # Works on Rails 3.2 -> end of Rails 5 series
|
140
|
+
template_name ||= maybe_template.virtual_path rescue nil # Works on Rails 6 -> 6.1.3
|
133
141
|
template_name ||= "Unknown"
|
134
142
|
layer_name = template_name + "/Rendering"
|
135
143
|
|
@@ -138,7 +146,7 @@ module ScoutApm
|
|
138
146
|
|
139
147
|
begin
|
140
148
|
req.start_layer(layer)
|
141
|
-
super(*args
|
149
|
+
super(*args)
|
142
150
|
ensure
|
143
151
|
req.stop_layer
|
144
152
|
end
|
@@ -215,6 +215,7 @@ module ScoutApm
|
|
215
215
|
end
|
216
216
|
end
|
217
217
|
end
|
218
|
+
ruby2_keywords :log if respond_to?(:ruby2_keywords, true)
|
218
219
|
end
|
219
220
|
|
220
221
|
module ActiveRecordInstruments
|
@@ -267,6 +268,7 @@ module ScoutApm
|
|
267
268
|
end
|
268
269
|
end
|
269
270
|
end
|
271
|
+
ruby2_keywords :log if respond_to?(:ruby2_keywords, true)
|
270
272
|
end
|
271
273
|
|
272
274
|
################################################################################
|
@@ -29,10 +29,11 @@ module ScoutApm
|
|
29
29
|
|
30
30
|
module TyphoeusHydraInstrumentation
|
31
31
|
def run(*args, &block)
|
32
|
+
layer = ScoutApm::Layer.new("HTTP", "Hydra")
|
33
|
+
layer.desc = scout_desc if current_layer
|
34
|
+
|
32
35
|
req = ScoutApm::RequestManager.lookup
|
33
|
-
req.start_layer(
|
34
|
-
current_layer = req.current_layer
|
35
|
-
current_layer.desc = scout_desc if current_layer
|
36
|
+
req.start_layer(layer)
|
36
37
|
|
37
38
|
begin
|
38
39
|
super(*args, &block)
|
@@ -50,10 +51,11 @@ module ScoutApm
|
|
50
51
|
|
51
52
|
module TyphoeusInstrumentation
|
52
53
|
def run(*args, &block)
|
54
|
+
layer = ScoutApm::Layer.new("HTTP", scout_request_verb)
|
55
|
+
layer.desc = scout_desc(scout_request_verb, scout_request_url)
|
56
|
+
|
53
57
|
req = ScoutApm::RequestManager.lookup
|
54
|
-
req.start_layer(
|
55
|
-
current_layer = req.current_layer
|
56
|
-
current_layer.desc = scout_desc(scout_request_verb, scout_request_url) if current_layer
|
58
|
+
req.start_layer(layer)
|
57
59
|
|
58
60
|
begin
|
59
61
|
super(*args, &block)
|
@@ -5,6 +5,10 @@
|
|
5
5
|
# show
|
6
6
|
# render :update
|
7
7
|
# end
|
8
|
+
|
9
|
+
# This doesn't cache the negative result when searching for a controller / job,
|
10
|
+
# so that we can ask again later after more of the request has occurred and
|
11
|
+
# correctly find it.
|
8
12
|
module ScoutApm
|
9
13
|
module LayerConverters
|
10
14
|
class FindLayerByType
|
data/lib/scout_apm/logger.rb
CHANGED
@@ -5,12 +5,34 @@ require 'scout_apm/environment'
|
|
5
5
|
module ScoutApm
|
6
6
|
module Utils
|
7
7
|
class SqlSanitizer
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
8
|
+
MULTIPLE_SPACES = %r|\s+|.freeze
|
9
|
+
MULTIPLE_QUESTIONS = /\?(,\?)+/.freeze
|
10
|
+
|
11
|
+
PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*\z|.freeze
|
12
|
+
PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
13
|
+
PSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
14
|
+
PSQL_AFTER_SELECT = /(?:SELECT\s+).*?(?:WHERE|FROM\z)/im.freeze # Should be everything between a FROM and a WHERE
|
15
|
+
PSQL_PLACEHOLDER = /\$\d+/.freeze
|
16
|
+
PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
17
|
+
PSQL_AFTER_FROM = /(?:FROM\s+).*?(?:WHERE|\z)/im.freeze # Should be everything between a FROM and a WHERE
|
18
|
+
PSQL_AFTER_JOIN = /(?:JOIN\s+).*?\z/im.freeze
|
19
|
+
PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|\z)/im.freeze
|
20
|
+
PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|\z)/im.freeze
|
21
|
+
|
22
|
+
MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
23
|
+
MYSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
24
|
+
MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = %r{'(?:\\'|[^']|'')*'}.freeze
|
25
|
+
MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = %r{"(?:\\"|[^"]|"")*"}.freeze
|
26
|
+
MYSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
27
|
+
|
28
|
+
SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
29
|
+
SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
30
|
+
SQLITE_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
31
|
+
|
32
|
+
# => "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (age > 50) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
|
33
|
+
SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
|
34
|
+
SQLSERVER_REMOVE_INTEGERS = /(?<!LIMIT )\b(?<!@)\d+\b/.freeze
|
35
|
+
SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
14
36
|
|
15
37
|
attr_accessor :database_engine
|
16
38
|
|
@@ -50,7 +72,9 @@ module ScoutApm
|
|
50
72
|
def to_s_postgres
|
51
73
|
sql.gsub!(PSQL_PLACEHOLDER, '?')
|
52
74
|
sql.gsub!(PSQL_VAR_INTERPOLATION, '')
|
75
|
+
# sql.gsub!(PSQL_REMOVE_STRINGS, '?')
|
53
76
|
sql.gsub!(PSQL_AFTER_WHERE) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
|
77
|
+
sql.gsub!(PSQL_AFTER_JOIN) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
|
54
78
|
sql.gsub!(PSQL_AFTER_SET) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
|
55
79
|
sql.gsub!(PSQL_REMOVE_INTEGERS, '?')
|
56
80
|
sql.gsub!(PSQL_IN_CLAUSE, 'IN (?)')
|
data/lib/scout_apm/version.rb
CHANGED
@@ -51,4 +51,12 @@ class AutoInstrumentTest < Minitest::Test
|
|
51
51
|
assert_equal instrumented_source("assignments"),
|
52
52
|
normalize_backtrace(::ScoutApm::AutoInstrument::Rails.rewrite(source_path("assignments")))
|
53
53
|
end
|
54
|
+
|
55
|
+
def test_hanging_method_rewrite
|
56
|
+
::ScoutApm::AutoInstrument::Rails.rewrite(source_path("hanging_method"))
|
57
|
+
end
|
58
|
+
|
59
|
+
def test_anonymous_block_value
|
60
|
+
::ScoutApm::AutoInstrument::Rails.rewrite(source_path("anonymous_block_value"))
|
61
|
+
end
|
54
62
|
end if defined? ScoutApm::AutoInstrument
|
@@ -13,4 +13,10 @@ class IgnoredUrlsTest < Minitest::Test
|
|
13
13
|
i = ScoutApm::IgnoredUris.new(["/slow", "/health"])
|
14
14
|
assert_equal false, i.ignore?("/users/2/health")
|
15
15
|
end
|
16
|
+
|
17
|
+
def test_does_not_ignore_empty_string
|
18
|
+
i = ScoutApm::IgnoredUris.new(["", "/admin"])
|
19
|
+
assert_equal false, i.ignore?("/users/2/health")
|
20
|
+
assert_equal true, i.ignore?("/admin/dashboard")
|
21
|
+
end
|
16
22
|
end
|
File without changes
|
File without changes
|
@@ -8,8 +8,11 @@ class TestRemoteServer < Minitest::Test
|
|
8
8
|
logger_io = StringIO.new
|
9
9
|
server = ScoutApm::Remote::Server.new(bind, port, router, Logger.new(logger_io))
|
10
10
|
|
11
|
+
# Cannot test this if we can't require webrick. Ruby 3 stopped including by default
|
12
|
+
skip unless server.require_webrick
|
13
|
+
|
11
14
|
server.start
|
12
|
-
sleep 0.
|
15
|
+
sleep 0.05 # Let the server finish starting. The assert should instead allow a time
|
13
16
|
assert server.running?
|
14
17
|
end
|
15
18
|
end
|
@@ -38,9 +38,9 @@ module ScoutApm
|
|
38
38
|
end
|
39
39
|
|
40
40
|
def test_postgres_strips_subquery_strings
|
41
|
-
raw_sql = %q|"SELECT
|
41
|
+
raw_sql = %q|"SELECT "orgs".* FROM "orgs" WHERE "orgs"."name" = 'Scout' AND "orgs"."created_by_user_id" IN (SELECT "users"."id" FROM "users" WHERE (id > AVG(id)) AND "type" = 'USER' AND "created_at" BETWEEN '2019-04-17 12:28:00.000000' AND '2019-04-18 12:28:00.000000')"|
|
42
42
|
sanitized_sql = SqlSanitizer.new(raw_sql).tap { |it| it.database_engine = :postgres}
|
43
|
-
expected_sql = %q|"SELECT
|
43
|
+
expected_sql = %q|"SELECT "orgs".* FROM "orgs" WHERE "orgs"."name" = ? AND "orgs"."created_by_user_id" IN (SELECT "users"."id" FROM "users" WHERE (id > AVG(id)) AND "type" = ? AND "created_at" BETWEEN ? AND ?)"|
|
44
44
|
assert_equal expected_sql, sanitized_sql.to_s
|
45
45
|
end
|
46
46
|
|
@@ -66,6 +66,21 @@ module ScoutApm
|
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
69
|
+
def test_postgres_inner_join_subquery
|
70
|
+
sql = %q{SELECT x AS y
|
71
|
+
FROM t1
|
72
|
+
INNER JOIN (
|
73
|
+
SELECT id,
|
74
|
+
(ts_rank((to_tsvector('simple', coalesce("pg_search_documents"."content"::text, ''))), (to_tsquery('simple', 'xyz' || 'omg' || 'secret')), ?)) AS rank
|
75
|
+
FROM t2
|
76
|
+
WHERE name = 'literal') sub ON sub.id = t1.id WHERE age > 10}
|
77
|
+
|
78
|
+
expected = %q{SELECT x AS y FROM t1 INNER JOIN ( SELECT id, (ts_rank((to_tsvector(?, coalesce("pg_search_documents"."content"::text, ?))), (to_tsquery(?, ? || ? || ?)), ?)) AS rank FROM t2 WHERE name = ?) sub ON sub.id = t1.id WHERE age > ?}
|
79
|
+
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
|
80
|
+
|
81
|
+
assert_equal expected, ss.to_s
|
82
|
+
end
|
83
|
+
|
69
84
|
def test_mysql_where
|
70
85
|
sql = %q|SELECT `users`.* FROM `users` WHERE `users`.`name` = ? [["name", "chris"]]|
|
71
86
|
ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :mysql }
|
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: 4.0
|
4
|
+
version: 4.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-
|
12
|
+
date: 2021-06-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: minitest
|
@@ -398,8 +398,6 @@ files:
|
|
398
398
|
- lib/scout_apm/utils/numbers.rb
|
399
399
|
- lib/scout_apm/utils/scm.rb
|
400
400
|
- lib/scout_apm/utils/sql_sanitizer.rb
|
401
|
-
- lib/scout_apm/utils/sql_sanitizer_regex.rb
|
402
|
-
- lib/scout_apm/utils/sql_sanitizer_regex_1_8_7.rb
|
403
401
|
- lib/scout_apm/utils/time.rb
|
404
402
|
- lib/scout_apm/utils/unique_id.rb
|
405
403
|
- lib/scout_apm/version.rb
|
@@ -410,11 +408,13 @@ files:
|
|
410
408
|
- test/tmp/README.md
|
411
409
|
- test/unit/agent_context_test.rb
|
412
410
|
- test/unit/agent_test.rb
|
411
|
+
- test/unit/auto_instrument/anonymous_block_value.rb
|
413
412
|
- test/unit/auto_instrument/assignments-instrumented.rb
|
414
413
|
- test/unit/auto_instrument/assignments.rb
|
415
414
|
- test/unit/auto_instrument/controller-ast.txt
|
416
415
|
- test/unit/auto_instrument/controller-instrumented.rb
|
417
416
|
- test/unit/auto_instrument/controller.rb
|
417
|
+
- test/unit/auto_instrument/hanging_method.rb
|
418
418
|
- test/unit/auto_instrument/rescue_from-instrumented.rb
|
419
419
|
- test/unit/auto_instrument/rescue_from.rb
|
420
420
|
- test/unit/auto_instrument_test.rb
|
@@ -443,9 +443,9 @@ files:
|
|
443
443
|
- test/unit/limited_layer_test.rb
|
444
444
|
- test/unit/logger_test.rb
|
445
445
|
- test/unit/metric_set_test.rb
|
446
|
-
- test/unit/remote/
|
447
|
-
- test/unit/remote/
|
448
|
-
- test/unit/remote/
|
446
|
+
- test/unit/remote/message_test.rb
|
447
|
+
- test/unit/remote/route_test.rb
|
448
|
+
- test/unit/remote/server_test.rb
|
449
449
|
- test/unit/request_histograms_test.rb
|
450
450
|
- test/unit/scored_item_set_test.rb
|
451
451
|
- test/unit/serializers/payload_serializer_test.rb
|
@@ -1,32 +0,0 @@
|
|
1
|
-
|
2
|
-
module ScoutApm
|
3
|
-
module Utils
|
4
|
-
module SqlRegex
|
5
|
-
MULTIPLE_SPACES = %r|\s+|.freeze
|
6
|
-
MULTIPLE_QUESTIONS = /\?(,\?)+/.freeze
|
7
|
-
|
8
|
-
PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*\z|.freeze
|
9
|
-
PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
10
|
-
PSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
11
|
-
PSQL_PLACEHOLDER = /\$\d+/.freeze
|
12
|
-
PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
13
|
-
PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|\z)/im.freeze
|
14
|
-
PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|\z)/im.freeze
|
15
|
-
|
16
|
-
MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
17
|
-
MYSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
18
|
-
MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = %r{'(?:\\'|[^']|'')*'}.freeze
|
19
|
-
MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = %r{"(?:\\"|[^"]|"")*"}.freeze
|
20
|
-
MYSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
21
|
-
|
22
|
-
SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
23
|
-
SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
24
|
-
SQLITE_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
|
25
|
-
|
26
|
-
# => "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (age > 50) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
|
27
|
-
SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
|
28
|
-
SQLSERVER_REMOVE_INTEGERS = /(?<!LIMIT )\b(?<!@)\d+\b/.freeze
|
29
|
-
SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
|
2
|
-
module ScoutApm
|
3
|
-
module Utils
|
4
|
-
module SqlRegex
|
5
|
-
MULTIPLE_SPACES = %r|\s+|.freeze
|
6
|
-
MULTIPLE_QUESTIONS = /\?(,\?)+/.freeze
|
7
|
-
|
8
|
-
PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
9
|
-
PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
10
|
-
PSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
|
11
|
-
PSQL_PLACEHOLDER = /\$\d+/.freeze
|
12
|
-
PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
13
|
-
PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|$)/i.freeze
|
14
|
-
PSQL_AFTER_SET = /(?:SET\s+).*?(?:WHERE|$)/i.freeze
|
15
|
-
|
16
|
-
MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
17
|
-
MYSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
|
18
|
-
MYSQL_REMOVE_SINGLE_QUOTE_STRINGS = /'(?:\\'|[^']|'')*'/.freeze
|
19
|
-
MYSQL_REMOVE_DOUBLE_QUOTE_STRINGS = /"(?:\\"|[^"]|"")*"/.freeze
|
20
|
-
MYSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
21
|
-
|
22
|
-
SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
|
23
|
-
SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
|
24
|
-
SQLITE_REMOVE_INTEGERS = /\b\d+\b/.freeze
|
25
|
-
|
26
|
-
# This is not officially supported, but will do its best.
|
27
|
-
SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
|
28
|
-
SQLSERVER_REMOVE_INTEGERS = /\b\d+\b/.freeze
|
29
|
-
SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|