Class: Mongo::Tracing::OpenTelemetry::OperationTracer Private
| Relationships & Source Files | |
| Super Chains via Extension / Inclusion / Inheritance | |
|
Class Chain:
self,
Forwardable
|
|
| Inherits: | Object |
| Defined in: | lib/mongo/tracing/open_telemetry/operation_tracer.rb |
Overview
OperationTracer is responsible for tracing MongoDB driver operations using ::Mongo::Tracing::OpenTelemetry.
Class Method Summary
-
.new(otel_tracer, parent_tracer) ⇒ OperationTracer
constructor
Internal use only
Initializes a new
OperationTracer.
Instance Method Summary
-
#trace_operation(operation, operation_context, op_name: nil) { ... } ⇒ Object
Internal use only
Trace a MongoDB operation.
-
#collection_key_for_operation(operation) ⇒ Symbol | nil
private
Internal use only
Returns the collection key for a given operation type.
-
#collection_name(operation) ⇒ String | nil
private
Internal use only
Extracts the collection name from the operation.
-
#create_operation_span(operation, operation_context, op_name) ⇒ OpenTelemetry::Trace::Span
private
Internal use only
Creates an
::Mongo::Tracing::OpenTelemetryspan for the operation. -
#execute_with_span(span, operation, recording) { ... } ⇒ Object
private
Internal use only
Executes the operation block within the span context.
-
#extract_collection_from_spec(operation) ⇒ String | nil
private
Internal use only
Extracts collection name from operation spec based on operation type.
-
#handle_span_exception(span, exception)
private
Internal use only
Handles exception for the span.
-
#operation_name(operation, op_name = nil) ⇒ String
private
Internal use only
Returns the operation name from the provided name or operation class.
-
#operation_span_name(operation, op_name = nil) ⇒ String
private
Internal use only
Generates the span name for the operation.
-
#process_cursor_context(result, cursor_id, context, span, recording)
private
Internal use only
Processes cursor context after operation execution.
-
#span_attributes(operation, op_name) ⇒ Hash
private
Internal use only
Builds the attributes passed at span creation.
-
#trace_with_span(span, operation, &block) ⇒ Object
private
Internal use only
Runs the operation with the span made current, and finishes the span.
Constructor Details
.new(otel_tracer, parent_tracer) ⇒ OperationTracer
Initializes a new OperationTracer.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 37
def initialize(otel_tracer, parent_tracer) @otel_tracer = otel_tracer @parent_tracer = parent_tracer end
Instance Method Details
#collection_key_for_operation(operation) ⇒ Symbol | nil (private)
Returns the collection key for a given operation type.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 224
def collection_key_for_operation(operation) case operation when Operation::Aggregate then :aggregate when Operation::Count then :count when Operation::Create then :create when Operation::Distinct then :distinct when Operation::Drop then :drop when Operation::WriteCommand then :first_value end end
#collection_name(operation) ⇒ String | nil (private)
Extracts the collection name from the operation.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 196
def collection_name(operation) return operation.coll_name.to_s if operation.respond_to?(:coll_name) && operation.coll_name extract_collection_from_spec(operation) end
#create_operation_span(operation, operation_context, op_name) ⇒ OpenTelemetry::Trace::Span (private)
Creates an ::Mongo::Tracing::OpenTelemetry span for the operation.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 100
def create_operation_span(operation, operation_context, op_name) parent_context = parent_context_for(operation_context, operation.cursor_id) @otel_tracer.start_span( operation_span_name(operation, op_name), attributes: span_attributes(operation, op_name), with_parent: parent_context, kind: :client ) end
#execute_with_span(span, operation, recording) { ... } ⇒ Object (private)
Executes the operation block within the span context.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 119
def execute_with_span(span, operation, recording) ::OpenTelemetry::Trace.with_span(span) do |s, c| yield.tap do |result| process_cursor_context(result, operation.cursor_id, c, s, recording) end end end
#extract_collection_from_spec(operation) ⇒ String | nil (private)
Extracts collection name from operation spec based on operation type.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 207
def extract_collection_from_spec(operation) collection_key = collection_key_for_operation(operation) return nil unless collection_key value = if collection_key == :first_value operation.spec[:selector].values.first else operation.spec[:selector][collection_key] end value&.to_s end
#handle_span_exception(span, exception) (private)
Handles exception for the span.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 131
def handle_span_exception(span, exception) span.record_exception(exception) span.status = ::OpenTelemetry::Trace::Status.error( "Unhandled exception of type: #{exception.class}" ) end
#operation_name(operation, op_name = nil) ⇒ String (private)
Returns the operation name from the provided name or operation class.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 144
def operation_name(operation, op_name = nil) op_name || operation.class.name.split('::').last.downcase end
#operation_span_name(operation, op_name = nil) ⇒ String (private)
Generates the span name for the operation.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 241
def operation_span_name(operation, op_name = nil) coll_name = collection_name(operation) if coll_name && !coll_name.empty? "#{operation_name(operation, op_name)} #{operation.db_name}.#{coll_name}" else "#{operation_name(operation, op_name)} #{operation.db_name}" end end
#process_cursor_context(result, cursor_id, context, span, recording) (private)
Processes cursor context after operation execution.
Updates the cursor context map based on the result. Removes closed cursors and stores context for newly created cursors.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 178
def process_cursor_context(result, cursor_id, context, span, recording) return unless result.is_a?(Cursor) if result.id.zero? # If the cursor is closed, remove it from the context map. cursor_context_map.delete(cursor_id) elsif result.id && cursor_id.nil? # New cursor created, store its context. cursor_context_map[result.id] = context span.set_attribute('db.mongodb.cursor_id', result.id) if recording end end
#span_attributes(operation, op_name) ⇒ Hash (private)
Builds the attributes passed at span creation. The cursor id is set by trace_with_span once the span is known to record. db.operation.summary is outside the spec's recommended creation set, but it is the span name, which is built anyway, and an attribute passed at creation is cheaper than one set later.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 158
def span_attributes(operation, op_name) { 'db.system.name' => 'mongodb', 'db.namespace' => operation.db_name.to_s, 'db.collection.name' => collection_name(operation), 'db.operation.name' => operation_name(operation, op_name), 'db.operation.summary' => operation_span_name(operation, op_name) }.compact end
#trace_operation(operation, operation_context, op_name: nil) { ... } ⇒ Object
Trace a MongoDB operation.
Creates an ::Mongo::Tracing::OpenTelemetry span for the operation, capturing attributes such as
database name, collection name, operation name, and cursor ID. The span is finished
automatically when the operation completes or fails.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 56
def trace_operation(operation, operation_context, op_name: nil, &block) span = create_operation_span(operation, operation_context, op_name) # With no SDK and no valid parent, the API returns a span with an # invalid context. It cannot be made current, recorded or # propagated, so it gets no work at all, not even finishing it. return yield unless span.context.valid? trace_with_span(span, operation, &block) end
#trace_with_span(span, operation, &block) ⇒ Object (private)
Runs the operation with the span made current, and finishes the span. A span that is not recording is still made current, so that the command spans created within it nest under it, but gets no further attributes and no outcome: the SDK would discard them.
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 79
def trace_with_span(span, operation, &block) recording = span.recording? if recording && !operation.cursor_id.nil? span.set_attribute('db.mongodb.cursor_id', operation.cursor_id) end execute_with_span(span, operation, recording, &block) rescue Exception => e handle_span_exception(span, e) if recording raise e ensure span.finish end