aws_advanced_ruby_driver_wrapper 1.0.0 → 1.1.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 +4 -4
- data/CHANGELOG.md +48 -2
- data/README.md +115 -6
- data/THIRD-PARTY-LICENSES +70 -11
- data/aws_advanced_ruby_driver_wrapper.gemspec +9 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_action_cable_postgresql_support.rb +40 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_connection_handler.rb +47 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_mysql2_adapter.rb +23 -9
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_postgresql_adapter.rb +65 -10
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/aws_trilogy_adapter.rb +80 -0
- data/lib/aws_advanced_ruby_driver_wrapper/active_record/type_adapter_alias.rb +61 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect.rb +48 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/driver_dialect_manager.rb +11 -4
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql2_driver_dialect.rb +129 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/mysql_driver_dialect.rb +9 -81
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/pg_driver_dialect.rb +28 -0
- data/lib/aws_advanced_ruby_driver_wrapper/driver_dialects/trilogy_driver_dialect.rb +118 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/error_handler.rb +16 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors/mysql_error_handler.rb +10 -5
- data/lib/aws_advanced_ruby_driver_wrapper/errors/trilogy_error_handler.rb +127 -0
- data/lib/aws_advanced_ruby_driver_wrapper/errors.rb +1 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/cluster_topology_monitor.rb +11 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor.rb +14 -0
- data/lib/aws_advanced_ruby_driver_wrapper/monitoring/monitor_connection.rb +6 -0
- data/lib/aws_advanced_ruby_driver_wrapper/mysql.rb +27 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/blue_green_plugin.rb +125 -7
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/drop_blue_connections_marker.rb +84 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/host_mapper.rb +3 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/base_routing.rb +7 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb +68 -41
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb +4 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb +5 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_until_corresponding_host_found_connect_routing.rb +7 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_builder.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_monitor.rb +10 -13
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/status_provider.rb +95 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb +11 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/default_plugin.rb +14 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/failover_plugin.rb +68 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/base_saml_auth_plugin.rb +266 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/federated_auth_plugin.rb +134 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/federated_auth/okta_auth_plugin.rb +113 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/gdb/gdb_failover_plugin.rb +30 -9
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/iam_auth_plugin.rb +16 -2
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/initial_connection_strategy_plugin.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_management_utility.rb +6 -3
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/key_manager.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/kms_encryption_plugin.rb +29 -6
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_mysql.sql +108 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/kms_encryption/sql/trigger_pg.sql +54 -0
- data/lib/aws_advanced_ruby_driver_wrapper/plugins/secrets_manager_plugin.rb +23 -1
- data/lib/aws_advanced_ruby_driver_wrapper/postgresql.rb +49 -23
- data/lib/aws_advanced_ruby_driver_wrapper/property_definition.rb +63 -1
- data/lib/aws_advanced_ruby_driver_wrapper/ruby_method.rb +3 -0
- data/lib/aws_advanced_ruby_driver_wrapper/services/dialect_service.rb +20 -7
- data/lib/aws_advanced_ruby_driver_wrapper/services/host_service.rb +34 -8
- data/lib/aws_advanced_ruby_driver_wrapper/services/monitor_service.rb +23 -4
- data/lib/aws_advanced_ruby_driver_wrapper/services/plugin_manager.rb +80 -29
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_container.rb +10 -2
- data/lib/aws_advanced_ruby_driver_wrapper/services/service_utility.rb +4 -1
- data/lib/aws_advanced_ruby_driver_wrapper/trilogy.rb +167 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/connection_config_parser.rb +25 -15
- data/lib/aws_advanced_ruby_driver_wrapper/utils/events/batching_event_publisher.rb +18 -7
- data/lib/aws_advanced_ruby_driver_wrapper/utils/global_aurora_topology_utils.rb +2 -2
- data/lib/aws_advanced_ruby_driver_wrapper/utils/iam_auth_utils.rb +13 -4
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/encryption_annotation_parser.rb +15 -31
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_statement_analyzer.rb +55 -76
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/mysql_text.rb +215 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/pg_statement_analyzer.rb +11 -20
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/query_analysis.rb +2 -3
- data/lib/aws_advanced_ruby_driver_wrapper/utils/parser/sql_parser.rb +21 -14
- data/lib/aws_advanced_ruby_driver_wrapper/utils/retry_util.rb +2 -1
- data/lib/aws_advanced_ruby_driver_wrapper/utils/saml_utils.rb +133 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/storage/storage_service.rb +29 -8
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/null_telemetry.rb +89 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_context.rb +124 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/{ar_constants.rb → telemetry/open_telemetry_counter.rb} +19 -5
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_factory.rb +122 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/open_telemetry_gauge.rb +36 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_const.rb +50 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/telemetry/telemetry_factory.rb +143 -0
- data/lib/aws_advanced_ruby_driver_wrapper/utils/topology_utils.rb +9 -2
- data/lib/aws_advanced_ruby_driver_wrapper/version.rb +1 -1
- data/lib/aws_advanced_ruby_driver_wrapper.rb +47 -2
- metadata +57 -3
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
# Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
|
|
4
|
+
#
|
|
5
|
+
# Licensed under the Apache License, Version 2.0 (the "License").
|
|
6
|
+
# You may not use this file except in compliance with the License.
|
|
7
|
+
# You may obtain a copy of the License at
|
|
8
|
+
#
|
|
9
|
+
# http://www.apache.org/licenses/LICENSE-2.0
|
|
10
|
+
#
|
|
11
|
+
# Unless required by applicable law or agreed to in writing, software
|
|
12
|
+
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
13
|
+
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
14
|
+
# See the License for the specific language governing permissions and
|
|
15
|
+
# limitations under the License.
|
|
16
|
+
|
|
17
|
+
require 'securerandom'
|
|
18
|
+
|
|
19
|
+
module AwsAdvancedRubyDriverWrapper
|
|
20
|
+
module Plugins
|
|
21
|
+
module BlueGreen
|
|
22
|
+
# Records that a Blue/Green switchover is retiring the blue environment, so that connections
|
|
23
|
+
# opened to blue before the switchover can be invalidated the next time they are used.
|
|
24
|
+
#
|
|
25
|
+
# Ruby cannot safely abort a connection from another thread, so instead of dropping blue connections
|
|
26
|
+
# from the monitor thread, each connection checks this marker on its own thread the next time it is
|
|
27
|
+
# used. See the +bg_drop_blue_connections+ property and BlueGreenPlugin#execute.
|
|
28
|
+
#
|
|
29
|
+
# A marker is immutable. It becomes +pending+ when the switchover reaches IN_PROGRESS and is
|
|
30
|
+
# replaced by an +active+ copy (see #activated) once the switchover is confirmed by POST or
|
|
31
|
+
# COMPLETED. It is cleared on rollback.
|
|
32
|
+
class DropBlueConnectionsMarker
|
|
33
|
+
# @return [String] a unique identity for this switchover's marker, so a connection can tell
|
|
34
|
+
# whether it has already been checked against it.
|
|
35
|
+
attr_reader :id
|
|
36
|
+
|
|
37
|
+
# @return [Integer] monotonic time (nanoseconds) at which the switchover reached IN_PROGRESS.
|
|
38
|
+
attr_reader :switchover_time_ns
|
|
39
|
+
|
|
40
|
+
# @return [Set<String>] the blue host set: downcased cluster and instance endpoint names plus
|
|
41
|
+
# their pre-switchover IP addresses.
|
|
42
|
+
attr_reader :blue_hosts
|
|
43
|
+
|
|
44
|
+
# @param blue_hosts [Enumerable<String>] blue endpoint names and their pre-switchover IPs
|
|
45
|
+
# @param switchover_time_ns [Integer] monotonic time the switchover reached IN_PROGRESS
|
|
46
|
+
# @param id [String] unique identity for this marker
|
|
47
|
+
# @param active [Boolean] false while the switchover is in progress, true once it is confirmed
|
|
48
|
+
def initialize(blue_hosts:, switchover_time_ns:, id: SecureRandom.uuid, active: false)
|
|
49
|
+
@id = id
|
|
50
|
+
@switchover_time_ns = switchover_time_ns
|
|
51
|
+
@blue_hosts = blue_hosts.to_set.freeze
|
|
52
|
+
@active = active
|
|
53
|
+
freeze
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def active?
|
|
57
|
+
@active
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# @return [DropBlueConnectionsMarker] an active copy of this marker, keeping its identity.
|
|
61
|
+
def activated
|
|
62
|
+
return self if @active
|
|
63
|
+
|
|
64
|
+
DropBlueConnectionsMarker.new(
|
|
65
|
+
blue_hosts: @blue_hosts, switchover_time_ns: @switchover_time_ns, id: @id, active: true
|
|
66
|
+
)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Whether a connection opened to the given host at the given time is now a stale blue connection.
|
|
70
|
+
#
|
|
71
|
+
# @param host [String, nil] the downcased connect-time host of the connection
|
|
72
|
+
# @param open_time_ns [Integer, nil] the monotonic time the connection was opened
|
|
73
|
+
# @return [Boolean]
|
|
74
|
+
def stale?(host, open_time_ns)
|
|
75
|
+
return false unless @active
|
|
76
|
+
return false if host.nil? || open_time_ns.nil?
|
|
77
|
+
return false unless open_time_ns < @switchover_time_ns
|
|
78
|
+
|
|
79
|
+
@blue_hosts.include?(host)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -39,8 +39,10 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
39
39
|
build_cluster_pairs(source_status, target_status)
|
|
40
40
|
end
|
|
41
41
|
|
|
42
|
+
# Keyed by downcased host so lookups line up with role_by_host (also downcased); the blue host
|
|
43
|
+
# set the drop-blue-connections marker is built from indexes this map with downcased endpoints.
|
|
42
44
|
def merge_ips(ip_map)
|
|
43
|
-
@host_ip_addresses.
|
|
45
|
+
ip_map.each { |host, ip| @host_ip_addresses[host.downcase] = ip }
|
|
44
46
|
end
|
|
45
47
|
|
|
46
48
|
def register_role(host_names, role)
|
|
@@ -15,6 +15,7 @@
|
|
|
15
15
|
# limitations under the License.
|
|
16
16
|
|
|
17
17
|
require_relative '../../../logging'
|
|
18
|
+
require_relative '../../../utils/telemetry/telemetry_const'
|
|
18
19
|
|
|
19
20
|
module AwsAdvancedRubyDriverWrapper
|
|
20
21
|
module Plugins
|
|
@@ -24,6 +25,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
24
25
|
include Logging
|
|
25
26
|
|
|
26
27
|
MINIMUM_SLEEP_CHUNK_SEC = 0.05
|
|
28
|
+
TELEMETRY_SWITCHOVER = 'Blue/Green Deployment switchover'
|
|
27
29
|
|
|
28
30
|
def match?(host_info, role)
|
|
29
31
|
(@host.nil? || @host.downcase == host_info&.host&.downcase) &&
|
|
@@ -39,6 +41,11 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
39
41
|
"bgd_id: #{defined?(@bgd_id) ? (@bgd_id || '<null>') : '<n/a>'}]"
|
|
40
42
|
end
|
|
41
43
|
|
|
44
|
+
# Records the time a call is held while the switchover is in progress as a span.
|
|
45
|
+
def in_switchover_span(telemetry_factory, &)
|
|
46
|
+
telemetry_factory.in_context(TELEMETRY_SWITCHOVER, Utils::Telemetry::TraceLevel::NESTED, &)
|
|
47
|
+
end
|
|
48
|
+
|
|
42
49
|
# Blocks until the Blue/Green switchover phase is no longer IN_PROGRESS, or until the
|
|
43
50
|
# configured timeout elapses.
|
|
44
51
|
def wait_while_in_progress(wrapper_props, storage_service, bgd_id, sleep_time_sec = MINIMUM_SLEEP_CHUNK_SEC)
|
data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/substitute_connect_routing.rb
CHANGED
|
@@ -52,57 +52,37 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
52
52
|
bg_plugin: nil)
|
|
53
53
|
plugin_manager = service_container.plugin_manager
|
|
54
54
|
dialect_service = service_container.dialect_service
|
|
55
|
+
driver_dialect = dialect_service.driver_dialect
|
|
55
56
|
|
|
56
57
|
unless Utils::RdsUtils.ip?(@substitute_host.host)
|
|
57
58
|
return open_connection(plugin_manager, @substitute_host, driver_props, wrapper_props, is_initial_connection, is_internal,
|
|
58
59
|
bg_plugin)
|
|
59
60
|
end
|
|
60
61
|
|
|
61
|
-
#
|
|
62
|
-
#
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
62
|
+
# The substitute host is a raw IP, so a connection made by hostname could resolve (via DNS)
|
|
63
|
+
# to the old instance during the switchover window. Connect to the IP directly instead.
|
|
64
|
+
if plugin_manager.iam_token_plugin_in_use?
|
|
65
|
+
return apply_iam(service_container, driver_props, wrapper_props, is_initial_connection, bg_plugin)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
# pg can pin the socket to the IP (hostaddr) while keeping the original hostname for TLS
|
|
69
|
+
# verification, so the pinned connection reaches the right instance and still passes
|
|
70
|
+
# verify-full whatever the CA source.
|
|
71
|
+
pinned_props = driver_dialect.props_pinned_to_ip(driver_props, @substitute_host.host)
|
|
72
|
+
if pinned_props
|
|
67
73
|
hostname_host = @substitute_host.deep_dup(host: @host)
|
|
68
|
-
return open_connection(plugin_manager, hostname_host,
|
|
74
|
+
return open_connection(plugin_manager, hostname_host, pinned_props, wrapper_props, is_initial_connection, is_internal,
|
|
69
75
|
bg_plugin)
|
|
70
76
|
end
|
|
71
77
|
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
rerouted_host.id = iam_host.id
|
|
81
|
-
rerouted_host.availability = Host::HostAvailability::AVAILABLE
|
|
82
|
-
|
|
83
|
-
rerouted_wrapper_props = wrapper_props.dup
|
|
84
|
-
PropertyDefinition::IAM_HOST.set(rerouted_wrapper_props, iam_host.host)
|
|
85
|
-
PropertyDefinition::IAM_PORT.set(rerouted_wrapper_props, iam_host.port.to_s) if iam_host.port_specified?
|
|
86
|
-
|
|
87
|
-
begin
|
|
88
|
-
conn = plugin_manager.internal_connect(
|
|
89
|
-
rerouted_host,
|
|
90
|
-
driver_props,
|
|
91
|
-
rerouted_wrapper_props,
|
|
92
|
-
is_initial_connection,
|
|
93
|
-
plugin_to_skip: bg_plugin
|
|
94
|
-
)
|
|
95
|
-
begin
|
|
96
|
-
@iam_successful_connect_notify&.call(iam_host.host)
|
|
97
|
-
rescue StandardError
|
|
98
|
-
nil
|
|
99
|
-
end
|
|
100
|
-
return conn
|
|
101
|
-
rescue StandardError => e
|
|
102
|
-
raise unless dialect_service.login_error?(e)
|
|
103
|
-
end
|
|
104
|
-
end
|
|
105
|
-
return nil
|
|
78
|
+
# mysql2/trilogy use :host for both the socket and TLS CN verification, so connecting to a
|
|
79
|
+
# raw IP with TLS active causes a CN mismatch. When TLS is active, fall back to the hostname
|
|
80
|
+
# (DNS resolves to the correct IP post-switchover), matching the effective behaviour of the
|
|
81
|
+
# Java/Go drivers which use the original hostname for TLS regardless of the socket address.
|
|
82
|
+
if driver_props[driver_dialect.tls_ca_property_key]
|
|
83
|
+
hostname_host = @substitute_host.deep_dup(host: @host)
|
|
84
|
+
return open_connection(plugin_manager, hostname_host, driver_props, wrapper_props, is_initial_connection, is_internal,
|
|
85
|
+
bg_plugin)
|
|
106
86
|
end
|
|
107
87
|
|
|
108
88
|
open_connection(plugin_manager, @substitute_host, driver_props, wrapper_props, is_initial_connection, is_internal, bg_plugin)
|
|
@@ -114,6 +94,53 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
114
94
|
|
|
115
95
|
private
|
|
116
96
|
|
|
97
|
+
# Connects to the substitute IP with IAM auth active, trying each configured IAM host in turn
|
|
98
|
+
# so the IAM plugin can resolve the correct token hostname. pg pins the socket to the IP
|
|
99
|
+
# (hostaddr) while presenting the IAM host name for TLS verification; the IAM token is still
|
|
100
|
+
# generated for the IAM host via the IAM_HOST property. Other drivers connect to the IP as-is.
|
|
101
|
+
def apply_iam(service_container, driver_props, wrapper_props, is_initial_connection, bg_plugin)
|
|
102
|
+
plugin_manager = service_container.plugin_manager
|
|
103
|
+
dialect_service = service_container.dialect_service
|
|
104
|
+
driver_dialect = dialect_service.driver_dialect
|
|
105
|
+
|
|
106
|
+
if @iam_hosts.nil? || @iam_hosts.empty?
|
|
107
|
+
raise StandardError,
|
|
108
|
+
'Connecting with IP address when IAM authentication is enabled requires an \'iam_host\' parameter.'
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
@iam_hosts.each do |iam_host|
|
|
112
|
+
rerouted_host = @substitute_host.deep_dup
|
|
113
|
+
rerouted_host.id = iam_host.id
|
|
114
|
+
rerouted_host.availability = Host::HostAvailability::AVAILABLE
|
|
115
|
+
|
|
116
|
+
rerouted_wrapper_props = wrapper_props.dup
|
|
117
|
+
PropertyDefinition::IAM_HOST.set(rerouted_wrapper_props, iam_host.host)
|
|
118
|
+
PropertyDefinition::IAM_PORT.set(rerouted_wrapper_props, iam_host.port.to_s) if iam_host.port_specified?
|
|
119
|
+
|
|
120
|
+
connect_props = driver_props
|
|
121
|
+
pinned_props = driver_dialect.props_pinned_to_ip(driver_props, @substitute_host.host)
|
|
122
|
+
if pinned_props
|
|
123
|
+
connect_props = pinned_props
|
|
124
|
+
rerouted_host = rerouted_host.deep_dup(host: iam_host.host)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
begin
|
|
128
|
+
conn = plugin_manager.internal_connect(
|
|
129
|
+
rerouted_host, connect_props, rerouted_wrapper_props, is_initial_connection, plugin_to_skip: bg_plugin
|
|
130
|
+
)
|
|
131
|
+
begin
|
|
132
|
+
@iam_successful_connect_notify&.call(iam_host.host)
|
|
133
|
+
rescue StandardError
|
|
134
|
+
nil
|
|
135
|
+
end
|
|
136
|
+
return conn
|
|
137
|
+
rescue StandardError => e
|
|
138
|
+
raise unless dialect_service.login_error?(e)
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
nil
|
|
142
|
+
end
|
|
143
|
+
|
|
117
144
|
# Opens a connection through the plugin pipeline. Monitoring connections (is_internal: true)
|
|
118
145
|
# must use internal_connect so they do NOT mutate the shared current connection — otherwise
|
|
119
146
|
# one monitor thread's connect would close another monitor thread's live connection via
|
data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_connect_routing.rb
CHANGED
|
@@ -35,8 +35,10 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
35
35
|
storage_service = service_container.storage_service
|
|
36
36
|
hold_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
38
|
+
in_switchover_span(service_container.telemetry_factory) do
|
|
39
|
+
wait_while_in_progress(wrapper_props, storage_service, @bgd_id, SLEEP_TIME_SEC) do |timeout_sec|
|
|
40
|
+
"Blue/Green Deployment switchover is still in progress after #{timeout_sec} s. Try to connect again later."
|
|
41
|
+
end
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
elapsed_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - hold_start_time) * 1000).round
|
data/lib/aws_advanced_ruby_driver_wrapper/plugins/blue_green/routing/suspend_execute_routing.rb
CHANGED
|
@@ -31,11 +31,13 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
31
31
|
end
|
|
32
32
|
|
|
33
33
|
# Blocks until switchover is no longer IN_PROGRESS
|
|
34
|
-
def apply(method_name, wrapper_props, storage_service)
|
|
34
|
+
def apply(method_name, wrapper_props, storage_service, telemetry_factory:)
|
|
35
35
|
hold_start_time = Process.clock_gettime(Process::CLOCK_MONOTONIC)
|
|
36
36
|
|
|
37
|
-
|
|
38
|
-
|
|
37
|
+
in_switchover_span(telemetry_factory) do
|
|
38
|
+
wait_while_in_progress(wrapper_props, storage_service, @bgd_id, SLEEP_TIME_SEC) do |timeout_sec|
|
|
39
|
+
"Blue/Green Deployment switchover is still in progress after #{timeout_sec} s. Try '#{method_name}' again later."
|
|
40
|
+
end
|
|
39
41
|
end
|
|
40
42
|
|
|
41
43
|
elapsed_ms = ((Process.clock_gettime(Process::CLOCK_MONOTONIC) - hold_start_time) * 1000).round
|
|
@@ -35,8 +35,14 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
35
35
|
# Blocks until a corresponding green host is found for host_info.host, the switchover
|
|
36
36
|
# completes, or the timeout elapses.
|
|
37
37
|
def apply(host_info, _, wrapper_props, _is_initial_connection, service_container, is_internal: false, bg_plugin: nil)
|
|
38
|
-
|
|
38
|
+
in_switchover_span(service_container.telemetry_factory) do
|
|
39
|
+
hold_until_corresponding_host_found(host_info, wrapper_props, service_container.storage_service)
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
private
|
|
39
44
|
|
|
45
|
+
def hold_until_corresponding_host_found(host_info, wrapper_props, storage_service)
|
|
40
46
|
bg_status = storage_service.get(BlueGreenPlugin::BLUE_GREEN_NAME, @bgd_id)
|
|
41
47
|
corresponding_pair = bg_status&.corresponding_hosts&.[](host_info.host)
|
|
42
48
|
|
|
@@ -223,7 +223,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
223
223
|
next [] if host_pair.nil?
|
|
224
224
|
|
|
225
225
|
blue_host_spec = host_pair[0]
|
|
226
|
-
blue_ip_entry = @host_mapper.host_ip_addresses[blue_host_spec.host]
|
|
226
|
+
blue_ip_entry = @host_mapper.host_ip_addresses[blue_host_spec.host.downcase]
|
|
227
227
|
blue_ip_host_spec = blue_ip_entry ? Host::HostInfo.new(host: blue_ip_entry, port: blue_host_spec.port,
|
|
228
228
|
role: blue_host_spec.role) : blue_host_spec
|
|
229
229
|
|
|
@@ -338,6 +338,10 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
338
338
|
@event.reset
|
|
339
339
|
end
|
|
340
340
|
|
|
341
|
+
def abandon_connections
|
|
342
|
+
@connection.abandon
|
|
343
|
+
end
|
|
344
|
+
|
|
341
345
|
private
|
|
342
346
|
|
|
343
347
|
def attempt_open_connection
|
|
@@ -390,7 +394,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
390
394
|
end
|
|
391
395
|
|
|
392
396
|
def iam_enabled?
|
|
393
|
-
@service_container.plugin_manager.
|
|
397
|
+
@service_container.plugin_manager.iam_token_plugin_in_use?
|
|
394
398
|
end
|
|
395
399
|
|
|
396
400
|
def driver_dialect
|
|
@@ -417,14 +421,6 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
417
421
|
true
|
|
418
422
|
end
|
|
419
423
|
|
|
420
|
-
def syntax_error?(err)
|
|
421
|
-
driver_dialect.sql_state(err)&.start_with?('42') || false
|
|
422
|
-
end
|
|
423
|
-
|
|
424
|
-
def db_error?(err)
|
|
425
|
-
!driver_dialect.sql_state(err).nil?
|
|
426
|
-
end
|
|
427
|
-
|
|
428
424
|
# @note Callers must hold @connection_mutex (invoke within a @connection_mutex.synchronize block).
|
|
429
425
|
def status_available?(conn)
|
|
430
426
|
dialect = @service_container.dialect_service.db_dialect
|
|
@@ -504,11 +500,11 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
504
500
|
end
|
|
505
501
|
|
|
506
502
|
def handle_collect_status_error(err, conn)
|
|
507
|
-
if
|
|
503
|
+
if @service_container.dialect_service.schema_error?(err)
|
|
508
504
|
@current_phase = Phase::NOT_CREATED
|
|
509
505
|
logger.warn { "[#{@role}] current_phase: #{@current_phase}, exception while querying for blue/green status." }
|
|
510
|
-
elsif
|
|
511
|
-
if err.message.include?('
|
|
506
|
+
elsif @service_container.dialect_service.database_error?(err)
|
|
507
|
+
if err.message.include?('while retrieving the blue/green fast switchover metadata')
|
|
512
508
|
@current_phase = Phase::NOT_CREATED
|
|
513
509
|
return
|
|
514
510
|
end
|
|
@@ -553,7 +549,8 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
553
549
|
@service_container.plugin_manager,
|
|
554
550
|
@service_container.session_state_service,
|
|
555
551
|
@service_container.storage_service,
|
|
556
|
-
@service_container.monitor_service
|
|
552
|
+
@service_container.monitor_service,
|
|
553
|
+
@service_container.telemetry_factory
|
|
557
554
|
)
|
|
558
555
|
|
|
559
556
|
@host_list_provider = @service_container.dialect_service.db_dialect.create_host_list_provider(scoped_container)
|
|
@@ -18,6 +18,7 @@ require 'concurrent'
|
|
|
18
18
|
require_relative '../../logging'
|
|
19
19
|
require_relative '../../property_definition'
|
|
20
20
|
require_relative '../../utils/rds_utils'
|
|
21
|
+
require_relative 'drop_blue_connections_marker'
|
|
21
22
|
require_relative 'iam_host_tracker'
|
|
22
23
|
require_relative 'interval_rate'
|
|
23
24
|
require_relative 'host_mapper'
|
|
@@ -61,6 +62,10 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
61
62
|
@process_status_lock = Mutex.new
|
|
62
63
|
@monitor_generation = 0
|
|
63
64
|
|
|
65
|
+
@drop_blue_connections = PropertyDefinition::BG_DROP_BLUE_CONNECTIONS.get_bool(wrapper_props)
|
|
66
|
+
# Identity of the drop-blue-connections marker created for the current switchover, if any.
|
|
67
|
+
@drop_marker_id = nil
|
|
68
|
+
|
|
64
69
|
@status_check_interval_map = {
|
|
65
70
|
IntervalRate::BASELINE => PropertyDefinition::BG_INTERVAL_BASELINE_SEC.get_float(wrapper_props) * 1000,
|
|
66
71
|
IntervalRate::INCREASED => PropertyDefinition::BG_INTERVAL_INCREASED_SEC.get_float(wrapper_props) * 1000,
|
|
@@ -93,6 +98,11 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
93
98
|
@monitors.each_value { |m| m&.stop }
|
|
94
99
|
end
|
|
95
100
|
|
|
101
|
+
# Detaches the monitors inherited by a forked child without closing the parent's connections.
|
|
102
|
+
def release_after_fork
|
|
103
|
+
@monitors.each_value { |m| m&.release_after_fork }
|
|
104
|
+
end
|
|
105
|
+
|
|
96
106
|
def log_switchover_final_summary
|
|
97
107
|
return unless switchover_finalized?
|
|
98
108
|
|
|
@@ -171,6 +181,18 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
171
181
|
|
|
172
182
|
logger.warn { 'Blue/Green switchover has timed out.' }
|
|
173
183
|
@summary_status = @rollback ? @builder.created : @builder.completed(@rollback)
|
|
184
|
+
# A timeout means the wrapper stopped waiting, not that the switchover is confirmed. Only
|
|
185
|
+
# activate the marker if the switchover was last observed at POST (past the point of no
|
|
186
|
+
# return); timing out in PREPARATION/IN_PROGRESS could still roll back, and dropping blue
|
|
187
|
+
# connections then would hit a blue that is still primary. In that case discard the pending
|
|
188
|
+
# marker so it does not linger unactivated for the full marker TTL: we have given up waiting
|
|
189
|
+
# on this switchover, and no later phase will arrive to activate it.
|
|
190
|
+
if @latest_status_phase == Phase::POST
|
|
191
|
+
activate_drop_marker
|
|
192
|
+
else
|
|
193
|
+
remove_drop_marker
|
|
194
|
+
@drop_marker_id = nil
|
|
195
|
+
end
|
|
174
196
|
update_monitors
|
|
175
197
|
update_status_cache
|
|
176
198
|
log_current_context
|
|
@@ -186,7 +208,15 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
186
208
|
@monitors = { Role::SOURCE => nil, Role::TARGET => nil }
|
|
187
209
|
old_monitors.each_value { |m| m&.stop }
|
|
188
210
|
|
|
189
|
-
|
|
211
|
+
# A completed switchover's marker must survive this reset so connections opened to the old
|
|
212
|
+
# blue environment are still invalidated on their next use. A rollback leaves blue as primary,
|
|
213
|
+
# so its marker is discarded instead. Either way a later switchover starts a fresh marker.
|
|
214
|
+
remove_drop_marker if @rollback
|
|
215
|
+
@drop_marker_id = nil
|
|
216
|
+
|
|
217
|
+
# IamAuthPlugin, FederatedAuthPlugin, and OktaAuthPlugin all cache tokens under the same
|
|
218
|
+
# shared IAM_TOKEN_CACHE_NAME, so clearing through any one of them clears all of them.
|
|
219
|
+
Plugins::IamAuthPlugin.clear_cache(@storage_service) if iam_token_cache_in_use?
|
|
190
220
|
|
|
191
221
|
@rollback = false
|
|
192
222
|
@green_topology_recognized_logged = false
|
|
@@ -220,12 +250,15 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
220
250
|
@switchover_state.update_dns_flags(@bgd_id, role, interim_status)
|
|
221
251
|
@summary_status = @builder.in_progress(@rollback)
|
|
222
252
|
@switchover_state.trigger_in_progress_monitor_reset
|
|
253
|
+
ensure_drop_marker_pending
|
|
223
254
|
when Phase::POST
|
|
224
255
|
@switchover_state.update_dns_flags(@bgd_id, role, interim_status)
|
|
225
256
|
@summary_status = @builder.post(@rollback)
|
|
257
|
+
activate_drop_marker
|
|
226
258
|
when Phase::COMPLETED
|
|
227
259
|
@switchover_state.update_dns_flags(@bgd_id, role, interim_status)
|
|
228
260
|
@summary_status = @builder.completed(@rollback)
|
|
261
|
+
activate_drop_marker
|
|
229
262
|
else
|
|
230
263
|
raise ArgumentError, "[bgd_id: '#{@bgd_id}'] Unknown BG phase '#{@latest_status_phase}'."
|
|
231
264
|
end
|
|
@@ -345,14 +378,73 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
345
378
|
)
|
|
346
379
|
end
|
|
347
380
|
|
|
381
|
+
# Creates a pending drop-blue-connections marker the first time a switchover reaches IN_PROGRESS.
|
|
382
|
+
# The marker is only confirmed (see #activate_drop_marker) once the switchover passes the point
|
|
383
|
+
# of no return, so nothing is invalidated while it is still in progress and could roll back.
|
|
384
|
+
def ensure_drop_marker_pending
|
|
385
|
+
return unless @drop_blue_connections
|
|
386
|
+
return if @rollback
|
|
387
|
+
return if @drop_marker_id
|
|
388
|
+
|
|
389
|
+
hosts = blue_host_set
|
|
390
|
+
return if hosts.empty?
|
|
391
|
+
|
|
392
|
+
marker = DropBlueConnectionsMarker.new(blue_hosts: hosts, switchover_time_ns: nano_time)
|
|
393
|
+
@drop_marker_id = marker.id
|
|
394
|
+
store_drop_marker(marker)
|
|
395
|
+
end
|
|
396
|
+
|
|
397
|
+
# Confirms the switchover's pending marker so stale blue connections begin to be invalidated.
|
|
398
|
+
# A marker is only created when IN_PROGRESS is observed (see #ensure_drop_marker_pending), since
|
|
399
|
+
# that is the only point with a reliable switchover time. A provider that first sees the
|
|
400
|
+
# deployment at POST/COMPLETED cannot tell which of its connections predate the switchover and
|
|
401
|
+
# would wrongly cover connections opened after switchover, including to green.
|
|
402
|
+
def activate_drop_marker
|
|
403
|
+
return unless @drop_blue_connections
|
|
404
|
+
return if @rollback
|
|
405
|
+
|
|
406
|
+
marker = read_drop_marker
|
|
407
|
+
return if marker.nil? || marker.active?
|
|
408
|
+
|
|
409
|
+
store_drop_marker(marker.activated)
|
|
410
|
+
end
|
|
411
|
+
|
|
412
|
+
# The blue host set: downcased SOURCE endpoint names plus their pre-switchover IP addresses.
|
|
413
|
+
def blue_host_set
|
|
414
|
+
return Set.new unless @summary_status
|
|
415
|
+
|
|
416
|
+
blue = @summary_status.role_by_host.select { |_host, role| role == Role::SOURCE }.keys
|
|
417
|
+
ips = blue.filter_map { |host| @host_mapper.host_ip_addresses[host] }
|
|
418
|
+
(blue + ips).to_set(&:downcase)
|
|
419
|
+
end
|
|
420
|
+
|
|
421
|
+
def store_drop_marker(marker)
|
|
422
|
+
@storage_service.set(BlueGreenPlugin::DROP_MARKER_NAME, BlueGreenPlugin.drop_marker_key(@bgd_id), marker)
|
|
423
|
+
end
|
|
424
|
+
|
|
425
|
+
def read_drop_marker
|
|
426
|
+
@storage_service.get(BlueGreenPlugin::DROP_MARKER_NAME, BlueGreenPlugin.drop_marker_key(@bgd_id), register_access: false)
|
|
427
|
+
end
|
|
428
|
+
|
|
429
|
+
def remove_drop_marker
|
|
430
|
+
@storage_service.remove(BlueGreenPlugin::DROP_MARKER_NAME, BlueGreenPlugin.drop_marker_key(@bgd_id))
|
|
431
|
+
end
|
|
432
|
+
|
|
433
|
+
def nano_time
|
|
434
|
+
Process.clock_gettime(Process::CLOCK_MONOTONIC, :nanosecond)
|
|
435
|
+
end
|
|
436
|
+
|
|
348
437
|
def switchover_finalized?
|
|
349
438
|
completed = (!@rollback && @summary_status.current_phase == Phase::COMPLETED) ||
|
|
350
439
|
(@rollback && @summary_status.current_phase == Phase::CREATED)
|
|
351
440
|
completed && @event_log.any? { |_, v| v.phase&.active_switchover_or_completed? }
|
|
352
441
|
end
|
|
353
442
|
|
|
354
|
-
|
|
355
|
-
|
|
443
|
+
# True when any auth plugin backed by the shared IAM token cache (IAM or AD FS
|
|
444
|
+
# or Okta) is in use, so a switchover knows to purge that cache regardless
|
|
445
|
+
# of which one is active.
|
|
446
|
+
def iam_token_cache_in_use?
|
|
447
|
+
@service_container.plugin_manager&.iam_token_plugin_in_use? || false
|
|
356
448
|
end
|
|
357
449
|
|
|
358
450
|
def context_hash
|
data/lib/aws_advanced_ruby_driver_wrapper/plugins/custom_endpoint/custom_endpoint_monitor.rb
CHANGED
|
@@ -41,7 +41,14 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
41
41
|
refresh_rate_sec,
|
|
42
42
|
refresh_rate_backoff_factor,
|
|
43
43
|
max_refresh_rate_sec,
|
|
44
|
-
|
|
44
|
+
credentials_provider: nil,
|
|
45
|
+
rds_client_func: lambda { |_, client_region|
|
|
46
|
+
# Pass the configured credentials provider when one is set; otherwise omit :credentials
|
|
47
|
+
# so the SDK resolves from its default chain.
|
|
48
|
+
options = { region: client_region }
|
|
49
|
+
options[:credentials] = credentials_provider if credentials_provider
|
|
50
|
+
Aws::RDS::Client.new(**options)
|
|
51
|
+
}
|
|
45
52
|
)
|
|
46
53
|
super(termination_timeout_sec: TERMINATION_TIMEOUT_SEC)
|
|
47
54
|
|
|
@@ -58,6 +65,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
58
65
|
@refresh_cv = ConditionVariable.new
|
|
59
66
|
@refresh_required = false
|
|
60
67
|
@connection_issue = false
|
|
68
|
+
@info_changed_counter = service_container.telemetry_factory.create_counter('custom_endpoint.info_changed.count')
|
|
61
69
|
end
|
|
62
70
|
|
|
63
71
|
def endpoint_info?
|
|
@@ -161,6 +169,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
161
169
|
logger.debug("[#{@endpoint_id}] Custom endpoint info changed: #{endpoint_info}")
|
|
162
170
|
cache_allowed_blocked(endpoint_info)
|
|
163
171
|
cache_info(endpoint_info)
|
|
172
|
+
@info_changed_counter.inc
|
|
164
173
|
speedup_refresh_rate
|
|
165
174
|
|
|
166
175
|
elapsed = monotonic_time - start
|
|
@@ -241,6 +250,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
241
250
|
end
|
|
242
251
|
|
|
243
252
|
def cached_info
|
|
253
|
+
# Explicitly unregistered: a monitor reading its own data must not keep itself alive.
|
|
244
254
|
storage_service.get(ENDPOINT_INFO_CACHE_NAME, @custom_endpoint_host.url, register_access: false)
|
|
245
255
|
end
|
|
246
256
|
|
|
@@ -38,6 +38,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
38
38
|
@props = props
|
|
39
39
|
@should_wait_for_info = PropertyDefinition::WAIT_FOR_CUSTOM_ENDPOINT_INFO.get_bool(props)
|
|
40
40
|
@wait_timeout_sec = PropertyDefinition::WAIT_FOR_CUSTOM_ENDPOINT_INFO_TIMEOUT_SEC.get_float(props)
|
|
41
|
+
@wait_for_info_counter = service_container.telemetry_factory.create_counter('custom_endpoint.wait_for_info.count')
|
|
41
42
|
|
|
42
43
|
@custom_endpoint_host = nil
|
|
43
44
|
@endpoint_id = nil
|
|
@@ -128,7 +129,8 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
128
129
|
@region,
|
|
129
130
|
PropertyDefinition::CUSTOM_ENDPOINT_INFO_REFRESH_RATE_SEC.get_float(props),
|
|
130
131
|
PropertyDefinition::CUSTOM_ENDPOINT_INFO_REFRESH_RATE_BACKOFF_FACTOR.get_int(props),
|
|
131
|
-
PropertyDefinition::CUSTOM_ENDPOINT_INFO_MAX_REFRESH_RATE_SEC.get_float(props)
|
|
132
|
+
PropertyDefinition::CUSTOM_ENDPOINT_INFO_MAX_REFRESH_RATE_SEC.get_float(props),
|
|
133
|
+
credentials_provider: PropertyDefinition::AWS_CREDENTIALS_PROVIDER.get(props)
|
|
132
134
|
)
|
|
133
135
|
end
|
|
134
136
|
end
|
|
@@ -137,6 +139,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
137
139
|
return if monitor.endpoint_info?
|
|
138
140
|
|
|
139
141
|
monitor.request_endpoint_info_update
|
|
142
|
+
@wait_for_info_counter.inc
|
|
140
143
|
logger.debug("CustomEndpointPlugin: waiting up to #{@wait_timeout_sec}s for endpoint info on #{@custom_endpoint_host.url}")
|
|
141
144
|
|
|
142
145
|
return if monitor.wait_for_info?(@wait_timeout_sec)
|
|
@@ -18,6 +18,7 @@ require 'concurrent'
|
|
|
18
18
|
require_relative '../errors'
|
|
19
19
|
require_relative '../host/host_info'
|
|
20
20
|
require_relative '../host/host_availability'
|
|
21
|
+
require_relative '../utils/telemetry/telemetry_const'
|
|
21
22
|
|
|
22
23
|
module AwsAdvancedRubyDriverWrapper
|
|
23
24
|
module Plugins
|
|
@@ -44,7 +45,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
44
45
|
host_info
|
|
45
46
|
end
|
|
46
47
|
|
|
47
|
-
conn = driver_dialect.connect(target_host_info, driver_props)
|
|
48
|
+
conn = with_driver_span { driver_dialect.connect(target_host_info, driver_props) }
|
|
48
49
|
|
|
49
50
|
if conn.nil?
|
|
50
51
|
raise Errors::AwsError,
|
|
@@ -83,7 +84,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
83
84
|
|
|
84
85
|
def internal_connect(host_info, driver_props, _wrapper_props, _is_initial_connection, _pipeline_callable)
|
|
85
86
|
driver_dialect = @service_container.dialect_service.driver_dialect
|
|
86
|
-
driver_dialect.connect(host_info, driver_props)
|
|
87
|
+
with_driver_span { driver_dialect.connect(host_info, driver_props) }
|
|
87
88
|
end
|
|
88
89
|
|
|
89
90
|
def execute(target_method_name, target_callable, *args, **, &)
|
|
@@ -92,7 +93,7 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
92
93
|
succeeded = false
|
|
93
94
|
|
|
94
95
|
begin
|
|
95
|
-
result = target_callable.call(*args, **, &)
|
|
96
|
+
result = with_driver_span { target_callable.call(*args, **, &) }
|
|
96
97
|
succeeded = true
|
|
97
98
|
result
|
|
98
99
|
ensure
|
|
@@ -103,6 +104,16 @@ module AwsAdvancedRubyDriverWrapper
|
|
|
103
104
|
end
|
|
104
105
|
end
|
|
105
106
|
end
|
|
107
|
+
|
|
108
|
+
private
|
|
109
|
+
|
|
110
|
+
# Records the time spent in the driver itself as a span named after the driver.
|
|
111
|
+
def with_driver_span(&)
|
|
112
|
+
telemetry_factory = @service_container.telemetry_factory
|
|
113
|
+
return yield unless telemetry_factory.traces_in_use?
|
|
114
|
+
|
|
115
|
+
telemetry_factory.in_context(@service_container.dialect_service.driver_dialect.name, Utils::Telemetry::TraceLevel::NESTED, &)
|
|
116
|
+
end
|
|
106
117
|
end
|
|
107
118
|
end
|
|
108
119
|
end
|