scout_apm 2.6.5 → 2.6.6

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: 41f15f4e7f91d0274a280b34d03697ff422963a39bcadc9f9056f6380b949603
4
- data.tar.gz: c76090db49ba3f24ea685ccf61c0fbe17555affe556d947990cb584bb8f56bb5
3
+ metadata.gz: 73af2b28e0b054233c1ccd48122741d7b8e27adf9c61ee93fea520f7e3a6b3c7
4
+ data.tar.gz: 544c20bf5c56478269232f19a792dcbc00c125befb6e5e7b406be04dc954944e
5
5
  SHA512:
6
- metadata.gz: b33379d021bbb49e1c2c60ca0c1a72f4603539142830b92f3846e87fdf9c9d2244e73dd0be5a84fc567945ca028b62450f48dbfd6fdc0fcab81eb6d44f82bab9
7
- data.tar.gz: 35183553754b6a56397ff10579f014abf168c1b3ef83c22318c691ba6ab2798d6a4264e7d17270b318fe43c0ea5a61ab75c025b974354b10f4f5b1395ad77bb5
6
+ metadata.gz: c8558cd998a6c54ca7cd3c3174ba96c28230b0041a49e2d494460116a6f9065ba28f998ce8a74b546f69a8f1d5ec5dd81b9be29e27f4a874f51e1352f02798f0
7
+ data.tar.gz: 18f7152a257b7ff61cb0c4953542527a2af25220d726ac26ade9242421f817afc83ce18fa28ea018188215717cedb25336ba79a61572cb706f99f16278be3545
@@ -1,3 +1,8 @@
1
+ # 2.6.6
2
+
3
+ * Add basic support for parsing Microsoft SQLServer queries (#317)
4
+ * Refine Postgresql Sanitization with subqueries and JSON operations (#262)
5
+
1
6
  # 2.6.5
2
7
 
3
8
  * Add a tag to any requests that reach maximum number of spans (#316)
@@ -48,6 +48,7 @@ module ScoutApm
48
48
  when "sqlite" then :sqlite
49
49
  when "mysql" then :mysql
50
50
  when "mysql2" then :mysql
51
+ when "sqlserver" then :sqlserver
51
52
  else default
52
53
  end
53
54
  else
@@ -34,15 +34,23 @@ module ScoutApm
34
34
  when :postgres then to_s_postgres
35
35
  when :mysql then to_s_mysql
36
36
  when :sqlite then to_s_sqlite
37
+ when :sqlserver then to_s_sqlserver
37
38
  end
38
39
  end
39
40
 
40
41
  private
41
42
 
43
+ def to_s_sqlserver
44
+ sql.gsub!(SQLSERVER_EXECUTESQL, '\1')
45
+ sql.gsub!(SQLSERVER_REMOVE_INTEGERS, '?')
46
+ sql.gsub!(SQLSERVER_IN_CLAUSE, 'IN (?)')
47
+ sql
48
+ end
49
+
42
50
  def to_s_postgres
43
51
  sql.gsub!(PSQL_PLACEHOLDER, '?')
44
52
  sql.gsub!(PSQL_VAR_INTERPOLATION, '')
45
- sql.gsub!(PSQL_REMOVE_STRINGS, '?')
53
+ sql.gsub!(PSQL_AFTER_WHERE) {|c| c.gsub(PSQL_REMOVE_STRINGS, '?')}
46
54
  sql.gsub!(PSQL_REMOVE_INTEGERS, '?')
47
55
  sql.gsub!(PSQL_IN_CLAUSE, 'IN (?)')
48
56
  sql.gsub!(MULTIPLE_SPACES, ' ')
@@ -5,11 +5,13 @@ module ScoutApm
5
5
  MULTIPLE_SPACES = %r|\s+|.freeze
6
6
  MULTIPLE_QUESTIONS = /\?(,\?)+/.freeze
7
7
 
8
+
8
9
  PSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
9
10
  PSQL_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
10
11
  PSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
11
12
  PSQL_PLACEHOLDER = /\$\d+/.freeze
12
13
  PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
14
+ PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|$)/i.freeze
13
15
 
14
16
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
17
  MYSQL_REMOVE_INTEGERS = /(?<!LIMIT )\b\d+\b/.freeze
@@ -20,6 +22,11 @@ module ScoutApm
20
22
  SQLITE_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
21
23
  SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
22
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
23
30
  end
24
31
  end
25
32
  end
@@ -10,6 +10,7 @@ module ScoutApm
10
10
  PSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
11
11
  PSQL_PLACEHOLDER = /\$\d+/.freeze
12
12
  PSQL_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
13
+ PSQL_AFTER_WHERE = /(?:WHERE\s+).*?(?:SELECT|$)/i.freeze
13
14
 
14
15
  MYSQL_VAR_INTERPOLATION = %r|\[\[.*\]\]\s*$|.freeze
15
16
  MYSQL_REMOVE_INTEGERS = /\b\d+\b/.freeze
@@ -21,6 +22,10 @@ module ScoutApm
21
22
  SQLITE_REMOVE_STRINGS = /'(?:[^']|'')*'/.freeze
22
23
  SQLITE_REMOVE_INTEGERS = /\b\d+\b/.freeze
23
24
 
25
+ # This is not officially supported, but will do its best.
26
+ SQLSERVER_EXECUTESQL = /EXEC sp_executesql N'(.*?)'.*/
27
+ SQLSERVER_REMOVE_INTEGERS = /\b\d+\b/.freeze
28
+ SQLSERVER_IN_CLAUSE = /IN\s+\(\?[^\)]*\)/.freeze
24
29
  end
