opentelemetry-instrumentation-trilogy 0.68.0 → 0.69.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: ca36bf926d9b8424c449d8752ec6639e1686ca6730d9c8f08c7b739ccdd970c1
4
- data.tar.gz: 5d89e6a9fdc07871f156f66d19fb9aa28b4fa7dd7621d95f64fd734aac385431
3
+ metadata.gz: 61673a70660a205354946b86bedb7ee5a3aa2cfd7af0aebab52b3c10e80b8c63
4
+ data.tar.gz: 6db4aa4e8c9cf0b62093d39b8e71a27f66735702271ac33426a755fce2240bd9
5
5
  SHA512:
6
- metadata.gz: ab0eec895a37c79f72f49321fcce1836e8debd6245a67ed65a2a5f1a13e52310c61b28134e06689e690dfa1b9c5e52517082b42e544794b957e181e7c70a5ec8
7
- data.tar.gz: b7e16175e4843890dac1662555cb9fcff7150fcfccea9c5e207f853b679dde127a0036927c44c7e1033c32e7cb24f19c2079d7717a316c75be7d30ca8c07d082
6
+ metadata.gz: 216d40455f51acf894bb5aecf79abc6050d972598509b19e0356ce1c01bef1c57da6f12045d2be745ffc9411ef449817a594bd312aa01ee357b35f0836c7a84e
7
+ data.tar.gz: d5b67b6383b4a21e9932ef6123d617a92d8f13763c6df1163ae749106503e4667a17329ff7213e8baa7eee3909e7bb5679392045a407978fdc3472376e0463cd
data/CHANGELOG.md CHANGED
@@ -1,5 +1,9 @@
1
1
  # Release History: opentelemetry-instrumentation-trilogy
2
2
 
3
+ ## v0.69.0 / 2026-05-21
4
+
5
+ - ADDED: Add `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable support for span attributes (#2095)
6
+
3
7
  ## v0.68.0 / 2026-04-14
4
8
 
5
9
  - BREAKING CHANGE: Min Ruby Version 3.3 (#2125)
data/README.md CHANGED
@@ -51,18 +51,53 @@ OpenTelemetry::Instrumentation::Trilogy.with_attributes('pizzatoppings' => 'mush
51
51
  end
52
52
  ```
53
53
 
54
+ ## Compatibility
55
+
56
+ This gem requires Trilogy 2.11 or higher and will not work with a future Trilogy 3.x release.
57
+
58
+ ## Configuration Options
59
+
60
+ | Option | Default | Description |
61
+ | ------ | ------- | ----------- |
62
+ | `db_statement` | `:obfuscate` | Controls how SQL queries appear in spans. `:obfuscate` replaces literal values with `?`, `:include` records the raw SQL, `:omit` excludes the attribute entirely. |
63
+ | `obfuscation_limit` | `2000` | Maximum length of the obfuscated SQL statement. Statements exceeding this limit are truncated. |
64
+ | `peer_service` | `nil` | Deprecated with no replacement. Sets the `peer.service` attribute on spans (old semantic conventions only). |
65
+ | `propagator` | `'none'` | Propagator for injecting trace context into SQL comments. `'none'` disables propagation, `'tracecontext'` uses W3C Trace Context, `'vitess'` uses Vitess-style propagation (requires `opentelemetry-propagator-vitess` gem). |
66
+ | `record_exception` | `true` | Records exceptions as span events when an error occurs. |
67
+ | `span_name` | `:statement_type` | Controls span naming (old semantic conventions only). `:statement_type` uses the SQL operation (e.g., `SELECT`), `:db_name` uses the database name, `:db_operation_and_name` combines both. |
68
+
54
69
  ## Semantic Conventions
55
70
 
