Skip to content

Commit 8e778ba

Browse files
fix!: Return message when sql is over the obfuscation limit (#1149)
Previously, when a SQL query with a prepended comment exceeded the obfuscation limit, the query would be truncated without obfuscation. Now, when the when the obfuscation limit is hit, a message is returned and obfuscation is not attempted.
1 parent 012b2c2 commit 8e778ba

File tree

6 files changed

+12
-62
lines changed

6 files changed

+12
-62
lines changed

helpers/sql-obfuscation/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ end
2525

2626
Make sure the `Instrumentation` class for your gem contains configuration options for:
2727

28-
- `:obfuscation_limit`: the length at which the obfuscated SQL string will be truncated.
28+
- `:obfuscation_limit`: the length at which the SQL string will not be obfuscated
2929
Example: `option :obfuscation_limit, default: 2000, validate: :integer`
3030

3131
If you want to add support for a new adapter, update the following constants to include keys for your adapter:

helpers/sql-obfuscation/lib/opentelemetry/helpers/sql_obfuscation.rb

Lines changed: 3 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -94,14 +94,16 @@ def generate_regex(dialect)
9494
# This is a SQL obfuscation utility intended for use in database adapter instrumentation.
9595
#
9696
# @param sql [String] The SQL to obfuscate.
97-
# @param obfuscation_limit [optional Integer] The maximum length of an obfuscated sql statement.
97+
# @param obfuscation_limit [optional Integer] the length at which the SQL string will not be obfuscated
9898
# @param adapter [optional Symbol] the type of database adapter calling the method. `:default`, `:mysql` and `:postgres` are supported.
9999
# @return [String] The SQL query string where the values are replaced with "?". When the sql statement exceeds the obufscation limit
100100
# the first matched pair from the SQL statement will be returned, with an appended truncation message. If trunaction is unsuccessful,
101101
# a string describing the error will be returned.
102102
#
103103
# @api public
104104
def obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default)
105+
return "SQL not obfuscated, query exceeds #{obfuscation_limit} characters" if sql.size > obfuscation_limit
106+
105107
regex = case adapter
106108
when :mysql
107109
MYSQL_COMPONENTS_REGEX
@@ -115,7 +117,6 @@ def obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default)
115117
# https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/160
116118
# https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/345
117119
sql = OpenTelemetry::Common::Utilities.utf8_encode(sql, binary: true)
118-
return truncate_statement(sql, regex, obfuscation_limit) if sql.size > obfuscation_limit
119120

120121
sql = sql.gsub(regex, PLACEHOLDER)
121122
return 'Failed to obfuscate SQL query - quote characters remained after obfuscation' if CLEANUP_REGEX[adapter].match(sql)
@@ -124,16 +125,6 @@ def obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default)
124125
rescue StandardError => e
125126
OpenTelemetry.handle_error(message: 'Failed to obfuscate SQL', exception: e)
126127
end
127-
128-
# @api private
129-
def truncate_statement(sql, regex, limit)
130-
first_match_index = sql.index(regex)
131-
truncation_message = "SQL truncated (> #{limit} characters)"
132-
return truncation_message unless first_match_index
133-
134-
truncated_sql = sql[..first_match_index - 1]
135-
"#{truncated_sql}...\n#{truncation_message}"
136-
end
137128
end
138129
end
139130
end

helpers/sql-obfuscation/test/helpers/sql_obfuscation_test.rb

Lines changed: 2 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -18,17 +18,9 @@ def test_named_arg_defaults_obfuscates
1818
assert_equal(expected, result)
1919
end
2020

