lib/opentelemetry/instrumentation/trilogy/patches/client.rb in opentelemetry-instrumentation-trilogy-0.58.0 vs lib/opentelemetry/instrumentation/trilogy/patches/client.rb in opentelemetry-instrumentation-trilogy-0.59.0
- old
+ new
@@ -1,55 +1,17 @@
# frozen_string_literal: true
+# Copyright The OpenTelemetry Authors
+#
+# SPDX-License-Identifier: Apache-2.0
+
module OpenTelemetry
module Instrumentation
module Trilogy
module Patches
# Module to prepend to Trilogy 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)
-
- 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
-
- FULL_SQL_REGEXP = Regexp.union(MYSQL_COMPONENTS.map { |component| COMPONENTS_REGEX_MAP[component] })
-
+ module Client
def initialize(options = {})
@connection_options = options # This is normally done by Trilogy#initialize
tracer.in_span(
'connect',
@@ -70,14 +32,24 @@
end
end
def query(sql)
tracer.in_span(
- database_span_name(sql),
- attributes: client_attributes(sql).merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
+ OpenTelemetry::Helpers::MySQL.database_span_name(
+ sql,
+ OpenTelemetry::Instrumentation::Trilogy.attributes[
+ OpenTelemetry::SemanticConventions::Trace::DB_OPERATION
+ ],
+ database_name,
+ config
+ ),
+ attributes: client_attributes(sql).merge!(
+ OpenTelemetry::Instrumentation::Trilogy.attributes
+ ),
kind: :client
- ) do
+ ) do |_span, context|
+ propagator.inject(sql, context: context)
super(sql)
end
end
private
@@ -94,66 +66,20 @@
attributes['db.instance.id'] = @connected_host unless @connected_host.nil?
if sql
case config[:db_statement]
when :obfuscate
- attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = obfuscate_sql(sql)
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] =
+ OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql)
when :include
attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql
end
end
attributes
end
- def obfuscate_sql(sql)
- if sql.size > config[:obfuscation_limit]
- first_match_index = sql.index(FULL_SQL_REGEXP)
- 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(FULL_SQL_REGEXP, '?')
- 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 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::Trilogy.attributes['db.operation']
- name = database_name
- if op && name
- "#{op} #{name}"
- elsif op
- op
- elsif name
- name
- end
- end || 'mysql'
- end
-
def database_name
connection_options[:database]
end
def database_user
@@ -166,14 +92,11 @@
def config
Trilogy::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.error("Error extracting sql statement type: #{e.message}")
- nil
+ def propagator
+ Trilogy::Instrumentation.instance.propagator
end
end
end
end
end