Class: Mongo::Tracing::OpenTelemetry::CommandTracer Private
| Relationships & Source Files | |
| Inherits: | Object |
| Defined in: | lib/mongo/tracing/open_telemetry/command_tracer.rb |
Overview
CommandTracer is responsible for tracing MongoDB server commands using ::Mongo::Tracing::OpenTelemetry.
Constant Summary
-
ELLIPSIS =
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 297
Ellipsis for truncated query text.
'...' -
EXCLUDED_KEYS =
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 294
Keys to exclude from query text capture.
%w[lsid $db $clusterTime signature].freeze
Class Method Summary
-
.new(otel_tracer, parent_tracer, query_text_max_length: 0) ⇒ CommandTracer
constructor
Internal use only
Initializes a new
CommandTracer.
Instance Attribute Summary
-
#query_text? ⇒ Boolean
readonly
private
Internal use only
Checks if query text capture is enabled.
Instance Method Summary
-
#start_span(message, operation_context, connection)
Internal use only
Starts a span for a MongoDB command.
-
#trace_command(message, _operation_context, connection) { ... } ⇒ Object
Internal use only
Trace a MongoDB command.
-
#base_attributes(message) ⇒ Hash
private
Internal use only
Returns base database and command attributes.
-
#collection_name(message) ⇒ String | nil
private
Internal use only
Extracts the collection name from the command message.
-
#command_name(message) ⇒ String
private
Internal use only
Extracts the command name from the message.
-
#connection_attributes(connection) ⇒ Hash
private
Internal use only
Returns connection-related attributes.
-
#create_command_span(message, connection) ⇒ OpenTelemetry::Trace::Span
private
Internal use only
Creates a span for a command.
-
#cursor_id(message) ⇒ Integer | nil
private
Internal use only
Extracts the cursor ID from getMore commands.
-
#database(message) ⇒ String
private
Internal use only
Extracts the database name from the message.
-
#handle_command_exception(span, exception)
private
Internal use only
Handles exceptions that occur during command execution.
-
#lsid(message) ⇒ BSON::Binary | nil
private
Internal use only
Extracts the logical session ID from the command.
-
#maybe_trace_error(result, span)
private
Internal use only
Records error status code if the command failed.
-
#process_command_result(result, cursor_id, context, span)
private
Internal use only
Processes the command result and updates span attributes.
-
#process_cursor_context(result, _cursor_id, _context, span)
private
Internal use only
Processes cursor context from the command result.
-
#query_summary(message) ⇒ String
private
Internal use only
Generates a summary string for the query.
-
#query_text(message) ⇒ String | nil
readonly
private
Internal use only
Extracts and formats the query text from the command.
-
#session_attributes(message) ⇒ Hash
private
Internal use only
Returns session and transaction attributes.
-
#span_attributes(message, connection) ⇒ Hash
private
Internal use only
Builds span attributes for the command.
-
#txn_number(message) ⇒ Integer | nil
private
Internal use only
Extracts the transaction number from the command.
Instance Attribute Details
#query_text? ⇒ Boolean (readonly, private)
Checks if query text capture is enabled.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 254
def query_text? @query_text_max_length.positive? end
Instance Method Details
#base_attributes(message) ⇒ Hash (private)
Returns base database and command attributes.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 136
def base_attributes() { 'db.system' => 'mongodb', 'db.namespace' => database(), 'db.collection.name' => collection_name(), 'db.command.name' => command_name(), 'db.query.summary' => query_summary(), 'db.query.text' => query_text() } end
#collection_name(message) ⇒ String | nil (private)
Extracts the collection name from the command message.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 220
def collection_name() case command_name() when 'getMore' .documents.first['collection'].to_s when 'listCollections', 'listDatabases', 'commitTransaction', 'abortTransaction' nil else value = .documents.first.values.first # Return nil if the value is not a string (e.g., for admin commands that have numeric values) value.is_a?(String) ? value : nil end end
#command_name(message) ⇒ String (private)
Extracts the command name from the message.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 238
def command_name() .documents.first.keys.first.to_s end
#connection_attributes(connection) ⇒ Hash (private)
Returns connection-related attributes.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 152
def connection_attributes(connection) { 'server.port' => connection.address.port, 'server.address' => connection.address.host, 'network.transport' => connection.transport.to_s, 'db.mongodb.server_connection_id' => connection.server.description.server_connection_id, 'db.mongodb.driver_connection_id' => connection.id } end
#create_command_span(message, connection) ⇒ OpenTelemetry::Trace::Span (private)
Creates a span for a command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 85
def create_command_span(, connection) @otel_tracer.start_span( command_name(), attributes: span_attributes(, connection), kind: :client ) end
#cursor_id(message) ⇒ Integer | nil (private)
Extracts the cursor ID from getMore commands.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 263
def cursor_id() return unless command_name() == 'getMore' .documents.first['getMore'].value end
#database(message) ⇒ String (private)
Extracts the database name from the message.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 247
def database() .documents.first['$db'].to_s end
#handle_command_exception(span, exception) (private)
Handles exceptions that occur during command execution.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 108
def handle_command_exception(span, exception) return unless span if exception.is_a?(Mongo::Error::OperationFailure) span.set_attribute('db.response.status_code', exception.code.to_s) end span.record_exception(exception) span.status = ::OpenTelemetry::Trace::Status.error("Unhandled exception of type: #{exception.class}") end
#lsid(message) ⇒ BSON::Binary | nil (private)
Extracts the logical session ID from the command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 274
def lsid() lsid_doc = .documents.first['lsid'] return unless lsid_doc lsid_doc['id'].to_uuid end
#maybe_trace_error(result, span) (private)
Records error status code if the command failed.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 191
def maybe_trace_error(result, span) return if result.successful? span.set_attribute('db.response.status_code', result.error.code.to_s) begin result.validate! rescue Mongo::Error::OperationFailure => e span.record_exception(e) end end
#process_command_result(result, cursor_id, context, span) (private)
Processes the command result and updates span attributes.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 99
def process_command_result(result, cursor_id, context, span) process_cursor_context(result, cursor_id, context, span) maybe_trace_error(result, span) end
#process_cursor_context(result, _cursor_id, _context, span) (private)
Processes cursor context from the command result.
#query_summary(message) ⇒ String (private)
Generates a summary string for the query.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 207
def query_summary() if (coll_name = collection_name()) "#{command_name()} #{database()}.#{coll_name}" else "#{command_name()} #{database()}" end end
#query_text(message) ⇒ String | nil (readonly, private)
Extracts and formats the query text from the command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 304
def query_text() return unless query_text? text = .payload['command'] .reject { |key, _| EXCLUDED_KEYS.include?(key) } .to_json if text.length > @query_text_max_length "#{text[0...@query_text_max_length]}#{ELLIPSIS}" else text end end
#session_attributes(message) ⇒ Hash (private)
Returns session and transaction attributes.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 167
def session_attributes() { 'db.mongodb.cursor_id' => cursor_id(), 'db.mongodb.lsid' => lsid(), 'db.mongodb.txn_number' => txn_number() } end
#span_attributes(message, connection) ⇒ Hash (private)
Builds span attributes for the command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 124
def span_attributes(, connection) base_attributes() .merge(connection_attributes(connection)) .merge(session_attributes()) .compact end
#start_span(message, operation_context, connection)
Starts a span for a MongoDB command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 42
def start_span(, operation_context, connection); end
#trace_command(message, _operation_context, connection) { ... } ⇒ Object
Trace a MongoDB command.
Creates an ::Mongo::Tracing::OpenTelemetry span for the command, capturing attributes such as command name, database name, collection name, server address, connection IDs, and optionally query text. The span is automatically nested under the current operation span and is finished when the command completes or fails.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 59
def trace_command(, _operation_context, connection) # Commands should always be nested under their operation span, not directly under # the transaction span. Don't pass with_parent to use automatic parent resolution # from the currently active span (the operation span). span = create_command_span(, connection) ::OpenTelemetry::Trace.with_span(span) do |s, c| yield.tap do |result| process_command_result(result, cursor_id(), c, s) end end rescue Exception => e handle_command_exception(span, e) raise e ensure span&.finish end
#txn_number(message) ⇒ Integer | nil (private)
Extracts the transaction number from the command.
# File 'lib/mongo/tracing/open_telemetry/command_tracer.rb', line 286
def txn_number() txn_num = .documents.first['txnNumber'] return unless txn_num txn_num.value end