56
- This instrumentation generally uses [Database semantic conventions](https://opentelemetry.io/docs/specs/semconv/database/database-spans/).
71
+ This instrumentation generally uses [Database semantic conventions](https://opentelemetry.io/docs/specs/semconv/database/database-spans/). See the [Database semantic convention stability](#database-semantic-convention-stability) section for how to switch between stable and old conventions.
72
+
73
+ | Stable Attribute Name | Old Attribute Name | Type | Notes |
74
+ | - | - | - | - |
75
+ | `db.namespace` | `db.name` | String | Database name from connection_options |
76
+ | `db.query.text` | `db.statement` | String | The database query being executed; set according to the `db_statement` config option |
77
+ | `db.response.status_code` | — | String | The Trilogy error code, if available |
78
+ | `db.system.name` | `db.system` | String | DBMS product identifier; always `mysql` |
79
+ | `error.type` | — | String | The exception class name when the operation fails |
80
+ | `server.address` | `net.peer.name` | String | Database host from connection_options |
81
+ | `server.port` | — | Integer | Database port from connection_options |
82
+ | — | `db.instance.id` | String | Connected host, e.g. result of `SELECT @@hostname` |
83
+ | — | `db.user` | String | Database username from connection_options |
84
+ | — | `peer.service` | String | Configured via the `peer_service` config option |
85
+
86
+ ## Database semantic convention stability
87
+
88
+ In the OpenTelemetry ecosystem, database semantic conventions have now reached a stable state. However, the initial Trilogy instrumentation was introduced before this stability was achieved, which resulted in database attributes being based on an older version of the semantic conventions.
89
+
90
+ To facilitate the migration to stable semantic conventions, you can use the `OTEL_SEMCONV_STABILITY_OPT_IN` environment variable. This variable allows you to opt-in to the new stable conventions, ensuring compatibility and future-proofing your instrumentation.
91
+
92
+ When setting the value for `OTEL_SEMCONV_STABILITY_OPT_IN`, you can specify which conventions you wish to adopt:
93
+
94
+ - `database` - Emits the stable database and networking conventions and ceases emitting the old conventions previously emitted by the instrumentation.
95
+ - `database/dup` - Emits both the old and stable database and networking conventions, enabling a phased rollout of the stable semantic conventions.
96
+ - Default behavior (in the absence of either value) is to continue emitting the old database and networking conventions the instrumentation previously emitted.
97
+
98
+ During the transition from old to stable conventions, Trilogy instrumentation code comes in three patch versions: `dup`, `old`, and `stable`. These versions are identical except for the attributes they send. Any changes to Trilogy instrumentation should consider all three patches.
57
99
 
58
- | Attribute Name | Type | Notes |
59
- | - | - | - |
60
- | `db.instance.id` | String | The name of the DB host executing the query e.g. `SELECT @@hostname` |
61
- | `db.name` | String | The name of the database from connection_options |
62
- | `db.statement` | String | SQL statement being executed |
63
- | `db.user` | String | The username from connection_options |
64
- | `db.system` | String | `mysql` |
65
- | `net.peer.name` | String | The name of the remote host from connection_options |
100
+ For additional information on migration, please refer to our [documentation](https://opentelemetry.io/docs/specs/semconv/non-normative/db-migration/).
66
101
 
67
102
  ## How can I get involved?
68
103
 
@@ -7,7 +7,70 @@
7
7
  module OpenTelemetry
8
8
  module Instrumentation
9
9
  module Trilogy
10
- # The Instrumentation class contains logic to detect and install the Trilogy instrumentation
10
+ # The {OpenTelemetry::Instrumentation::Trilogy::Instrumentation} class contains logic to detect and install the Trilogy instrumentation
11
+ #
12
+ # Installation and configuration of this instrumentation is done within the
13
+ # {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry/SDK#configure-instance_method OpenTelemetry::SDK#configure}
14
+ # block, calling {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry%2FSDK%2FConfigurator:use use()}
15
+ # or {https://www.rubydoc.info/gems/opentelemetry-sdk/OpenTelemetry%2FSDK%2FConfigurator:use_all use_all()}.
16
+ #
17
+ # ## Configuration keys and options
18
+ #
19
+ # ### `:db_statement`
20
+ #
21
+ # Controls how SQL queries appear in spans.
22
+ #
23
+ # - `:obfuscate` **(default)** - Replaces literal values with `?` to prevent
24
+ # sensitive data from being recorded.
25
+ # - `:include` - Records the raw SQL query as-is.
26
+ # - `:omit` - Excludes the SQL query attribute entirely.
27
+ #
28
+ # ### `:obfuscation_limit`
29
+ #
30
+ # Maximum length of the obfuscated SQL statement. Statements exceeding this limit
31
+ # are truncated. Default is `2000`.
32
+ #
33
+ # ### `:peer_service`
34
+ #
35
+ # Sets the `peer.service` attribute on spans. Default is `nil`.
36
+ # Only applies when using old semantic conventions. Deprecated with no replacement.
37
+ #
38
+ # ### `:propagator`
39
+ #
40
+ # Propagator for injecting trace context into SQL comments.
41
+ #
42
+ # - `'none'` **(default)** - Disables trace context propagation.
43
+ # - `'tracecontext'` - Uses W3C Trace Context format via SQL comments.
44
+ # - `'vitess'` - Uses Vitess-style propagation. Requires the
45
+ # `opentelemetry-propagator-vitess` gem.
46
+ #
47
+ # ### `:record_exception`
48
+ #
49
+ # Records exceptions as span events when an error occurs. Default is `true`.
50
+ #
51
+ # ### `:span_name`
52
+ #
53
+ # Controls how span names are generated. Only applies when using old semantic
54
+ # conventions; ignored for stable semantic conventions.
55
+ #
56
+ # - `:statement_type` **(default)** - Uses the SQL operation (e.g., `SELECT`).
57
+ # - `:db_name` - Uses the database name.
58
+ # - `:db_operation_and_name` - Combines the operation and database name.
59
+ #
60
+ # @example An explicit default configuration
61
+ # OpenTelemetry::SDK.configure do |c|
62
+ # c.use_all({
63
+ # 'OpenTelemetry::Instrumentation::Trilogy' => {
64
+ # db_statement: :obfuscate,
65
+ # obfuscation_limit: 2000,
66
+ # peer_service: nil,
67
+ # propagator: 'none',
68
+ # record_exception: true,
69
+ # span_name: :statement_type,
70
+ # },
71
+ # })
72
+ # end
73
+ #
11
74
  class Instrumentation < OpenTelemetry::Instrumentation::Base
12
75
  install do |config|
13
76
  require_dependencies
@@ -20,7 +83,7 @@ module OpenTelemetry
20
83
  end
21
84
 
22
85
  compatible do
23
- Gem::Requirement.create('>= 2.3', '< 3.0').satisfied_by?(Gem::Version.new(::Trilogy::VERSION))
86
+ Gem::Requirement.create('>= 2.11', '< 3.0').satisfied_by?(Gem::Version.new(::Trilogy::VERSION))
24
87
  end
25
88
 
26
89
  option :peer_service, default: nil, validate: :string
@@ -30,16 +93,47 @@ module OpenTelemetry
30
93
  option :propagator, default: 'none', validate: %w[none tracecontext vitess]
31
94
  option :record_exception, default: true, validate: :boolean
32
95
 
33
- attr_reader :propagator
96
+ attr_reader :propagator, :semconv
34
97
 
35
98
  private
36
99
 
37
100
  def require_dependencies
38
- require_relative 'patches/client'
101
+ @semconv = determine_semconv
102
+
103
+ case @semconv
104
+ when :old
105
+ require_relative 'patches/old/client'
106
+ when :stable
107
+ require_relative 'patches/stable/client'
108
+ when :dup
109
+ require_relative 'patches/dup/client'
110
+ end
39
111
  end
40
112
 
41
113
  def patch_client
42
- ::Trilogy.prepend(Patches::Client)
114
+ case @semconv
115
+ when :old
116
+ ::Trilogy.prepend(Patches::Old::Client)
117
+ when :stable
118
+ ::Trilogy.prepend(Patches::Stable::Client)
119
+ when :dup
120
+ ::Trilogy.prepend(Patches::Dup::Client)
121
+ end
122
+ end
123
+
124
+ def determine_semconv
125
+ opt_in = ENV.fetch('OTEL_SEMCONV_STABILITY_OPT_IN', nil)
126
+ return :old if opt_in.nil?
127
+
128
+ opt_in_values = opt_in.split(',').map(&:strip)
129
+
130
+ if opt_in_values.include?('database/dup')
131
+ :dup
132
+ elsif opt_in_values.include?('database')
133
+ :stable
134
+ else
135
+ :old
136
+ end
43
137
  end
44
138
 
45
139
  def configure_propagator(config)
@@ -0,0 +1,157 @@
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-processor'
9
+
10
+ module OpenTelemetry
11
+ module Instrumentation
12
+ module Trilogy
13
+ module Patches
14
+ module Dup
15
+ # Module to prepend to Trilogy for instrumentation (emits both old and stable semantic conventions)
16
+ module Client
17
+ def initialize(options = {})
18
+ @connection_options = options # This is normally done by Trilogy#initialize
19
+ @_otel_database_name = connection_options&.dig(:database)
20
+ @_otel_base_attributes = _build_otel_base_attributes.freeze
21
+
22
+ tracer.in_span(
23
+ 'connect',
24
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
25
+ kind: :client,
26
+ record_exception: config[:record_exception]
27
+ ) do |span|
28
+ super
29
+ rescue StandardError => e
30
+ set_error_attributes(span, e)
31
+ raise
32
+ end
33
+ end
34
+
35
+ def ping(...)
36
+ tracer.in_span(
37
+ 'ping',
38
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
39
+ kind: :client,
40
+ record_exception: config[:record_exception]
41
+ ) do |span|
42
+ super
43
+ rescue StandardError => e
44
+ set_error_attributes(span, e)
45
+ raise
46
+ end
47
+ end
48
+
49
+ def query(sql)
50
+ context_attributes = OpenTelemetry::Instrumentation::Trilogy.attributes
51
+
52
+ tracer.in_span(
53
+ OpenTelemetry::Helpers::MySQL.database_span_name(
54
+ sql,
55
+ context_attributes[OpenTelemetry::SemanticConventions::Trace::DB_OPERATION],
56
+ @_otel_database_name,
57
+ config
58
+ ),
59
+ attributes: client_attributes(sql).merge!(context_attributes),
60
+ kind: :client,
61
+ record_exception: config[:record_exception]
62
+ ) do |span, context|
63
+ if propagator && sql.frozen?
64
+ sql = +sql
65
+ propagator.inject(sql, context: context)
66
+ sql.freeze
67
+ elsif propagator
68
+ propagator.inject(sql, context: context)
69
+ end
70
+
71
+ super
72
+ rescue StandardError => e
73
+ set_error_attributes(span, e)
74
+ raise
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def _build_otel_base_attributes
81
+ database_user = connection_options&.dig(:username)
82
+ mysql_host = connection_options&.fetch(:host, nil) || 'unknown sock'
83
+ mysql_port = connection_options&.dig(:port)
84
+
85
+ # Include both old and stable attributes
86
+ attributes = {
87
+ # Old conventions
88
+ ::OpenTelemetry::SemanticConventions::Trace::DB_SYSTEM => 'mysql',
89
+ ::OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => mysql_host,
90
+ # Stable conventions
91
+ 'db.system.name' => 'mysql',
92
+ 'server.address' => mysql_host
93
+ }
94
+
95
+ attributes['server.port'] = mysql_port if mysql_port
96
+
97
+ # Database name (old: db.name, stable: db.namespace)
98
+ if @_otel_database_name
99
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_NAME] = @_otel_database_name
100
+ attributes['db.namespace'] = @_otel_database_name
101
+ end
102
+
103
+ # db.user (old only - removed in stable)
104
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_USER] = database_user if database_user
105
+
106
+ # peer.service (old only - not stable and not a db attribute)
107
+ attributes[::OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] unless config[:peer_service].nil?
108
+ attributes
109
+ end
110
+
111
+ def client_attributes(sql = nil)
112
+ attributes = @_otel_base_attributes.dup
113
+
114
+ # Old convention
115
+ attributes['db.instance.id'] = @connected_host unless @connected_host.nil?
116
+
117
+ if sql
118
+ case config[:db_statement]
119
+ when :obfuscate
120
+ obfuscated = OpenTelemetry::Helpers::SqlProcessor.obfuscate_sql(sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql)
121
+ # Old convention
122
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = obfuscated
123
+ # Stable convention
124
+ attributes['db.query.text'] = obfuscated
125
+ when :include
126
+ # Old convention
127
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql
128
+ # Stable convention
129
+ attributes['db.query.text'] = sql
130
+ end
131
+ end
132
+
133
+ attributes
134
+ end
135
+
136
+ def set_error_attributes(span, error)
137
+ span.set_attribute('error.type', error.class.name)
138
+ span.set_attribute('db.response.status_code', error.error_code.to_s) if error.respond_to?(:error_code) && error.error_code
139
+ end
140
+
141
+ def tracer
142
+ Trilogy::Instrumentation.instance.tracer
143
+ end
144
+
145
+ def config
146
+ Trilogy::Instrumentation.instance.config
147
+ end
148
+
149
+ def propagator
150
+ Trilogy::Instrumentation.instance.propagator
151
+ end
152
+ end
153
+ end
154
+ end
155
+ end
156
+ end
157
+ end
@@ -0,0 +1,119 @@
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-processor'
9
+
10
+ module OpenTelemetry
11
+ module Instrumentation
12
+ module Trilogy
13
+ module Patches
14
+ module Old
15
+ # Module to prepend to Trilogy for instrumentation (old semantic conventions)
16
+ module Client
17
+ def initialize(options = {})
18
+ @connection_options = options # This is normally done by Trilogy#initialize
19
+ @_otel_database_name = connection_options&.dig(:database)
20
+ @_otel_base_attributes = _build_otel_base_attributes.freeze
21
+
22
+ tracer.in_span(
23
+ 'connect',
24
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
25
+ kind: :client,
26
+ record_exception: config[:record_exception]
27
+ ) do
28
+ super
29
+ end
30
+ end
31
+
32
+ def ping(...)
33
+ tracer.in_span(
34
+ 'ping',
35
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
36
+ kind: :client,
37
+ record_exception: config[:record_exception]
38
+ ) do
39
+ super
40
+ end
41
+ end
42
+
43
+ def query(sql)
44
+ context_attributes = OpenTelemetry::Instrumentation::Trilogy.attributes
45
+
46
+ tracer.in_span(
47
+ OpenTelemetry::Helpers::MySQL.database_span_name(
48
+ sql,
49
+ context_attributes[OpenTelemetry::SemanticConventions::Trace::DB_OPERATION],
50
+ @_otel_database_name,
51
+ config
52
+ ),
53
+ attributes: client_attributes(sql).merge!(context_attributes),
54
+ kind: :client,
55
+ record_exception: config[:record_exception]
56
+ ) do |_span, context|
57
+ if propagator && sql.frozen?
58
+ sql = +sql
59
+ propagator.inject(sql, context: context)
60
+ sql.freeze
61
+ elsif propagator
62
+ propagator.inject(sql, context: context)
63
+ end
64
+
65
+ super
66
+ end
67
+ end
68
+
69
+ private
70
+
71
+ def _build_otel_base_attributes
72
+ database_user = connection_options&.dig(:username)
73
+
74
+ attributes = {
75
+ ::OpenTelemetry::SemanticConventions::Trace::DB_SYSTEM => 'mysql',
76
+ ::OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => connection_options&.fetch(:host, 'unknown sock') || 'unknown sock'
77
+ }
78
+
79
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_NAME] = @_otel_database_name if @_otel_database_name
80
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_USER] = database_user if database_user
81
+ attributes[::OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] unless config[:peer_service].nil?
82
+ attributes
83
+ end
84
+
85
+ def client_attributes(sql = nil)
86
+ attributes = @_otel_base_attributes.dup
87
+
88
+ attributes['db.instance.id'] = @connected_host unless @connected_host.nil?
89
+
90
+ if sql
91
+ case config[:db_statement]
92
+ when :obfuscate
93
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] =
94
+ OpenTelemetry::Helpers::SqlProcessor.obfuscate_sql(sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql)
95
+ when :include
96
+ attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql
97
+ end
98
+ end
99
+
100
+ attributes
101
+ end
102
+
103
+ def tracer
104
+ Trilogy::Instrumentation.instance.tracer
105
+ end
106
+
107
+ def config
108
+ Trilogy::Instrumentation.instance.config
109
+ end
110
+
111
+ def propagator
112
+ Trilogy::Instrumentation.instance.propagator
113
+ end
114
+ end
115
+ end
116
+ end
117
+ end
118
+ end
119
+ end
@@ -0,0 +1,132 @@
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-processor'
9
+
10
+ module OpenTelemetry
11
+ module Instrumentation
12
+ module Trilogy
13
+ module Patches
14
+ module Stable
15
+ # Module to prepend to Trilogy for instrumentation (stable semantic conventions)
16
+ module Client
17
+ def initialize(options = {})
18
+ @connection_options = options # This is normally done by Trilogy#initialize
19
+ @_otel_database_name = connection_options&.dig(:database)
20
+ @_otel_base_attributes = _build_otel_base_attributes.freeze
21
+
22
+ tracer.in_span(
23
+ 'connect',
24
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
25
+ kind: :client,
26
+ record_exception: config[:record_exception]
27
+ ) do |span|
28
+ super
29
+ rescue StandardError => e
30
+ set_error_attributes(span, e)
31
+ raise
32
+ end
33
+ end
34
+
35
+ def ping(...)
36
+ tracer.in_span(
37
+ 'ping',
38
+ attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
39
+ kind: :client,
40
+ record_exception: config[:record_exception]
41
+ ) do |span|
42
+ super
43
+ rescue StandardError => e
44
+ set_error_attributes(span, e)
45
+ raise
46
+ end
47
+ end
48
+
49
+ def query(sql)
50
+ context_attributes = OpenTelemetry::Instrumentation::Trilogy.attributes
51
+
52
+ tracer.in_span(
53
+ OpenTelemetry::Helpers::MySQL.database_span_name(
54
+ sql,
55
+ context_attributes[OpenTelemetry::SemanticConventions::Trace::DB_OPERATION],
56
+ @_otel_database_name,
57
+ config
58
+ ),
59
+ attributes: client_attributes(sql).merge!(context_attributes),
60
+ kind: :client,
61
+ record_exception: config[:record_exception]
62
+ ) do |span, context|
63
+ if propagator && sql.frozen?
64
+ sql = +sql
65
+ propagator.inject(sql, context: context)
66
+ sql.freeze
67
+ elsif propagator
68
+ propagator.inject(sql, context: context)
69
+ end
70
+
71
+ super
72
+ rescue StandardError => e
73
+ set_error_attributes(span, e)
74
+ raise
75
+ end
76
+ end
77
+
78
+ private
79
+
80
+ def _build_otel_base_attributes
81
+ mysql_host = connection_options&.fetch(:host, nil) || 'unknown sock'
82
+ mysql_port = connection_options&.dig(:port)
83
+
84
+ attributes = {
85
+ 'db.system.name' => 'mysql',
86
+ 'server.address' => mysql_host
87
+ }
88
+
89
+ attributes['server.port'] = mysql_port if mysql_port
90
+
91
+ attributes['db.namespace'] = @_otel_database_name if @_otel_database_name
92
+ attributes
93
+ end
94
+
95
+ def client_attributes(sql = nil)
96
+ attributes = @_otel_base_attributes.dup
97
+
98
+ if sql
99
+ case config[:db_statement]
100
+ when :obfuscate
101
+ attributes['db.query.text'] =
102
+ OpenTelemetry::Helpers::SqlProcessor.obfuscate_sql(sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql)
103
+ when :include
104
+ attributes['db.query.text'] = sql
105
+ end
106
+ end
107
+
108
+ attributes
109
+ end
110
+
111
+ def set_error_attributes(span, error)
112
+ span.set_attribute('error.type', error.class.name)
113
+ span.set_attribute('db.response.status_code', error.error_code.to_s) if error.respond_to?(:error_code) && error.error_code
114
+ end
115
+
116
+ def tracer
117
+ Trilogy::Instrumentation.instance.tracer
118
+ end
119
+
120
+ def config
121
+ Trilogy::Instrumentation.instance.config
122
+ end
123
+
124
+ def propagator
125
+ Trilogy::Instrumentation.instance.propagator
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -7,7 +7,7 @@
7
7
  module OpenTelemetry
