class Mongo::Server::AppMetadata

Application metadata that is sent to the server during a handshake,

when a new connection is established.

@api private

@since 2.4.0

Constants

AUTH_OPTION_KEYS

Option keys that affect auth mechanism negotiation.

@api private

DRIVER_NAME

The driver name.

@since 2.4.0

MAX_APP_NAME_SIZE

The max application name byte size.

@since 2.4.0

MAX_DOCUMENT_SIZE

The max application metadata document byte size.

@since 2.4.0

PURPOSES

Possible connection purposes.

@api private

Attributes

purpose[R]

@return [ Symbol ] The purpose of the connection for which this

app metadata is created.

@api private

server_api[R]

@return [ Hash | nil ] The requested server API version.

Thes hash can have the following items:
- *:version* -- string
- *:strict* -- boolean
- *:deprecation_errors* -- boolean

@api private

wrapping_libraries[R]

@return [ Array<Hash> | nil ] Information about libraries wrapping

the driver.

Public Class Methods

new(options = {}) click to toggle source

Instantiate the new AppMetadata object.

@api private

@example Instantiate the app metadata.

Mongo::Server::AppMetadata.new(options)

@param [ Hash ] options Metadata options. @option options [ String, Symbol ] :app_name Application name that is

printed to the mongod logs upon establishing a connection in server
versions >= 3.4.

@option options [ Symbol ] :auth_mech The authentication mechanism to

use. One of :mongodb_cr, :mongodb_x509, :plain, :scram, :scram256

@option options [ String ] :auth_source The source to authenticate from. @option options [ Array<String> ] :compressors A list of potential

compressors to use, in order of preference. The driver chooses the
first compressor that is also supported by the server. Currently the
driver only supports 'zstd', 'snappy' and 'zlib'.

@option options [ String ] :platform Platform information to include in

the metadata printed to the mongod logs upon establishing a connection
in server versions >= 3.4.

@option options [ Symbol ] :purpose The purpose of this connection. @option options [ Hash ] :server_api The requested server API version.

This hash can have the following items:
- *:version* -- string
- *:strict* -- boolean
- *:deprecation_errors* -- boolean

@option options [ String ] :user The user name. @option options [ Array<Hash> ] :wrapping_libraries Information about

libraries such as ODMs that are wrapping the driver. Specify the
lower level libraries first. Allowed hash keys: :name, :version,
:platform.

@since 2.4.0

# File lib/mongo/server/app_metadata.rb, line 88
def initialize(options = {})
  @app_name = options[:app_name].to_s if options[:app_name]
  @platform = options[:platform]
  if @purpose = options[:purpose]
    unless PURPOSES.include?(@purpose)
      raise ArgumentError, "Invalid purpose: #{@purpose}"
    end
  end
  @compressors = options[:compressors] || []
  @wrapping_libraries = options[:wrapping_libraries]
  @server_api = options[:server_api]

  if options[:user] && !options[:auth_mech]
    auth_db = options[:auth_source] || 'admin'
    @request_auth_mech = "#{auth_db}.#{options[:user]}"
  end
end

Public Instance Methods

validated_document() click to toggle source

Get the metadata as BSON::Document to be sent to as part of the handshake. The document should be appended to a suitable handshake command.

This method ensures that the metadata are valid.

@return [BSON::Document] Valid document for connection's handshake.

@raise [ Error::InvalidApplicationName ] When the metadata are invalid.

@api private

# File lib/mongo/server/app_metadata.rb, line 137
def validated_document
  validate!
  document
end

Private Instance Methods

architecture() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 235
def architecture
  RbConfig::CONFIG['target_cpu']
end
document() click to toggle source

Get the metadata as BSON::Document to be sent to as part of the handshake. The document should be appended to a suitable handshake command.

@return [BSON::Document] Document for connection's handshake.

# File lib/mongo/server/app_metadata.rb, line 174
def document
  @document ||= begin
    client_document = full_client_document
    while client_document.to_bson.to_s.size > MAX_DOCUMENT_SIZE do
      if client_document[:os][:name] || client_document[:os][:architecture]
        client_document[:os].delete(:name)
        client_document[:os].delete(:architecture)
      elsif client_document[:platform]
        client_document.delete(:platform)
      else
        client_document = nil
      end
    end
    document = BSON::Document.new(
      {
        compression: @compressors,
        client: client_document,
      }
    )
    document[:saslSupportedMechs] = @request_auth_mech if @request_auth_mech
    if @server_api
      document.update(
        Utils.transform_server_api(@server_api)
      )
    end
    document
  end
end
driver_doc() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 203
def driver_doc
  names = [DRIVER_NAME]
  versions = [Mongo::VERSION]
  if wrapping_libraries
    wrapping_libraries.each do |library|
      names << library[:name] || ''
      versions << library[:version] || ''
    end
  end
  {
    name: names.join('|'),
    version: versions.join('|'),
  }
end
full_client_document() click to toggle source

Get BSON::Document to be used as value for `client` key in handshake document.

@return [BSON::Document] Document describing client for handshake.

# File lib/mongo/server/app_metadata.rb, line 159
def full_client_document
  BSON::Document.new.tap do |doc|
    doc[:application] = { name: @app_name } if @app_name
    doc[:driver] = driver_doc
    doc[:os] = os_doc
    doc[:platform] = platform
  end
end
name() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 231
def name
  RbConfig::CONFIG['host_os']
end
os_doc() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 218
def os_doc
  {
    type: type,
    name: name,
    architecture: architecture
  }
end
platform() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 239
def platform
  if BSON::Environment.jruby?
    ruby_versions = ["JRuby #{JRUBY_VERSION}", "like Ruby #{RUBY_VERSION}"]
    platforms = [RUBY_PLATFORM, "JVM #{java.lang.System.get_property('java.version')}"]
  else
    ruby_versions = ["Ruby #{RUBY_VERSION}"]
    platforms = [RUBY_PLATFORM]
  end
  platforms = [
    @platform,
    *ruby_versions,
    *platforms,
    RbConfig::CONFIG['build'],
  ]
  if @purpose
    platforms << @purpose.to_s[0].upcase
  end
  platform = platforms.compact.join(', ')
  platforms = [platform]
  if wrapping_libraries
    wrapping_libraries.each do |library|
      platforms << library[:platform] || ''
    end
  end
  platforms.join('|')
end
type() click to toggle source
# File lib/mongo/server/app_metadata.rb, line 226
def type
  (RbConfig::CONFIG && RbConfig::CONFIG['host_os']) ?
    RbConfig::CONFIG['host_os'].split('_').first[/[a-z]+/i].downcase : 'unknown'
end
validate!() click to toggle source

Check whether it is possible to build a valid app metadata document with params provided on intialization.

@raise [ Error::InvalidApplicationName ] When the metadata are invalid.

# File lib/mongo/server/app_metadata.rb, line 148
def validate!
  if @app_name && @app_name.bytesize > MAX_APP_NAME_SIZE
    raise Error::InvalidApplicationName.new(@app_name, MAX_APP_NAME_SIZE)
  end
  true
end