21-
def test_obfuscation_limit_truncates_query_after_first_match
21+
def test_obfuscation_returns_message_when_limit_is_reached
2222
sql = "SELECT * from users where users.id = 1 and users.email = '[email protected]'"
23-
expected = "SELECT * from users where users.id = ...\nSQL truncated (> 42 characters)"
24-
result = OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(sql, obfuscation_limit: 42)
25-
26-
assert_equal(expected, result)
27-
end
28-
29-
def test_obfuscation_limit_truncates_when_query_not_encoded_with_utf8
30-
sql = "SELECT * from 😄 where users.id = 1 and users.😄 = '[email protected]'"
31-
expected = "SELECT * from where users.id = ...\nSQL truncated (> 42 characters)"
23+
expected = 'SQL not obfuscated, query exceeds 42 characters'
3224
result = OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(sql, obfuscation_limit: 42)
3325

3426
assert_equal(expected, result)

instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -236,20 +236,9 @@
236236
describe 'with obfuscation_limit' do
237237
let(:config) { { db_statement: :obfuscate, obfuscation_limit: 10 } }
238238

239-
it 'truncates SQL using config limit' do
239+
it 'returns a message when the limit is reached' do
240240
sql = "SELECT * from users where users.id = 1 and users.email = '[email protected]'"
241-
obfuscated_sql = "SELECT * from users where users.id = ...\nSQL truncated (> 10 characters)"
242-
expect do
243-
client.query(sql)
244-
end.must_raise Mysql2::Error
245-
246-
_(span.attributes['db.statement']).must_equal obfuscated_sql
247-
end
248-
249-
it 'handles regex non-matches' do
250-
sql = 'ALTER TABLE my_table DISABLE TRIGGER ALL;'
251-
obfuscated_sql = 'SQL truncated (> 10 characters)'
252-
241+
obfuscated_sql = 'SQL not obfuscated, query exceeds 10 characters'
253242
expect do
254243
client.query(sql)
255244
end.must_raise Mysql2::Error

instrumentation/pg/test/opentelemetry/instrumentation/pg/instrumentation_test.rb

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -297,20 +297,9 @@
297297
describe 'with obfuscation_limit' do
298298
let(:config) { { db_statement: :obfuscate, obfuscation_limit: 10 } }
299299

300-
it 'truncates SQL using config limit' do
300+
it 'returns a message when the limit is reached' do
301301
sql = "SELECT * from users where users.id = 1 and users.email = '[email protected]'"
302-
obfuscated_sql = "SELECT * from users where users.id = ...\nSQL truncated (> 10 characters)"
303-
expect do
304-
client.exec(sql)
305-
end.must_raise PG::UndefinedTable
306-
307-
_(span.attributes['db.statement']).must_equal obfuscated_sql
308-
end
309-
310-
it 'handles regex non-matches' do
311-
sql = 'ALTER TABLE my_table DISABLE TRIGGER ALL;'
312-
obfuscated_sql = 'SQL truncated (> 10 characters)'
313-
302+
obfuscated_sql = 'SQL not obfuscated, query exceeds 10 characters'
314303
expect do
315304
client.exec(sql)
316305
end.must_raise PG::UndefinedTable

instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb

Lines changed: 2 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -323,20 +323,9 @@
323323
describe 'with obfuscation_limit' do
324324
let(:config) { { db_statement: :obfuscate, obfuscation_limit: 10 } }
325325

326-
it 'truncates SQL using config limit' do
326+
it 'returns a message when the limit is reached' do
327327
sql = "SELECT * from users where users.id = 1 and users.email = '[email protected]'"
328-
obfuscated_sql = "SELECT * from users where users.id = ...\nSQL truncated (> 10 characters)"
329-
expect do
330-
client.query(sql)
331-
end.must_raise Trilogy::Error
332-
333-
_(span.attributes['db.statement']).must_equal obfuscated_sql
334-
end
335-
336-
it 'handles regex non-matches' do
337-
sql = 'ALTER TABLE my_table DISABLE TRIGGER ALL;'
338-
obfuscated_sql = 'SQL truncated (> 10 characters)'
339-
328+
obfuscated_sql = 'SQL not obfuscated, query exceeds 10 characters'
340329
expect do
341330
client.query(sql)
342331
end.must_raise Trilogy::Error

0 commit comments

Comments
 (0)