8
8
  module Instrumentation
9
9
  module Trilogy
10
- VERSION = '0.68.0'
10
+ VERSION = '0.69.0'
11
11
  end
12
12
  end
13
13
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: opentelemetry-instrumentation-trilogy
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.68.0
4
+ version: 0.69.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - OpenTelemetry Authors
@@ -94,16 +94,18 @@ files:
94
94
  - lib/opentelemetry/instrumentation.rb
95
95
  - lib/opentelemetry/instrumentation/trilogy.rb
96
96
  - lib/opentelemetry/instrumentation/trilogy/instrumentation.rb
97
- - lib/opentelemetry/instrumentation/trilogy/patches/client.rb
97
+ - lib/opentelemetry/instrumentation/trilogy/patches/dup/client.rb
98
+ - lib/opentelemetry/instrumentation/trilogy/patches/old/client.rb
99
+ - lib/opentelemetry/instrumentation/trilogy/patches/stable/client.rb
98
100
  - lib/opentelemetry/instrumentation/trilogy/version.rb
99
101
  homepage: https://github.com/open-telemetry/opentelemetry-ruby-contrib
100
102
  licenses:
101
103
  - Apache-2.0
102
104
  metadata:
103
- changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-trilogy/0.68.0/file/CHANGELOG.md
104
- source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/opentelemetry-instrumentation-trilogy/v0.68.0/instrumentation/trilogy
105
+ changelog_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-trilogy/0.69.0/file/CHANGELOG.md
106
+ source_code_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/tree/opentelemetry-instrumentation-trilogy/v0.69.0/instrumentation/trilogy
105
107
  bug_tracker_uri: https://github.com/open-telemetry/opentelemetry-ruby-contrib/issues
