Skip to content

Commit 5c8570c

Browse files
committed
feat: semantic convention opt it
1 parent 9e8fe43 commit 5c8570c

File tree

9 files changed

+1372
-112
lines changed

9 files changed

+1372
-112
lines changed

instrumentation/mysql2/Appraisals

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
# frozen_string_literal: true
22

3-
appraise 'mysql2-0.4.0' do
4-
gem 'mysql2'
3+
# To facilitate database semantic convention stability migration, we are using
4+
# appraisal to test the different semantic convention modes along with different
5+
# gem versions. For more information on the semantic convention modes, see:
6+
# https://opentelemetry.io/docs/specs/semconv/non-normative/db-migration/
7+
8+
semconv_stability = %w[old stable dup]
9+
semconv_stability.each do |stability|
10+
appraise "mysql2-0.4.0-#{stability}" do
11+
gem 'mysql2'
12+
end
513
end

instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/instrumentation.rb

Lines changed: 36 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,9 @@ module Mysql2
1111
# instrumentation
1212
class Instrumentation < OpenTelemetry::Instrumentation::Base
1313
install do |_config|
14-
require_dependencies
15-
patch_client
14+
patch_type = determine_semconv
15+
send(:"require_dependencies_#{patch_type}")
16+
send(:"patch_client_#{patch_type}")
1617
end
1718

1819
present do
@@ -26,12 +27,41 @@ class Instrumentation < OpenTelemetry::Instrumentation::Base
2627

2728
private
2829

29-
def require_dependencies
30-
require_relative 'patches/client'
30+
def determine_semconv
31+
stability_opt_in = ENV.fetch('OTEL_SEMCONV_STABILITY_OPT_IN', '')
32+
values = stability_opt_in.split(',').map(&:strip)
33+
34+
if values.include?('database/dup')
35+
'dup'
36+
elsif values.include?('database')
37+
'stable'
38+
else
39+
'old'
40+
end
41+
end
42+
43+
def require_dependencies_dup
44+
require_relative 'patches/dup/client'
45+
end
46+
47+
def require_dependencies_old
48+
require_relative 'patches/old/client'
49+
end
50+
51+
def require_dependencies_stable
52+
require_relative 'patches/stable/client'
53+
end
54+
55+
def patch_client_dup
56+
::Mysql2::Client.prepend(Patches::Dup::Client)
57+
end
58+
59+
def patch_client_old
60+
::Mysql2::Client.prepend(Patches::Old::Client)
3161
end
3262

33-
def patch_client
34-
::Mysql2::Client.prepend(Patches::Client)
63+
def patch_client_stable
64+
::Mysql2::Client.prepend(Patches::Stable::Client)
3565
end
3666
end
3767
end

instrumentation/mysql2/lib/opentelemetry/instrumentation/mysql2/patches/client.rb

