mongo 2.25.0 → 2.26.1
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/lib/mongo/bulk_write/combineable.rb +0 -7
- data/lib/mongo/bulk_write/validatable.rb +0 -4
- data/lib/mongo/bulk_write.rb +0 -34
- data/lib/mongo/client.rb +35 -5
- data/lib/mongo/client_encryption.rb +36 -11
- data/lib/mongo/cluster.rb +1 -2
- data/lib/mongo/collection/queryable_encryption.rb +7 -6
- data/lib/mongo/collection/view/aggregation.rb +9 -9
- data/lib/mongo/collection/view/change_stream.rb +1 -5
- data/lib/mongo/collection/view/iterable.rb +2 -9
- data/lib/mongo/collection/view/map_reduce.rb +5 -4
- data/lib/mongo/collection/view/readable.rb +3 -3
- data/lib/mongo/collection/view/writable.rb +0 -35
- data/lib/mongo/crypt/auto_encrypter.rb +5 -1
- data/lib/mongo/crypt/binding.rb +66 -1
- data/lib/mongo/crypt/explicit_encrypter.rb +27 -12
- data/lib/mongo/crypt/explicit_encryption_context.rb +51 -12
- data/lib/mongo/crypt/handle.rb +18 -0
- data/lib/mongo/cursor.rb +13 -0
- data/lib/mongo/database/view.rb +7 -6
- data/lib/mongo/database.rb +7 -10
- data/lib/mongo/error/unsupported_option.rb +0 -40
- data/lib/mongo/grid/fs_bucket.rb +2 -2
- data/lib/mongo/grid/stream/read.rb +2 -2
- data/lib/mongo/grid/stream/write.rb +1 -1
- data/lib/mongo/index/view.rb +3 -2
- data/lib/mongo/monitoring/event/secure.rb +6 -1
- data/lib/mongo/operation/map_reduce/result.rb +6 -2
- data/lib/mongo/operation/result.rb +9 -0
- data/lib/mongo/operation/shared/executable.rb +1 -6
- data/lib/mongo/operation/shared/result/aggregatable.rb +3 -3
- data/lib/mongo/protocol/message.rb +0 -4
- data/lib/mongo/protocol/msg.rb +1 -12
- data/lib/mongo/protocol/serializers.rb +1 -9
- data/lib/mongo/retryable/backpressure.rb +17 -2
- data/lib/mongo/retryable/read_worker.rb +1 -1
- data/lib/mongo/retryable/retry_policy.rb +2 -2
- data/lib/mongo/retryable/write_worker.rb +2 -2
- data/lib/mongo/retryable.rb +1 -1
- data/lib/mongo/server/app_metadata.rb +1 -2
- data/lib/mongo/server/connection.rb +7 -0
- data/lib/mongo/server/connection_pool.rb +60 -9
- data/lib/mongo/server/description/features.rb +2 -3
- data/lib/mongo/server/description.rb +0 -1
- data/lib/mongo/server/pending_connection.rb +0 -5
- data/lib/mongo/server.rb +1 -2
- data/lib/mongo/session.rb +10 -3
- data/lib/mongo/tracing/open_telemetry/command_tracer.rb +141 -102
- data/lib/mongo/tracing/open_telemetry/operation_tracer.rb +52 -17
- data/lib/mongo/tracing/open_telemetry/tracer.rb +10 -1
- data/lib/mongo/uri/options_mapper.rb +15 -4
- data/lib/mongo/version.rb +1 -1
- metadata +2 -2
|
@@ -37,6 +37,8 @@ module Mongo
|
|
|
37
37
|
def initialize(otel_tracer, parent_tracer)
|
|
38
38
|
@otel_tracer = otel_tracer
|
|
39
39
|
@parent_tracer = parent_tracer
|
|
40
|
+
@operation_names = {}
|
|
41
|
+
@operation_names_mutex = Mutex.new
|
|
40
42
|
end
|
|
41
43
|
|
|
42
44
|
# Trace a MongoDB operation.
|
|
@@ -53,21 +55,43 @@ module Mongo
|
|
|
53
55
|
# @yield the block representing the operation to be traced.
|
|
54
56
|
#
|
|
55
57
|
# @return [ Object ] the result of the operation.
|
|
56
|
-
#
|
|
57
|
-
# rubocop:disable Lint/RescueException
|
|
58
58
|
def trace_operation(operation, operation_context, op_name: nil, &block)
|
|
59
59
|
span = create_operation_span(operation, operation_context, op_name)
|
|
60
|
-
|
|
60
|
+
# With no SDK and no valid parent, the API returns a span with an
|
|
61
|
+
# invalid context. It cannot be made current, recorded or
|
|
62
|
+
# propagated, so it gets no work at all, not even finishing it.
|
|
63
|
+
return yield unless span.context.valid?
|
|
64
|
+
|
|
65
|
+
trace_with_span(span, operation, &block)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
private
|
|
69
|
+
|
|
70
|
+
# Runs the operation with the span made current, and finishes the span.
|
|
71
|
+
# A span that is not recording is still made current, so that the
|
|
72
|
+
# command spans created within it nest under it, but gets no further
|
|
73
|
+
# attributes and no outcome: the SDK would discard them.
|
|
74
|
+
#
|
|
75
|
+
# @param span [ OpenTelemetry::Trace::Span ] a span with a valid context.
|
|
76
|
+
# @param operation [ Mongo::Operation ] the operation.
|
|
77
|
+
#
|
|
78
|
+
# @return [ Object ] the result of the operation.
|
|
79
|
+
#
|
|
80
|
+
# rubocop:disable Lint/RescueException
|
|
81
|
+
def trace_with_span(span, operation, &block)
|
|
82
|
+
recording = span.recording?
|
|
83
|
+
if recording && !operation.cursor_id.nil?
|
|
84
|
+
span.set_attribute('db.mongodb.cursor_id', operation.cursor_id)
|
|
85
|
+
end
|
|
86
|
+
execute_with_span(span, operation, recording, &block)
|
|
61
87
|
rescue Exception => e
|
|
62
|
-
handle_span_exception(span, e)
|
|
88
|
+
handle_span_exception(span, e) if recording
|
|
63
89
|
raise e
|
|
64
90
|
ensure
|
|
65
|
-
span
|
|
91
|
+
span.finish
|
|
66
92
|
end
|
|
67
93
|
# rubocop:enable Lint/RescueException
|
|
68
94
|
|
|
69
|
-
private
|
|
70
|
-
|
|
71
95
|
# Creates an OpenTelemetry span for the operation.
|
|
72
96
|
#
|
|
73
97
|
# @param operation [ Mongo::Operation ] the operation.
|
|
@@ -89,14 +113,15 @@ module Mongo
|
|
|
89
113
|
#
|
|
90
114
|
# @param span [ OpenTelemetry::Trace::Span ] the span.
|
|
91
115
|
# @param operation [ Mongo::Operation ] the operation.
|
|
116
|
+
# @param recording [ true | false ] whether the span is recording.
|
|
92
117
|
#
|
|
93
118
|
# @yield the block to execute.
|
|
94
119
|
#
|
|
95
120
|
# @return [ Object ] the result of the block.
|
|
96
|
-
def execute_with_span(span, operation)
|
|
121
|
+
def execute_with_span(span, operation, recording)
|
|
97
122
|
::OpenTelemetry::Trace.with_span(span) do |s, c|
|
|
98
123
|
yield.tap do |result|
|
|
99
|
-
process_cursor_context(result, operation.cursor_id, c, s)
|
|
124
|
+
process_cursor_context(result, operation.cursor_id, c, s, recording)
|
|
100
125
|
end
|
|
101
126
|
end
|
|
102
127
|
end
|
|
@@ -106,8 +131,6 @@ module Mongo
|
|
|
106
131
|
# @param span [ OpenTelemetry::Trace::Span ] the span.
|
|
107
132
|
# @param exception [ Exception ] the exception.
|
|
108
133
|
def handle_span_exception(span, exception)
|
|
109
|
-
return unless span
|
|
110
|
-
|
|
111
134
|
span.record_exception(exception)
|
|
112
135
|
span.status = ::OpenTelemetry::Trace::Status.error(
|
|
113
136
|
"Unhandled exception of type: #{exception.class}"
|
|
@@ -115,16 +138,28 @@ module Mongo
|
|
|
115
138
|
end
|
|
116
139
|
|
|
117
140
|
# Returns the operation name from the provided name or operation class.
|
|
141
|
+
# The name derived from the class is cached per class. There are few
|
|
142
|
+
# operation classes, so the cache needs no bound. It is guarded by a
|
|
143
|
+
# mutex because not every Ruby runtime makes Hash writes thread-safe.
|
|
118
144
|
#
|
|
119
145
|
# @param operation [ Mongo::Operation ] the operation.
|
|
120
146
|
# @param op_name [ String | nil ] optional operation name.
|
|
121
147
|
#
|
|
122
148
|
# @return [ String ] the operation name in lowercase.
|
|
123
149
|
def operation_name(operation, op_name = nil)
|
|
124
|
-
op_name
|
|
150
|
+
return op_name if op_name
|
|
151
|
+
|
|
152
|
+
klass = operation.class
|
|
153
|
+
@operation_names_mutex.synchronize do
|
|
154
|
+
@operation_names[klass] ||= klass.name.split('::').last.downcase
|
|
155
|
+
end
|
|
125
156
|
end
|
|
126
157
|
|
|
127
|
-
# Builds
|
|
158
|
+
# Builds the attributes passed at span creation. The cursor id is set
|
|
159
|
+
# by trace_with_span once the span is known to record.
|
|
160
|
+
# db.operation.summary is outside the spec's recommended creation set,
|
|
161
|
+
# but it is the span name, which is built anyway, and an attribute
|
|
162
|
+
# passed at creation is cheaper than one set later.
|
|
128
163
|
#
|
|
129
164
|
# @param operation [ Mongo::Operation ] the operation.
|
|
130
165
|
# @param op_name [ String | nil ] optional operation name.
|
|
@@ -136,8 +171,7 @@ module Mongo
|
|
|
136
171
|
'db.namespace' => operation.db_name.to_s,
|
|
137
172
|
'db.collection.name' => collection_name(operation),
|
|
138
173
|
'db.operation.name' => operation_name(operation, op_name),
|
|
139
|
-
'db.operation.summary' => operation_span_name(operation, op_name)
|
|
140
|
-
'db.mongodb.cursor_id' => operation.cursor_id,
|
|
174
|
+
'db.operation.summary' => operation_span_name(operation, op_name)
|
|
141
175
|
}.compact
|
|
142
176
|
end
|
|
143
177
|
|
|
@@ -150,7 +184,8 @@ module Mongo
|
|
|
150
184
|
# @param cursor_id [ Integer | nil ] the cursor ID before the operation.
|
|
151
185
|
# @param context [ OpenTelemetry::Context ] the OpenTelemetry context.
|
|
152
186
|
# @param span [ OpenTelemetry::Trace::Span ] the current span.
|
|
153
|
-
|
|
187
|
+
# @param recording [ true | false ] whether the span is recording.
|
|
188
|
+
def process_cursor_context(result, cursor_id, context, span, recording)
|
|
154
189
|
return unless result.is_a?(Cursor)
|
|
155
190
|
|
|
156
191
|
if result.id.zero?
|
|
@@ -159,7 +194,7 @@ module Mongo
|
|
|
159
194
|
elsif result.id && cursor_id.nil?
|
|
160
195
|
# New cursor created, store its context.
|
|
161
196
|
cursor_context_map[result.id] = context
|
|
162
|
-
span.set_attribute('db.mongodb.cursor_id', result.id)
|
|
197
|
+
span.set_attribute('db.mongodb.cursor_id', result.id) if recording
|
|
163
198
|
end
|
|
164
199
|
end
|
|
165
200
|
|
|
@@ -200,6 +200,9 @@ module Mongo
|
|
|
200
200
|
# Generates a unique key for transaction tracking.
|
|
201
201
|
#
|
|
202
202
|
# Returns nil for implicit sessions or sessions not in a transaction.
|
|
203
|
+
# Every operation in a transaction needs the key, so it is cached on
|
|
204
|
+
# the session together with the transaction number it was built for.
|
|
205
|
+
# Two threads may build it at the same time; they build the same key.
|
|
203
206
|
#
|
|
204
207
|
# @param session [ Mongo::Session ] the session.
|
|
205
208
|
#
|
|
@@ -207,7 +210,13 @@ module Mongo
|
|
|
207
210
|
def transaction_map_key(session)
|
|
208
211
|
return if session.nil? || session.implicit? || !session.in_transaction?
|
|
209
212
|
|
|
210
|
-
|
|
213
|
+
txn_num = session.txn_num
|
|
214
|
+
cached = session.tracing_transaction_key
|
|
215
|
+
return cached[1] if cached && cached[0] == txn_num
|
|
216
|
+
|
|
217
|
+
key = "#{session.session_id['id'].to_uuid}-#{txn_num}"
|
|
218
|
+
session.tracing_transaction_key = [ txn_num, key ].freeze
|
|
219
|
+
key
|
|
211
220
|
end
|
|
212
221
|
|
|
213
222
|
private
|
|
@@ -614,7 +614,7 @@ module Mongo
|
|
|
614
614
|
#
|
|
615
615
|
# @return [ Hash | nil ] The auth mechanism properties hash.
|
|
616
616
|
def convert_auth_mech_props(_name, value)
|
|
617
|
-
properties = hash_extractor('authMechanismProperties', value)
|
|
617
|
+
properties = hash_extractor('authMechanismProperties', value, invalidate_on_error: true)
|
|
618
618
|
if properties
|
|
619
619
|
properties.each do |k, v|
|
|
620
620
|
properties[k] = (v.downcase == 'true') if k.to_s.downcase == 'canonicalize_host_name' && v
|
|
@@ -863,16 +863,27 @@ module Mongo
|
|
|
863
863
|
|
|
864
864
|
# Extract values from the string and put them into a nested hash.
|
|
865
865
|
#
|
|
866
|
+
# Multiple key-value pairs are delimited by a comma. Within each pair,
|
|
867
|
+
# the key is everything up to the first colon and the value is everything
|
|
868
|
+
# after it, so values may themselves contain colons (for example
|
|
869
|
+
# TOKEN_RESOURCE:mongodb://host).
|
|
870
|
+
#
|
|
866
871
|
# @param [ String ] name Name of the URI option being processed.
|
|
867
872
|
# @param [ String ] value The string to build a hash from.
|
|
873
|
+
# @param [ true | false ] invalidate_on_error When a pair is malformed
|
|
874
|
+
# (has no value), discard the whole option and return nil instead of
|
|
875
|
+
# skipping just that pair. Used for options such as
|
|
876
|
+
# authMechanismProperties whose values must not contain commas.
|
|
868
877
|
#
|
|
869
|
-
# @return [ Hash ] The hash built from the string.
|
|
870
|
-
def hash_extractor(name, value)
|
|
878
|
+
# @return [ Hash | nil ] The hash built from the string, or nil.
|
|
879
|
+
def hash_extractor(name, value, invalidate_on_error: false)
|
|
871
880
|
h = {}
|
|
872
881
|
value.split(',').each do |tag|
|
|
873
|
-
k, v = tag.split(':')
|
|
882
|
+
k, v = tag.split(':', 2)
|
|
874
883
|
if v.nil?
|
|
875
884
|
log_warn("Invalid hash value for #{name}: key `#{k}` does not have a value: #{value}")
|
|
885
|
+
return nil if invalidate_on_error
|
|
886
|
+
|
|
876
887
|
next
|
|
877
888
|
end
|
|
878
889
|
|
data/lib/mongo/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: mongo
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.
|
|
4
|
+
version: 2.26.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- The MongoDB Ruby Team
|
|
@@ -561,7 +561,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
561
561
|
- !ruby/object:Gem::Version
|
|
562
562
|
version: '0'
|
|
563
563
|
requirements: []
|
|
564
|
-
rubygems_version: 4.0.
|
|
564
|
+
rubygems_version: 4.0.23
|
|
565
565
|
specification_version: 4
|
|
566
566
|
summary: Ruby driver for MongoDB
|
|
567
567
|
test_files: []
|