106
- documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-trilogy/0.68.0
108
+ documentation_uri: https://rubydoc.info/gems/opentelemetry-instrumentation-trilogy/0.69.0
107
109
  rdoc_options: []
108
110
  require_paths:
109
111
  - lib
@@ -1,117 +0,0 @@
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-processor'
9
-
10
- module OpenTelemetry
11
- module Instrumentation
12
- module Trilogy
13
- module Patches
14
- # Module to prepend to Trilogy for instrumentation
15
- module Client
16
- def initialize(options = {})
17
- @connection_options = options # This is normally done by Trilogy#initialize
18
- @_otel_database_name = connection_options&.dig(:database)
19
- @_otel_base_attributes = _build_otel_base_attributes.freeze
20
-
21
- tracer.in_span(
22
- 'connect',
23
- attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
24
- kind: :client,
25
- record_exception: config[:record_exception]
26
- ) do
27
- super
28
- end
29
- end
30
-
31
- def ping(...)
32
- tracer.in_span(
33
- 'ping',
34
- attributes: client_attributes.merge!(OpenTelemetry::Instrumentation::Trilogy.attributes),
35
- kind: :client,
36
- record_exception: config[:record_exception]
37
- ) do
38
- super
39
- end
40
- end
41
-
42
- def query(sql)
43
- context_attributes = OpenTelemetry::Instrumentation::Trilogy.attributes
44
-
45
- tracer.in_span(
46
- OpenTelemetry::Helpers::MySQL.database_span_name(
47
- sql,
48
- context_attributes[OpenTelemetry::SemanticConventions::Trace::DB_OPERATION],
49
- @_otel_database_name,
50
- config
51
- ),
52
- attributes: client_attributes(sql).merge!(context_attributes),
53
- kind: :client,
54
- record_exception: config[:record_exception]
55
- ) do |_span, context|
56
- if propagator && sql.frozen?
57
- sql = +sql
58
- propagator.inject(sql, context: context)
59
- sql.freeze
60
- elsif propagator
61
- propagator.inject(sql, context: context)
62
- end
63
-
64
- super
65
- end
66
- end
67
-
68
- private
69
-
70
- def _build_otel_base_attributes
71
- database_user = connection_options&.dig(:username)
72
-
73
- attributes = {
74
- ::OpenTelemetry::SemanticConventions::Trace::DB_SYSTEM => 'mysql',
75
- ::OpenTelemetry::SemanticConventions::Trace::NET_PEER_NAME => connection_options&.fetch(:host, 'unknown sock') || 'unknown sock'
76
- }
77
-
78
- attributes[::OpenTelemetry::SemanticConventions::Trace::DB_NAME] = @_otel_database_name if @_otel_database_name
79
- attributes[::OpenTelemetry::SemanticConventions::Trace::DB_USER] = database_user if database_user
80
- attributes[::OpenTelemetry::SemanticConventions::Trace::PEER_SERVICE] = config[:peer_service] unless config[:peer_service].nil?
81
- attributes
82
- end
83
-
84
- def client_attributes(sql = nil)
85
- attributes = @_otel_base_attributes.dup
86
-
87
- attributes['db.instance.id'] = @connected_host unless @connected_host.nil?
88
-
89
- if sql
90
- case config[:db_statement]
91
- when :obfuscate
92
- attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] =
93
- OpenTelemetry::Helpers::SqlProcessor.obfuscate_sql(sql, obfuscation_limit: config[:obfuscation_limit], adapter: :mysql)
94
- when :include
95
- attributes[::OpenTelemetry::SemanticConventions::Trace::DB_STATEMENT] = sql
96
- end
97
- end
98
-
99
- attributes
100
- end
101
-
102
- def tracer
103
- Trilogy::Instrumentation.instance.tracer
104
- end
105
-
106
- def config
107
- Trilogy::Instrumentation.instance.config
108
- end
109
-
110
- def propagator
111
- Trilogy::Instrumentation.instance.propagator
112
- end
113
- end
114
- end
115
- end
116
- end
117
- end