Lines changed: 0 additions & 100 deletions
This file was deleted.
Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'opentelemetry-helpers-mysql'
8+
require 'opentelemetry-helpers-sql-obfuscation'
9+
10+
module OpenTelemetry
11+
module Instrumentation
12+
module Mysql2
13+
module Patches
14+
module Dup
15+
# Module to prepend to Mysql2::Client for instrumentation
16+
module Client
17+
def query(sql, options = {})
18+
tracer.in_span(
19+
_otel_span_name(sql),
20+
attributes: _otel_span_attributes(sql),
21+
kind: :client
22+
) do
23+
super
24+
end
25+
end
26+
27+
def prepare(sql)
28+
tracer.in_span(
29+
_otel_span_name(sql),
30+
attributes: _otel_span_attributes(sql),
31+
kind: :client
32+
) do
33+
super
34+
end
35+
end
36+
37+
private
38+
39+
def _otel_span_name(sql)
40+
OpenTelemetry::Helpers::MySQL.database_span_name(
41+
sql,
42+
OpenTelemetry::Instrumentation::Mysql2.attributes[
43+
'db.operation.name'
44+
],
45+
_otel_database_name,
46+
config
47+
)
48+
end
49+
50+
def _otel_span_attributes(sql)
51+
attributes = _otel_client_attributes
52+
case config[:db_statement]
53+
when :include
54+
attributes[SemanticConventions::Trace::DB_STATEMENT] = sql
55+
attributes['db.query.text'] = sql
56+
when :obfuscate
57+
attributes[SemanticConventions::Trace::DB_STATEMENT] =
58+
OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(
59+
sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql
60+
)
61+
attributes['db.query.text'] =
62+
OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(
63+
sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql
64+
)
65+
end
66+
67+
attributes.merge!(OpenTelemetry::Instrumentation::Mysql2.attributes)
68+
attributes.compact!
69+
attributes
70+
end
71+
72+
def _otel_database_name
73+
# https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L78
74+
(query_options[:database] || query_options[:dbname] || query_options[:db])&.to_s
75+
end
76+
77+
def _otel_client_attributes
78+
# The client specific attributes can be found via the query_options instance variable
79+
# exposed on the mysql2 Client
80+
# https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L25-L26
81+
host = (query_options[:host] || query_options[:hostname]).to_s
82+
port = query_options[:port].to_s
83+
84+
attributes = {
85+
SemanticConventions::Trace::DB_SYSTEM => 'mysql',
86+
SemanticConventions::Trace::NET_PEER_NAME => host,
87+
SemanticConventions::Trace::NET_PEER_PORT => port,
88+
'db.system.name' => 'mysql',
89+
'server.address' => host,
90+
'server.port' => port
91+
}
92+
93+
attributes[SemanticConventions::Trace::DB_NAME] = _otel_database_name
94+
attributes['db.namespace'] = _otel_database_name
95+
attributes[SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service]
96+
attributes
97+
end
98+
99+
def tracer
100+
Mysql2::Instrumentation.instance.tracer
101+
end
102+
103+
def config
104+
Mysql2::Instrumentation.instance.config
105+
end
106+
end
107+
end
108+
end
109+
end
110+
end
111+
end
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
# frozen_string_literal: true
2+
3+
# Copyright The OpenTelemetry Authors
4+
#
5+
# SPDX-License-Identifier: Apache-2.0
6+
7+
require 'opentelemetry-helpers-mysql'
8+
require 'opentelemetry-helpers-sql-obfuscation'
9+
10+
module OpenTelemetry
11+
module Instrumentation
12+
module Mysql2
13+
module Patches
14+
module Old
15+
# Module to prepend to Mysql2::Client for instrumentation
16+
module Client
17+
def query(sql, options = {})
18+
tracer.in_span(
19+
_otel_span_name(sql),
20+
attributes: _otel_span_attributes(sql),
21+
kind: :client
22+
) do
23+
super
24+
end
25+
end
26+
27+
def prepare(sql)
28+
tracer.in_span(
29+
_otel_span_name(sql),
30+
attributes: _otel_span_attributes(sql),
31+
kind: :client
32+
) do
33+
super
34+
end
35+
end
36+
37+
private
38+
39+
def _otel_span_name(sql)
40+
OpenTelemetry::Helpers::MySQL.database_span_name(
41+
sql,
42+
OpenTelemetry::Instrumentation::Mysql2.attributes[
43+
SemanticConventions::Trace::DB_OPERATION
44+
],
45+
_otel_database_name,
46+
config
47+
)
48+
end
49+
50+
def _otel_span_attributes(sql)
51+
attributes = _otel_client_attributes
52+
case config[:db_statement]
53+
when :include
54+
attributes[SemanticConventions::Trace::DB_STATEMENT] = sql
55+
when :obfuscate
56+
attributes[SemanticConventions::Trace::DB_STATEMENT] =
57+
OpenTelemetry::Helpers::SqlObfuscation.obfuscate_sql(
58+
sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql
59+
)
60+
end
61+
62+
attributes.merge!(OpenTelemetry::Instrumentation::Mysql2.attributes)
63+
attributes.compact!
64+
attributes
65+
end
66+
67+
def _otel_database_name
68+
# https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L78
69+
(query_options[:database] || query_options[:dbname] || query_options[:db])&.to_s
70+
end
71+
72+
def _otel_client_attributes
73+
# The client specific attributes can be found via the query_options instance variable
74+
# exposed on the mysql2 Client
75+
# https://github.com/brianmario/mysql2/blob/ca08712c6c8ea672df658bb25b931fea22555f27/lib/mysql2/client.rb#L25-L26
76+
host = (query_options[:host] || query_options[:hostname]).to_s
77+
port = query_options[:port].to_s
78+
79+
attributes = {
80+
SemanticConventions::Trace::DB_SYSTEM => 'mysql',
81+
SemanticConventions::Trace::NET_PEER_NAME => host,
82+
SemanticConventions::Trace::NET_PEER_PORT => port
83+
}
84+
85+
attributes[SemanticConventions::Trace::DB_NAME] = _otel_database_name
86+
attributes[SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service]
87+
attributes
88+
end
89+
90+
def tracer
91+
Mysql2::Instrumentation.instance.tracer
92+
end
93+
94+
def config
95+
Mysql2::Instrumentation.instance.config
96+
end
97+
end
98+
end
99+
end
100+
end
101+
end
102+
end

0 commit comments

Comments
 (0)