25
30
  end
26
31
  end
@@ -1,3 +1,3 @@
1
1
  module ScoutApm
2
- VERSION = "2.6.5"
2
+ VERSION = "2.6.6"
3
3
  end
@@ -28,7 +28,23 @@ module ScoutApm
28
28
  sql = %q|SELECT "users".* FROM "users" INNER JOIN "blogs" ON "blogs"."user_id" = "users"."id" WHERE (blogs.title = 'hello world')|
29
29
  ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
30
30
  assert_equal %q|SELECT "users".* FROM "users" INNER JOIN "blogs" ON "blogs"."user_id" = "users"."id" WHERE (blogs.title = ?)|, ss.to_s
31
+ end
32
+
33
+ def test_postgres_strips_after_where
34
+ raw_sql = %q|SELECT DISTINCT ON (flagged_traces.metric_name) flagged_traces.metric_name, "flagged_traces"."trace_id", "flagged_traces"."trace_type", "flagged_traces"."trace_occurred_at", flagged_traces.details ->> 'uri' as uri, (flagged_traces.details ->> 'n_sum_millis')::float as potential_savings, (flagged_traces.details ->> 'n_count')::float as num_queries FROM "flagged_traces" WHERE "flagged_traces"."app_id" = 5 AND "flagged_traces"."trace_type" = 'Request' AND ("flagged_traces"."trace_occurred_at" BETWEEN '2019-04-17 12:28:00.000000' AND '2019-04-18 12:28:00.000000') AND "flagged_traces"."flag_type" = 'nplusone' ORDER BY "flagged_traces"."metric_name" ASC, potential_savings DESC|
35
+ sanitized_sql = SqlSanitizer.new(raw_sql).tap { |it| it.database_engine = :postgres}
36
+ expected_sql = %q|SELECT DISTINCT ON (flagged_traces.metric_name) flagged_traces.metric_name, "flagged_traces"."trace_id", "flagged_traces"."trace_type", "flagged_traces"."trace_occurred_at", flagged_traces.details ->> 'uri' as uri, (flagged_traces.details ->> 'n_sum_millis')::float as potential_savings, (flagged_traces.details ->> 'n_count')::float as num_queries FROM "flagged_traces" WHERE "flagged_traces"."app_id" = ? AND "flagged_traces"."trace_type" = ? AND ("flagged_traces"."trace_occurred_at" BETWEEN ? AND ?) AND "flagged_traces"."flag_type" = ? ORDER BY "flagged_traces"."metric_name" ASC, potential_savings DESC|
37
+ assert_equal expected_sql, sanitized_sql.to_s
38
+ end
31
39
 
40
+ def test_postgres_strips_subquery_strings
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
+ sanitized_sql = SqlSanitizer.new(raw_sql).tap { |it| it.database_engine = :postgres}
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
+ assert_equal expected_sql, sanitized_sql.to_s
45
+ end
46
+
47
+ def test_postgres_strips_integers
32
48
  # Strip integers
33
49
  sql = %q|SELECT "blogs".* FROM "blogs" WHERE (view_count > 10)|
34
50
  ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :postgres }
@@ -89,6 +105,30 @@ module ScoutApm
89
105
  assert_equal %q|INSERT INTO `users` VALUES (?, ?)|, ss.to_s
90
106
  end
91
107
 
108
+ def test_sqlserver_integers
109
+ skip "SQLServer Support requires Ruby 1.9+ For Regexes"
110
+
111
+ sql = "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"
112
+ ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
113
+ assert_equal %q|SELECT [users].* FROM [users] WHERE (age > ?) ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @0 ROWS ONLY|, ss.to_s
114
+ end
115
+
116
+ def test_sqlserver_strings
117
+ skip "SQLServer Support requires Ruby 1.9+ For Regexes"
118
+
119
+ sql = "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE [users].[email] = @0 ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @1 ROWS ONLY', N'@0 nvarchar(4000), @1 int', @0 = N'foo', @1 = 10"
120
+ ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
121
+ assert_equal %q|SELECT [users].* FROM [users] WHERE [users].[email] = @0 ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @1 ROWS ONLY|, ss.to_s
122
+ end
123
+
124
+ def test_sqlserver_in_clause
125
+ skip "SQLServer Support requires Ruby 1.9+ For Regexes"
126
+
127
+ sql = "EXEC sp_executesql N'SELECT [users].* FROM [users] WHERE (id IN (1,2,3)) ORDER BY [users].[id] ASC OFFSET 0 ROWS FETCH NEXT @0 ROWS ONLY', N'@0 int', @0 = 10"
128
+ ss = SqlSanitizer.new(sql).tap{ |it| it.database_engine = :sqlserver }
129
+ assert_equal %q|SELECT [users].* FROM [users] WHERE (id IN (?)) ORDER BY [users].[id] ASC OFFSET ? ROWS FETCH NEXT @0 ROWS ONLY|, ss.to_s
130
+ end
131
+
92
132
  def test_scrubs_invalid_encoding
93
133
  skip "Ruby 1.8.7 has no concept of encoding" if RUBY_VERSION.start_with?("1.8.")
94
134
 
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: 2.6.5
4
+ version: 2.6.6
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: 2019-12-12 00:00:00.000000000 Z
12
+ date: 2019-12-19 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: minitest