From 43d24eec166934990008e63be383ef922e8f5dbe Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Thu, 8 Aug 2024 10:39:20 -0700 Subject: [PATCH 01/17] Add Mysql2 and Trilogy collection_name attribute --- instrumentation/mysql2/example/mysql2.rb | 3 ++ .../instrumentation/mysql2/patches/client.rb | 17 +++++- .../mysql2/test/fixtures/sql_table_name.json | 54 +++++++++++++++++++ .../mysql2/instrumentation_test.rb | 23 +++++++- .../instrumentation/trilogy/patches/client.rb | 15 +++++- .../trilogy/test/fixtures/sql_table_name.json | 54 +++++++++++++++++++ .../trilogy/instrumentation_test.rb | 28 ++++++++++ 7 files changed, 189 insertions(+), 5 deletions(-) create mode 100644 instrumentation/mysql2/test/fixtures/sql_table_name.json create mode 100644 instrumentation/trilogy/test/fixtures/sql_table_name.json diff --git a/instrumentation/mysql2/example/mysql2.rb b/instrumentation/mysql2/example/mysql2.rb index 294e9575e..5515cc550 100644 --- a/instrumentation/mysql2/example/mysql2.rb +++ b/instrumentation/mysql2/example/mysql2.rb @@ -21,3 +21,6 @@ client.query("SELECT * from information_schema.INNODB_TABLES; /**Dé**/").each do |row| puts row end + +client.query('CREATE TABLE test_table (id SERIAL PRIMARY KEY, name VARCHAR(50), age INT)') +client.query('DROP TABLE test_table') diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index c9dbdaddd..65365e208 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -13,6 +13,10 @@ module Mysql2 module Patches # Module to prepend to Mysql2::Client for instrumentation module Client + + # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands + TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i + def query(sql, options = {}) tracer.in_span( _otel_span_name(sql), @@ -47,7 +51,7 @@ def _otel_span_name(sql) end def _otel_span_attributes(sql) - attributes = _otel_client_attributes + attributes = _otel_client_attributes(sql) case config[:db_statement] when :include attributes[SemanticConventions::Trace::DB_STATEMENT] = sql @@ -68,7 +72,7 @@ def _otel_database_name (query_options[:database] || query_options[:dbname] || query_options[:db])&.to_s end - def _otel_client_attributes + def _otel_client_attributes(sql) # The client specific attributes can be found via the query_options instance variable # exposed on the mysql2 Client # https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L25-L26 @@ -83,9 +87,18 @@ def _otel_client_attributes attributes[SemanticConventions::Trace::DB_NAME] = _otel_database_name attributes[SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] + attributes['db.collection.name'] = collection_name(sql) + attributes end + def collection_name(sql) + sql.scan(TABLE_NAME).flatten[0] + + rescue StandardError + nil + end + def tracer Mysql2::Instrumentation.instance.tracer end diff --git a/instrumentation/mysql2/test/fixtures/sql_table_name.json b/instrumentation/mysql2/test/fixtures/sql_table_name.json new file mode 100644 index 000000000..eacd9571f --- /dev/null +++ b/instrumentation/mysql2/test/fixtures/sql_table_name.json @@ -0,0 +1,54 @@ +[ + { + "name": "from", + "sql": "SELECT * FROM test_table" + }, + { + "name": "select_count_from", + "sql": "SELECT COUNT(*) FROM test_table WHERE condition" + }, + { + "name": "from_with_subquery", + "sql": "SELECT * FROM (SELECT * FROM test_table) AS table_alias" + }, + { + "name": "insert_into", + "sql": "INSERT INTO test_table (column1, column2) VALUES (value1, value2)" + }, + { + "name": "update", + "sql": "UPDATE test_table SET column1 = value1 WHERE condition" + }, + { + "name": "delete_from", + "sql": "DELETE FROM test_table WHERE condition" + }, + { + "name": "create_table", + "sql": "CREATE TABLE test_table (column1 datatype, column2 datatype)" + }, + { + "name": "create_table_if_not_exists", + "sql": "CREATE TABLE IF NOT EXISTS test_table (column1 datatype, column2 datatype)" + }, + { + "name": "alter_table", + "sql": "ALTER TABLE test_table ADD column_name datatype" + }, + { + "name": "drop_table", + "sql": "DROP TABLE test_table" + }, + { + "name": "drop_table_if_exists", + "sql": "DROP TABLE IF EXISTS test_table" + }, + { + "name": "insert_into", + "sql": "INSERT INTO test_table values('', 'a''b c',0, 1 , 'd''e f''s h')" + }, + { + "name": "from_with_join", + "sql": "SELECT columns FROM test_table JOIN table2 ON test_table.column = table2.column" + } + ] \ No newline at end of file diff --git a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb index 319e138d8..6891f426d 100644 --- a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb +++ b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb @@ -15,9 +15,9 @@ # 1. Build the opentelemetry/opentelemetry-ruby-contrib image # - docker-compose build # 2. Bundle install -# - docker-compose run ex-instrumentation-mysql2-test bundle install +# - docker-compose run ex-instrumentation-mysql2-test bundle exec appraisal install # 3. Run test suite -# - docker-compose run ex-instrumentation-mysql2-test bundle exec rake test +# - docker-compose run ex-instrumentation-mysql2-test bundle exec appraisal rake test describe OpenTelemetry::Instrumentation::Mysql2::Instrumentation do let(:instrumentation) { OpenTelemetry::Instrumentation::Mysql2::Instrumentation.instance } let(:exporter) { EXPORTER } @@ -473,6 +473,25 @@ end end end + + describe '#connection_name' do + + def self.load_fixture + data = File.read("#{Dir.pwd}/test/fixtures/sql_table_name.json") + JSON.parse(data) + end + + load_fixture.each do |test_case| + name = test_case['name'] + query = test_case['sql'] + + it "returns the table name for #{name}" do + table_name = client.send(:collection_name, query) + + expect(table_name).must_equal('test_table') + end + end + end end end unless ENV['OMIT_SERVICES'] end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 8f15dd89d..a4f5bce8f 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -13,6 +13,10 @@ module Trilogy module Patches # Module to prepend to Trilogy for instrumentation module Client + + # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands + TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i + def initialize(options = {}) @connection_options = options # This is normally done by Trilogy#initialize @@ -76,6 +80,8 @@ def client_attributes(sql = nil) attributes['db.instance.id'] = @connected_host unless @connected_host.nil? if sql + attributes['db.collection.name'] = collection_name(sql) + case config[:db_statement] when :obfuscate attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = @@ -84,10 +90,17 @@ def client_attributes(sql = nil) attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql end end - + attributes.compact! attributes end + def collection_name(sql) + sql.scan(TABLE_NAME).flatten[0] + + rescue StandardError + nil + end + def database_name connection_options[:database] end diff --git a/instrumentation/trilogy/test/fixtures/sql_table_name.json b/instrumentation/trilogy/test/fixtures/sql_table_name.json new file mode 100644 index 000000000..eacd9571f --- /dev/null +++ b/instrumentation/trilogy/test/fixtures/sql_table_name.json @@ -0,0 +1,54 @@ +[ + { + "name": "from", + "sql": "SELECT * FROM test_table" + }, + { + "name": "select_count_from", + "sql": "SELECT COUNT(*) FROM test_table WHERE condition" + }, + { + "name": "from_with_subquery", + "sql": "SELECT * FROM (SELECT * FROM test_table) AS table_alias" + }, + { + "name": "insert_into", + "sql": "INSERT INTO test_table (column1, column2) VALUES (value1, value2)" + }, + { + "name": "update", + "sql": "UPDATE test_table SET column1 = value1 WHERE condition" + }, + { + "name": "delete_from", + "sql": "DELETE FROM test_table WHERE condition" + }, + { + "name": "create_table", + "sql": "CREATE TABLE test_table (column1 datatype, column2 datatype)" + }, + { + "name": "create_table_if_not_exists", + "sql": "CREATE TABLE IF NOT EXISTS test_table (column1 datatype, column2 datatype)" + }, + { + "name": "alter_table", + "sql": "ALTER TABLE test_table ADD column_name datatype" + }, + { + "name": "drop_table", + "sql": "DROP TABLE test_table" + }, + { + "name": "drop_table_if_exists", + "sql": "DROP TABLE IF EXISTS test_table" + }, + { + "name": "insert_into", + "sql": "INSERT INTO test_table values('', 'a''b c',0, 1 , 'd''e f''s h')" + }, + { + "name": "from_with_join", + "sql": "SELECT columns FROM test_table JOIN table2 ON test_table.column = table2.column" + } + ] \ No newline at end of file diff --git a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb index 9b1b7b845..e90c7ae4d 100644 --- a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb +++ b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb @@ -9,6 +9,16 @@ require_relative '../../../../lib/opentelemetry/instrumentation/trilogy' require_relative '../../../../lib/opentelemetry/instrumentation/trilogy/patches/client' +# This test suite requires a running mysql container and dedicated test container. We can use the same +# docker-compose file as the mysql2 instrumentation tests. The test container should have the mysql client. +# To run tests locally: +# 1. Build the opentelemetry/opentelemetry-ruby-contrib image +# - docker-compose build +# 2. Open a bash shell in the test container and cd to the trilogy directory +# - docker-compose run ex-instrumentation-mysql2-test bash -c 'cd ../trilogy && bash' +# 3. Bundle install and run tests with the Appraisals gem +# - bundle exec appraisal install && bundle exec appraisal rake test + describe OpenTelemetry::Instrumentation::Trilogy do let(:instrumentation) { OpenTelemetry::Instrumentation::Trilogy::Instrumentation.instance } let(:exporter) { EXPORTER } @@ -626,5 +636,23 @@ end end end + + describe '#connection_name' do + def self.load_fixture + data = File.read("#{Dir.pwd}/test/fixtures/sql_table_name.json") + JSON.parse(data) + end + + load_fixture.each do |test_case| + name = test_case['name'] + query = test_case['sql'] + + it "returns the table name for #{name}" do + table_name = client.send(:collection_name, query) + + expect(table_name).must_equal('test_table') + end + end + end end end From 8bd58186aa952bb02704de93ab0755fb03e5e6d9 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Thu, 8 Aug 2024 10:41:13 -0700 Subject: [PATCH 02/17] Remove empty line --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 1 - .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 65365e208..b2b08b073 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -94,7 +94,6 @@ def _otel_client_attributes(sql) def collection_name(sql) sql.scan(TABLE_NAME).flatten[0] - rescue StandardError nil end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index a4f5bce8f..26d6bcdac 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -96,7 +96,6 @@ def client_attributes(sql = nil) def collection_name(sql) sql.scan(TABLE_NAME).flatten[0] - rescue StandardError nil end From 146bd714ae89d2d7ae0c17f1da5ae71514c8e8ed Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Thu, 8 Aug 2024 10:49:15 -0700 Subject: [PATCH 03/17] Appease rubocop --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 1 - .../opentelemetry/instrumentation/mysql2/instrumentation_test.rb | 1 - .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 1 - 3 files changed, 3 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index b2b08b073..fd352cba5 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -13,7 +13,6 @@ module Mysql2 module Patches # Module to prepend to Mysql2::Client for instrumentation module Client - # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i diff --git a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb index 6891f426d..dc442747c 100644 --- a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb +++ b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb @@ -475,7 +475,6 @@ end describe '#connection_name' do - def self.load_fixture data = File.read("#{Dir.pwd}/test/fixtures/sql_table_name.json") JSON.parse(data) diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 26d6bcdac..7d4be1ac3 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -13,7 +13,6 @@ module Trilogy module Patches # Module to prepend to Trilogy for instrumentation module Client - # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i From f9c244eaf83ee3e891748ad385363bc41644a48f Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Tue, 20 Aug 2024 11:37:00 -0700 Subject: [PATCH 04/17] Refactor compact! --- .../opentelemetry/instrumentation/trilogy/patches/client.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 7d4be1ac3..207d0440d 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -79,7 +79,8 @@ def client_attributes(sql = nil) attributes['db.instance.id'] = @connected_host unless @connected_host.nil? if sql - attributes['db.collection.name'] = collection_name(sql) + collection_name = collection_name(sql) + attributes['db.collection.name'] = collection_name if collection_name case config[:db_statement] when :obfuscate @@ -89,7 +90,7 @@ def client_attributes(sql = nil) attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql end end - attributes.compact! + attributes end From 60470529006b0d779bad04f18de15a3514790cb4 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan <76922290+hannahramadan@users.noreply.github.com> Date: Tue, 20 Aug 2024 11:58:06 -0700 Subject: [PATCH 05/17] Apply suggestions from code review Co-authored-by: Kayla Reopelle <87386821+kaylareopelle@users.noreply.github.com> --- .../instrumentation/trilogy/instrumentation_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb index e90c7ae4d..d067db4ff 100644 --- a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb +++ b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb @@ -9,8 +9,8 @@ require_relative '../../../../lib/opentelemetry/instrumentation/trilogy' require_relative '../../../../lib/opentelemetry/instrumentation/trilogy/patches/client' -# This test suite requires a running mysql container and dedicated test container. We can use the same -# docker-compose file as the mysql2 instrumentation tests. The test container should have the mysql client. +# This test suite requires a running mysql service within a dedicated test container. We can use the same +# docker-compose service as the mysql2 instrumentation tests. The test container should run the mysql client. # To run tests locally: # 1. Build the opentelemetry/opentelemetry-ruby-contrib image # - docker-compose build From b61e51e7c7804571aa008f0e7f76fca8d15760fa Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Wed, 21 Aug 2024 12:42:35 -0700 Subject: [PATCH 06/17] Update to older semantic convention --- .../instrumentation/mysql2/patches/client.rb | 22 +++++++++++-------- .../instrumentation/trilogy/patches/client.rb | 2 +- 2 files changed, 14 insertions(+), 10 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index fd352cba5..caa544f08 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -51,14 +51,19 @@ def _otel_span_name(sql) def _otel_span_attributes(sql) attributes = _otel_client_attributes(sql) - case config[:db_statement] - when :include - attributes[SemanticConventions::Trace::DB_STATEMENT] = sql - when :obfuscate - attributes[SemanticConventions::Trace::DB_STATEMENT] = - OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql( - sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql - ) + + if sql + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name(sql) + + case config[:db_statement] + when :include + attributes[SemanticConventions::Trace::DB_STATEMENT] = sql + when :obfuscate + attributes[SemanticConventions::Trace::DB_STATEMENT] = + OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql( + sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql + ) + end end attributes.merge!(OpenTelemetry::Instrumentation::Mysql2.attributes) @@ -86,7 +91,6 @@ def _otel_client_attributes(sql) attributes[SemanticConventions::Trace::DB_NAME] = _otel_database_name attributes[SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] - attributes['db.collection.name'] = collection_name(sql) attributes end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 207d0440d..e16dd573f 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -80,7 +80,7 @@ def client_attributes(sql = nil) if sql collection_name = collection_name(sql) - attributes['db.collection.name'] = collection_name if collection_name + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name if collection_name case config[:db_statement] when :obfuscate From a23b9546b6471190cbd6abf50f6853f1eee18f18 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Mon, 26 Aug 2024 09:36:09 -0700 Subject: [PATCH 07/17] Update regex --- .../opentelemetry/instrumentation/mysql2/patches/client.rb | 4 ++-- .../opentelemetry/instrumentation/pg/patches/connection.rb | 4 ++-- .../opentelemetry/instrumentation/trilogy/patches/client.rb | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index caa544f08..a0e59d403 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -14,7 +14,7 @@ module Patches # Module to prepend to Mysql2::Client for instrumentation module Client # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i def query(sql, options = {}) tracer.in_span( @@ -96,7 +96,7 @@ def _otel_client_attributes(sql) end def collection_name(sql) - sql.scan(TABLE_NAME).flatten[0] + Regexp.last_match[1] if SQL =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb index 98814950b..4ab9db7d0 100644 --- a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb +++ b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb @@ -15,7 +15,7 @@ module Patches # Module to prepend to PG::Connection for instrumentation module Connection # rubocop:disable Metrics/ModuleLength # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i PG::Constants::EXEC_ISH_METHODS.each do |method| define_method method do |*args, &block| @@ -132,7 +132,7 @@ def validated_operation(operation) end def collection_name(text) - text.scan(TABLE_NAME).flatten[0] + Regexp.last_match[1] if SQL =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index e16dd573f..c383249c5 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -14,7 +14,7 @@ module Patches # Module to prepend to Trilogy for instrumentation module Client # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:FROM|INTO|UPDATE|CREATE\s+TABLE(?:\s+IF\s+NOT\s+EXISTS)?|DROP\s+TABLE(?:\s+IF\s+EXISTS)?|ALTER\s+TABLE(?:\s+IF\s+EXISTS)?)\s+([\w\.]+)/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i def initialize(options = {}) @connection_options = options # This is normally done by Trilogy#initialize @@ -95,7 +95,7 @@ def client_attributes(sql = nil) end def collection_name(sql) - sql.scan(TABLE_NAME).flatten[0] + Regexp.last_match[1] if SQL =~ TABLE_NAME rescue StandardError nil end From f099af317ae1dd1de75339aa1aaf216ef174170d Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Mon, 26 Aug 2024 09:42:06 -0700 Subject: [PATCH 08/17] Use correct variable --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 2 +- .../lib/opentelemetry/instrumentation/pg/patches/connection.rb | 2 +- .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index a0e59d403..11695dca2 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -96,7 +96,7 @@ def _otel_client_attributes(sql) end def collection_name(sql) - Regexp.last_match[1] if SQL =~ TABLE_NAME + Regexp.last_match[1] if sql =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb index 4ab9db7d0..2e20349dd 100644 --- a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb +++ b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb @@ -132,7 +132,7 @@ def validated_operation(operation) end def collection_name(text) - Regexp.last_match[1] if SQL =~ TABLE_NAME + Regexp.last_match[1] if text =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index c383249c5..e70c8427e 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -95,7 +95,7 @@ def client_attributes(sql = nil) end def collection_name(sql) - Regexp.last_match[1] if SQL =~ TABLE_NAME + Regexp.last_match[1] if sql =~ TABLE_NAME rescue StandardError nil end From 8134ee34d4dba6f036815e69c42a848334b42f86 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Mon, 26 Aug 2024 11:20:15 -0700 Subject: [PATCH 09/17] Go directly to matching data vs MatchData object --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 2 +- .../lib/opentelemetry/instrumentation/pg/patches/connection.rb | 2 +- .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 11695dca2..6c68b0d0d 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -96,7 +96,7 @@ def _otel_client_attributes(sql) end def collection_name(sql) - Regexp.last_match[1] if sql =~ TABLE_NAME + Regexp.last_match(1) if sql =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb index 2e20349dd..421a02fd0 100644 --- a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb +++ b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb @@ -132,7 +132,7 @@ def validated_operation(operation) end def collection_name(text) - Regexp.last_match[1] if text =~ TABLE_NAME + Regexp.last_match(1) if text =~ TABLE_NAME rescue StandardError nil end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index e70c8427e..097409958 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -95,7 +95,7 @@ def client_attributes(sql = nil) end def collection_name(sql) - Regexp.last_match[1] if sql =~ TABLE_NAME + Regexp.last_match(1) if sql =~ TABLE_NAME rescue StandardError nil end From 83286689e8f288e5894bd3bcba08883606c30d6c Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Tue, 27 Aug 2024 12:24:28 -0700 Subject: [PATCH 10/17] Feature flag --- .../lib/opentelemetry/instrumentation/mysql2/instrumentation.rb | 1 + .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 2 +- .../opentelemetry/instrumentation/trilogy/instrumentation.rb | 1 + .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb index 9a7b78ccb..636135119 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb @@ -23,6 +23,7 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base option :db_statement, default: :obfuscate, validate: %I[omit include obfuscate] option :span_name, default: :statement_type, validate: %I[statement_type db_name db_operation_and_name] option :obfuscation_limit, default: 2000, validate: :integer + option :db_collection_name, default: :include, validate: %I[omit include] private diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 6c68b0d0d..113301a16 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -53,7 +53,7 @@ def _otel_span_attributes(sql) attributes = _otel_client_attributes(sql) if sql - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name(sql) + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name(sql) if config[:db_collection_name] == :include case config[:db_statement] when :include diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb index 684fbe660..d8c5edf05 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb @@ -28,6 +28,7 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base option :span_name, default: :statement_type, validate: %I[statement_type db_name db_operation_and_name] option :obfuscation_limit, default: 2000, validate: :integer option :propagator, default: nil, validate: :string + option :db_collection_name, default: :include, validate: %I[omit include] attr_reader :propagator diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 097409958..5efa4dc9d 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -80,7 +80,7 @@ def client_attributes(sql = nil) if sql collection_name = collection_name(sql) - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name if collection_name + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name && config[:db_collection_name] == :include case config[:db_statement] when :obfuscate From 8f42fa24e00a93e7d4a948f16abf6aeefa7b808f Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Tue, 27 Aug 2024 12:28:33 -0700 Subject: [PATCH 11/17] No nils --- .../lib/opentelemetry/instrumentation/trilogy/patches/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 5efa4dc9d..412011364 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -80,7 +80,7 @@ def client_attributes(sql = nil) if sql collection_name = collection_name(sql) - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name && config[:db_collection_name] == :include + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name if collection_name && config[:db_collection_name] == :include case config[:db_statement] when :obfuscate From e73b23a08be7e4a8b562d7ebfae1f9a9a3b6d954 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Mon, 14 Oct 2024 12:16:45 -0700 Subject: [PATCH 12/17] Omit db_sql_table by default --- .../opentelemetry/instrumentation/mysql2/instrumentation.rb | 2 +- .../opentelemetry/instrumentation/mysql2/patches/client.rb | 4 ++-- .../instrumentation/mysql2/instrumentation_test.rb | 2 +- .../instrumentation/trilogy/instrumentation.rb | 2 +- .../opentelemetry/instrumentation/trilogy/patches/client.rb | 6 +++--- .../instrumentation/trilogy/instrumentation_test.rb | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb index 636135119..4ff0c3222 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb @@ -23,7 +23,7 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base option :db_statement, default: :obfuscate, validate: %I[omit include obfuscate] option :span_name, default: :statement_type, validate: %I[statement_type db_name db_operation_and_name] option :obfuscation_limit, default: 2000, validate: :integer - option :db_collection_name, default: :include, validate: %I[omit include] + option :db_sql_table, default: :omit, validate: %I[omit include] private diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 113301a16..c3f360750 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -53,7 +53,7 @@ def _otel_span_attributes(sql) attributes = _otel_client_attributes(sql) if sql - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name(sql) if config[:db_collection_name] == :include + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = db_sql_table_name(sql) if config[:db_sql_table] == :include case config[:db_statement] when :include @@ -95,7 +95,7 @@ def _otel_client_attributes(sql) attributes end - def collection_name(sql) + def db_sql_table_name(sql) Regexp.last_match(1) if sql =~ TABLE_NAME rescue StandardError nil diff --git a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb index dc442747c..6c57b4336 100644 --- a/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb +++ b/instrumentation/mysql2/test/opentelemetry/instrumentation/mysql2/instrumentation_test.rb @@ -485,7 +485,7 @@ def self.load_fixture query = test_case['sql'] it "returns the table name for #{name}" do - table_name = client.send(:collection_name, query) + table_name = client.send(:db_sql_table_name, query) expect(table_name).must_equal('test_table') end diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb index d8c5edf05..62c0b63fd 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/instrumentation.rb @@ -28,7 +28,7 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base option :span_name, default: :statement_type, validate: %I[statement_type db_name db_operation_and_name] option :obfuscation_limit, default: 2000, validate: :integer option :propagator, default: nil, validate: :string - option :db_collection_name, default: :include, validate: %I[omit include] + option :db_sql_table, default: :omit, validate: %I[omit include] attr_reader :propagator diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 412011364..13b328804 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -79,8 +79,8 @@ def client_attributes(sql = nil) attributes['db.instance.id'] = @connected_host unless @connected_host.nil? if sql - collection_name = collection_name(sql) - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = collection_name if collection_name && config[:db_collection_name] == :include + sql_table_name = db_sql_table_name(sql) + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = sql_table_name if sql_table_name && config[:db_sql_table] == :include case config[:db_statement] when :obfuscate @@ -94,7 +94,7 @@ def client_attributes(sql = nil) attributes end - def collection_name(sql) + def db_sql_table_name(sql) Regexp.last_match(1) if sql =~ TABLE_NAME rescue StandardError nil diff --git a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb index d067db4ff..dd1e1af35 100644 --- a/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb +++ b/instrumentation/trilogy/test/opentelemetry/instrumentation/trilogy/instrumentation_test.rb @@ -648,7 +648,7 @@ def self.load_fixture query = test_case['sql'] it "returns the table name for #{name}" do - table_name = client.send(:collection_name, query) + table_name = client.send(:db_sql_table_name, query) expect(table_name).must_equal('test_table') end From 46616da8690cfce4bf9da424c1d437ae60ff3f0b Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Mon, 14 Oct 2024 13:23:25 -0700 Subject: [PATCH 13/17] Capture table names in double quotes --- .../opentelemetry/instrumentation/mysql2/patches/client.rb | 2 +- instrumentation/mysql2/test/fixtures/sql_table_name.json | 4 ++++ .../opentelemetry/instrumentation/trilogy/patches/client.rb | 2 +- instrumentation/trilogy/test/fixtures/sql_table_name.json | 4 ++++ 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index c3f360750..d1094f4cd 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -14,7 +14,7 @@ module Patches # Module to prepend to Mysql2::Client for instrumentation module Client # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["]?([\w.]+)["]?/i def query(sql, options = {}) tracer.in_span( diff --git a/instrumentation/mysql2/test/fixtures/sql_table_name.json b/instrumentation/mysql2/test/fixtures/sql_table_name.json index eacd9571f..665ff93ed 100644 --- a/instrumentation/mysql2/test/fixtures/sql_table_name.json +++ b/instrumentation/mysql2/test/fixtures/sql_table_name.json @@ -50,5 +50,9 @@ { "name": "from_with_join", "sql": "SELECT columns FROM test_table JOIN table2 ON test_table.column = table2.column" + }, + { + "name": "table_name_with_double_quotes", + "sql": "SELECT columns FROM \"test_table\"" } ] \ No newline at end of file diff --git a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb index 13b328804..e39659bfd 100644 --- a/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb +++ b/instrumentation/trilogy/lib/opentelemetry/instrumentation/trilogy/patches/client.rb @@ -14,7 +14,7 @@ module Patches # Module to prepend to Trilogy for instrumentation module Client # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["]?([\w.]+)["]?/i def initialize(options = {}) @connection_options = options # This is normally done by Trilogy#initialize diff --git a/instrumentation/trilogy/test/fixtures/sql_table_name.json b/instrumentation/trilogy/test/fixtures/sql_table_name.json index eacd9571f..665ff93ed 100644 --- a/instrumentation/trilogy/test/fixtures/sql_table_name.json +++ b/instrumentation/trilogy/test/fixtures/sql_table_name.json @@ -50,5 +50,9 @@ { "name": "from_with_join", "sql": "SELECT columns FROM test_table JOIN table2 ON test_table.column = table2.column" + }, + { + "name": "table_name_with_double_quotes", + "sql": "SELECT columns FROM \"test_table\"" } ] \ No newline at end of file From 4af3e2c333e378f9fc352bfac4933e2b26d3d586 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Wed, 30 Oct 2024 14:19:41 -0700 Subject: [PATCH 14/17] Don't report table name on error --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index d1094f4cd..0b50b8d99 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -53,7 +53,7 @@ def _otel_span_attributes(sql) attributes = _otel_client_attributes(sql) if sql - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = db_sql_table_name(sql) if config[:db_sql_table] == :include + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = db_sql_table_name(sql) if db_sql_table_name(sql) && config[:db_sql_table] == :include case config[:db_statement] when :include @@ -98,6 +98,7 @@ def _otel_client_attributes(sql) def db_sql_table_name(sql) Regexp.last_match(1) if sql =~ TABLE_NAME rescue StandardError + OpenTelemetry.handle_error(message: 'Error extracting collection name', exception: e) nil end From d6ffcdf2bb96d3050f9f42ffc24098e4b9236784 Mon Sep 17 00:00:00 2001 From: Hannah Ramadan <76922290+hannahramadan@users.noreply.github.com> Date: Fri, 8 Nov 2024 10:28:41 -0800 Subject: [PATCH 15/17] Apply suggestions from code review Co-authored-by: Ariel Valentin --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 0b50b8d99..10a9e92c5 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -97,7 +97,7 @@ def _otel_client_attributes(sql) def db_sql_table_name(sql) Regexp.last_match(1) if sql =~ TABLE_NAME - rescue StandardError + rescue StandardError => e OpenTelemetry.handle_error(message: 'Error extracting collection name', exception: e) nil end From d9f1975664a402a7084c89f3d6794cf9c85e5c0e Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Fri, 8 Nov 2024 10:52:29 -0800 Subject: [PATCH 16/17] Update regex --- .../opentelemetry/instrumentation/pg/patches/connection.rb | 2 +- instrumentation/pg/test/fixtures/sql_table_name.json | 4 ++++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb index 421a02fd0..19f0bf202 100644 --- a/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb +++ b/instrumentation/pg/lib/opentelemetry/instrumentation/pg/patches/connection.rb @@ -15,7 +15,7 @@ module Patches # Module to prepend to PG::Connection for instrumentation module Connection # rubocop:disable Metrics/ModuleLength # Capture the first word (including letters, digits, underscores, & '.', ) that follows common table commands - TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["']?([\w.]+)["']?/i + TABLE_NAME = /\b(?:(?:FROM|INTO|UPDATE)|(?:(?:CREATE|DROP|ALTER)\s+TABLE(?:\s+IF\s+(?:NOT\s+)?EXISTS)?))\s+["]?([\w.]+)["]?/i PG::Constants::EXEC_ISH_METHODS.each do |method| define_method method do |*args, &block| diff --git a/instrumentation/pg/test/fixtures/sql_table_name.json b/instrumentation/pg/test/fixtures/sql_table_name.json index eacd9571f..665ff93ed 100644 --- a/instrumentation/pg/test/fixtures/sql_table_name.json +++ b/instrumentation/pg/test/fixtures/sql_table_name.json @@ -50,5 +50,9 @@ { "name": "from_with_join", "sql": "SELECT columns FROM test_table JOIN table2 ON test_table.column = table2.column" + }, + { + "name": "table_name_with_double_quotes", + "sql": "SELECT columns FROM \"test_table\"" } ] \ No newline at end of file From 68f42ec3074b90bb5baa14fadb8b9541bcb60cbb Mon Sep 17 00:00:00 2001 From: Hannah Ramadan Date: Fri, 8 Nov 2024 13:43:16 -0800 Subject: [PATCH 17/17] Only make one sql table method call --- .../lib/opentelemetry/instrumentation/mysql2/patches/client.rb | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb index 10a9e92c5..f4b08910f 100644 --- a/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb +++ b/instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb @@ -53,7 +53,8 @@ def _otel_span_attributes(sql) attributes = _otel_client_attributes(sql) if sql - attributes[SemanticConventions::Trace::DB_SQL_TABLE] = db_sql_table_name(sql) if db_sql_table_name(sql) && config[:db_sql_table] == :include + sql_table_name = db_sql_table_name(sql) + attributes[SemanticConventions::Trace::DB_SQL_TABLE] = sql_table_name if sql_table_name && config[:db_sql_table] == :include case config[:db_statement] when :include