lib/opentelemetry/instrumentation/mysql2/patches/client.rb in opentelemetry-instrumentation-mysql2-0.25.0 vs lib/opentelemetry/instrumentation/mysql2/patches/client.rb in opentelemetry-instrumentation-mysql2-0.26.0

- old
+ new

@@ -7,122 +7,40 @@ module OpenTelemetry module Instrumentation module Mysql2 module Patches # Module to prepend to Mysql2::Client for instrumentation - module Client # rubocop:disable Metrics/ModuleLength - QUERY_NAMES = [ - 'set names', - 'select', - 'insert', - 'update', - 'delete', - 'begin', - 'commit', - 'rollback', - 'savepoint', - 'release savepoint', - 'explain', - 'drop database', - 'drop table', - 'create database', - 'create table' - ].freeze - - QUERY_NAME_RE = Regexp.new("^(#{QUERY_NAMES.join('|')})", Regexp::IGNORECASE) - - # From: https://github.com/newrelic/newrelic-ruby-agent/blob/0235b288d85b8bc795bdc1a24621dd9f84cfef45/lib/new_relic/agent/database/obfuscation_helpers.rb#L9-L34 - COMPONENTS_REGEX_MAP = { - single_quotes: /'(?:[^']|'')*?(?:\\'.*|'(?!'))/, - double_quotes: /"(?:[^"]|"")*?(?:\\".*|"(?!"))/, - 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{\/\*(?:[^\/]|\/[^*])*?(?:\*\/|\/\*.*)} - }.freeze - - MYSQL_COMPONENTS = %i[ - single_quotes - double_quotes - numeric_literals - boolean_literals - hexadecimal_literals - comments - multi_line_comments - ].freeze - + module Client def query(sql, options = {}) attributes = client_attributes case config[:db_statement] when :include attributes[SemanticConventions::Trace::DB_STATEMENT] = sql when :obfuscate - attributes[SemanticConventions::Trace::DB_STATEMENT] = obfuscate_sql(sql) + attributes[SemanticConventions::Trace::DB_STATEMENT] = + OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql( + sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql + ) end tracer.in_span( - database_span_name(sql), + OpenTelemetry::Helpers::MySQL.database_span_name( + sql, + OpenTelemetry::Instrumentation::Mysql2.attributes[ + SemanticConventions::Trace::DB_OPERATION + ], + database_name, + config + ), attributes: attributes.merge!(OpenTelemetry::Instrumentation::Mysql2.attributes), kind: :client ) do super(sql, options) end end private - def obfuscate_sql(sql) - if sql.size > config[:obfuscation_limit] - first_match_index = sql.index(generated_mysql_regex) - truncation_message = "SQL truncated (> #{config[:obfuscation_limit]} characters)" - return truncation_message unless first_match_index - - truncated_sql = sql[..first_match_index - 1] - "#{truncated_sql}...\n#{truncation_message}" - else - obfuscated = OpenTelemetry::Common::Utilities.utf8_encode(sql, binary: true) - obfuscated = obfuscated.gsub(generated_mysql_regex, '?') - obfuscated = 'Failed to obfuscate SQL query - quote characters remained after obfuscation' if detect_unmatched_pairs(obfuscated) - obfuscated - end - rescue StandardError => e - OpenTelemetry.handle_error(message: 'Failed to obfuscate SQL', exception: e) - 'OpenTelemetry error: failed to obfuscate sql' - end - - def generated_mysql_regex - @generated_mysql_regex ||= Regexp.union(MYSQL_COMPONENTS.map { |component| COMPONENTS_REGEX_MAP[component] }) - end - - def detect_unmatched_pairs(obfuscated) - # We use this 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. - %r{'|"|\/\*|\*\/}.match(obfuscated) - end - - def database_span_name(sql) - case config[:span_name] - when :statement_type - extract_statement_type(sql) - when :db_name - database_name - when :db_operation_and_name - op = OpenTelemetry::Instrumentation::Mysql2.attributes[SemanticConventions::Trace::DB_OPERATION] - name = database_name - if op && name - "#{op} #{name}" - elsif op - op - elsif name - name - end - end || 'mysql' - end - def database_name # https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L78 (query_options[:database] || query_options[:dbname] || query_options[:db])&.to_s end @@ -147,16 +65,9 @@ Mysql2::Instrumentation.instance.tracer end def config Mysql2::Instrumentation.instance.config - end - - def extract_statement_type(sql) - QUERY_NAME_RE.match(sql) { |match| match[1].downcase } unless sql.nil? - rescue StandardError => e - OpenTelemetry.logger.debug("Error extracting sql statement type: #{e.message}") - nil end end end end end