123456789_123456789_123456789_123456789_123456789_

Class: Mongo::Tracing::OpenTelemetry::OperationTracer Private

Do not use. This class is for internal use only.
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

Instance Method Summary

Instance Method Details

#collection_key_for_operation(operation) ⇒ Symbol | nil (private)

Returns the collection key for a given operation type.

Parameters:

Returns:

  • (Symbol | nil)

    the collection key symbol or nil.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 199

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.

Parameters:

Returns:

  • (String | nil)

    the collection name, or nil if not applicable.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 171

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.

Parameters:

Returns:

  • (OpenTelemetry::Trace::Span)

    the created span.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 78

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) { ... } ⇒ Object (private)

Executes the operation block within the span context.

Parameters:

  • span (OpenTelemetry::Trace::Span)

    the span.

  • operation (Mongo::Operation)

    the operation.

Yields:

  • the block to execute.

Returns:

  • (Object)

    the result of the block.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 96

def execute_with_span(span, operation)
  ::OpenTelemetry::Trace.with_span(span) do |s, c|
    yield.tap do |result|
      process_cursor_context(result, operation.cursor_id, c, s)
    end
  end
end

#extract_collection_from_spec(operation) ⇒ String | nil (private)

Extracts collection name from operation spec based on operation type.

Parameters:

Returns:

  • (String | nil)

    the collection name, or nil if not found.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 182

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.

Parameters:

  • span (OpenTelemetry::Trace::Span)

    the span.

  • exception (Exception)

    the exception.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 108

def handle_span_exception(span, exception)
  return unless span

  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.

Parameters:

  • operation (Mongo::Operation)

    the operation.

  • op_name (String | nil) (defaults to: nil)

    optional operation name.

Returns:

  • (String)

    the operation name in lowercase.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 123

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.

Parameters:

  • operation (Mongo::Operation)

    the operation.

  • op_name (String | nil) (defaults to: nil)

    optional operation name.

Returns:

  • (String)

    span name in format “operation_name db.collection” or “operation_name db”.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 216

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) (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.

Parameters:

  • result (Object)

    the operation result.

  • cursor_id (Integer | nil)

    the cursor ID before the operation.

  • context (OpenTelemetry::Context)
  • span (OpenTelemetry::Trace::Span)

    the current span.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 153

def process_cursor_context(result, cursor_id, context, span)
  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)
  end
end

#span_attributes(operation, op_name) ⇒ Hash (private)

Builds span attributes for the operation.

Parameters:

  • operation (Mongo::Operation)

    the operation.

  • op_name (String | nil)

    optional operation name.

Returns:

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 133

def span_attributes(operation, op_name)
  {
    'db.system' => '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),
    'db.mongodb.cursor_id' => operation.cursor_id,
  }.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.

Parameters:

  • operation (Mongo::Operation)

    the MongoDB operation to trace.

  • operation_context (Mongo::Operation::Context)

    the context of the operation.

  • op_name (String | nil)

    an optional name for the operation. If nil, the operation class name is used.

Yields:

  • the block representing the operation to be traced.

Returns:

  • (Object)

    the result of the operation.

[ GitHub ]

  
# File 'lib/mongo/tracing/open_telemetry/operation_tracer.rb', line 58

def trace_operation(operation, operation_context, op_name: nil, &block)
  span = create_operation_span(operation, operation_context, op_name)
  execute_with_span(span, operation, &block)
rescue Exception => e
  handle_span_exception(span, e)
  raise e
ensure
  span&.finish
end