Module: OpenTelemetry::Helpers::SqlObfuscation
- Defined in:
- lib/opentelemetry/helpers/sql_obfuscation.rb,
lib/opentelemetry/helpers/sql_obfuscation/version.rb
Overview
This module contains SQL obfuscation behavior to share with instrumentation for specific database adapters. The class uses code from: https://github.com/newrelic/newrelic-ruby-agent/blob/1fca78cc7a087421ad58088d8bea72c0362bc62f/lib/new_relic/agent/database/obfuscation_helpers.rb
To use this in your instrumentation, the Instrumentation
class for
your gem must contain configuration options for:
:db_statement
Example:option :db_statement, default: :include, validate: %I[omit include obfuscate]
:obfuscation_limit
Example:option :obfuscation_limit, default: 2000, validate: :integer
If you want to add support for a new adapter, update the following constants to include keys for your adapter:
- DIALECT_COMPONENTS
- CLEANUP_REGEX
You must also add a new constant that uses
generate_regex
with your adapter's dialect components that is named like<ADAPTER>_COMPONENTS_REGEX
, such as:MYSQL_COMPONENTS_REGEX
.
Constant Summary collapse
- COMPONENTS_REGEX_MAP =
{ single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/, double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/, dollar_quotes: /(\$(?!\d)[^$]*?\$).*?(?:\1|$)/, uuids: /\{?(?:[0-9a-fA-F]\-*){32}\}?/, numeric_literals: /-?\b(?:[0-9]+\.)?[0-9]+([eE][+-]?[0-9]+)?\b/, boolean_literals: /\b(?:true|false|null)\b/i, hexadecimal_literals: /0x[0-9a-fA-F]+/, comments: /(?:#|--).*?(?=\r|\n|$)/i, multi_line_comments: %r{(?:\/\*.*?\*\/)}m, oracle_quoted_strings: /q'\[.*?(?:\]'|$)|q'\{.*?(?:\}'|$)|q'\<.*?(?:\>'|$)|q'\(.*?(?:\)'|$)/ }.freeze
- DIALECT_COMPONENTS =
{ default: COMPONENTS_REGEX_MAP.keys, mysql: %i[single_quotes double_quotes numeric_literals boolean_literals hexadecimal_literals comments multi_line_comments], postgres: %i[single_quotes dollar_quotes uuids numeric_literals boolean_literals comments multi_line_comments], sqlite: %i[single_quotes numeric_literals boolean_literals hexadecimal_literals comments multi_line_comments], oracle: %i[single_quotes oracle_quoted_strings numeric_literals comments multi_line_comments], cassandra: %i[single_quotes uuids numeric_literals boolean_literals hexadecimal_literals comments multi_line_comments] }.freeze
- PLACEHOLDER =
'?'
- CLEANUP_REGEX =
We use these to check whether the query contains any quote characters after obfuscation. If so, that's a good indication that the original query was malformed, and so our obfuscation can't reliably find literals. In such a case, we'll replace the entire query with a placeholder.
{ default: %r{'|"|\/\*|\*\/}, mysql: %r{'|"|\/\*|\*\//}, postgres: %r{'|\/\*|\*\/|\$(?!\?)/}, sqlite: %r{'|\/\*|\*\//}, cassandra: %r{'|\/\*|\*\//}, oracle: %r{'|\/\*|\*\//} }.freeze
- DEFAULT_COMPONENTS_REGEX =
generate_regex(:default)
- MYSQL_COMPONENTS_REGEX =
generate_regex(:mysql)
- POSTGRES_COMPONENTS_REGEX =
generate_regex(:postgres)
- SQLITE_COMPONENTS_REGEX =
generate_regex(:sqlite)
- CASSANDRA_COMPONENTS_REGEX =
generate_regex(:cassandra)
- ORACLE_COMPONENTS_REGEX =
generate_regex(:oracle)
- VERSION =
'0.1.0'
Class Method Summary collapse
- .generate_regex(dialect) ⇒ Object private
-
.obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default) ⇒ String
This is a SQL obfuscation utility intended for use in database adapter instrumentation.
- .truncate_statement(sql, regex, limit) ⇒ Object private
Class Method Details
.generate_regex(dialect) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
82 83 84 85 |
# File 'lib/opentelemetry/helpers/sql_obfuscation.rb', line 82 def generate_regex(dialect) components = DIALECT_COMPONENTS[dialect] Regexp.union(components.map { |component| COMPONENTS_REGEX_MAP[component] }) end |
.obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default) ⇒ String
This is a SQL obfuscation utility intended for use in database adapter instrumentation.
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 |
# File 'lib/opentelemetry/helpers/sql_obfuscation.rb', line 104 def obfuscate_sql(sql, obfuscation_limit: 2000, adapter: :default) regex = case adapter when :mysql MYSQL_COMPONENTS_REGEX when :postgres POSTGRES_COMPONENTS_REGEX else DEFAULT_COMPONENTS_REGEX end # Original MySQL UTF-8 Encoding Fixes: # https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/160 # https://github.com/open-telemetry/opentelemetry-ruby-contrib/pull/345 sql = OpenTelemetry::Common::Utilities.utf8_encode(sql, binary: true) return truncate_statement(sql, regex, obfuscation_limit) if sql.size > obfuscation_limit sql = sql.gsub(regex, PLACEHOLDER) return 'Failed to obfuscate SQL query - quote characters remained after obfuscation' if CLEANUP_REGEX[adapter].match(sql) sql rescue StandardError => e OpenTelemetry.handle_error(message: 'Failed to obfuscate SQL', exception: e) end |
.truncate_statement(sql, regex, limit) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
129 130 131 132 133 134 135 136 |
# File 'lib/opentelemetry/helpers/sql_obfuscation.rb', line 129 def truncate_statement(sql, regex, limit) first_match_index = sql.index(regex) = "SQL truncated (> #{limit} characters)" return unless first_match_index truncated_sql = sql[..first_match_index - 1] "#{truncated_sql}...\n#{}" end |