Menu Docs
Página inicial do Docs
/ / /
Driver Ruby MongoDB
/

Monitoramento

Nesta página

  • Monitoramento de comandos
  • Descoberta e monitoramento de servidores
  • servidor Heartbeats
  • pool de conexões e monitoramento de conexões
  • Desabilitar o monitoramento
  • Eventos excluídos e editados

O driver permite que o aplicativo seja notificado quando determinados eventos acontecem. Esses eventos são organizados nas seguintes categorias:

  • Monitoramento de comandos

  • Ciclo de vida da topologia

  • Ciclo de vida do servidor

  • Heartbeats do servidor

  • pool de conexões e conexões

A topologia e os eventos do servidor fazem parte da Descoberta e Monitoramento do Servidor (SDAM).

Todos os comandos iniciados pelo usuário que são enviados para o servidor publicam eventos que podem ser assinados para obter informações refinadas. A API de monitoramento publica um evento de início garantido para cada comando e, em seguida, um evento bem-sucedido ou um evento com falha. Um assinante deve implementar 3 métodos: started, succeeded e failed, cada um deles usando um único parâmetro para o evento. Veja a seguir um exemplo de assinante de registro com base em um assinante de registro usado internamente pelo driver:

class CommandLogSubscriber
include Mongo::Loggable
def started(event)
# The default inspection of a command which is a BSON document gets
# truncated in the middle. To get the full rendering of the command, the
# ``to_json`` method can be called on the document.
log_debug("#{prefix(event)} | STARTED | #{format_command(event.command.to_json)}")
end
def succeeded(event)
log_debug("#{prefix(event)} | SUCCEEDED | #{event.duration}s")
end
def failed(event)
log_debug("#{prefix(event)} | FAILED | #{event.message} | #{event.duration}s")
end
private
def logger
Mongo::Logger.logger
end
def format_command(args)
begin
args.inspect
rescue Exception
'<Unable to inspect arguments>'
end
end
def format_message(message)
format("COMMAND | %s".freeze, message)
end
def prefix(event)
"#{event.address.to_s} | #{event.database_name}.#{event.command_name}"
end
end

Para registrar um assinante personalizado, você pode fazer isso globalmente para todos os clientes ou por cliente:

subscriber = CommandLogSubscriber.new
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::COMMAND, subscriber)
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test' )
client.subscribe( Mongo::Monitoring::COMMAND, subscriber )

Saída de amostra:

D, [2018-09-23T13:47:31.258020 #4692] DEBUG -- : COMMAND | 127.0.0.1:27027 | test.hello | STARTED | {"hello"=>1, "$readPreference"=>{"mode"=>"primary"}, "lsid"=>{"id"=><BSON::Binary:0x47111693353080 type=uuid data=0x730341e880dc40a2...>}}
D, [2018-09-23T13:47:31.259145 #4692] DEBUG -- : COMMAND | 127.0.0.1:27027 | test.hello | SUCCEEDED | 0.000791175s

O Ruby driver implementa a especificação MongoDB Server Discovery and Monitoring (SDAM). e disponibiliza os seguintes eventos para o aplicativo:

  • Abertura de topologia

  • Abertura do servidor

  • Descrição do servidor alterada

  • topologia alterada

  • servidor fechado

  • topologia fechada

  • Evento de pulsação (analisados abaixo em uma seção separada)

Para todos os eventos que não sejam os eventos de pulsação, o método succeeded será chamado em cada assinante do evento com o evento como o único argumento. Os dados disponíveis para eventos variam, portanto, para registrar os eventos, é necessária uma classe separada para cada tipo de evento. Um simples assinante de registro do SDAM pode ter a seguinte aparência:

class SDAMLogSubscriber
include Mongo::Loggable
def succeeded(event)
log_debug(format_event(event))
end
private
def logger
Mongo::Logger.logger
end
def format_message(message)
format("SDAM | %s".freeze, message)
end
end
class TopologyOpeningLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
"Topology type '#{event.topology.display_name}' initializing."
end
end
class ServerOpeningLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
"Server #{event.address} initializing."
end
end
class ServerDescriptionChangedLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
"Server description for #{event.address} changed from " +
"'#{event.previous_description.server_type}' to '#{event.new_description.server_type}'."
end
end
class TopologyChangedLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
if event.previous_topology != event.new_topology
"Topology type '#{event.previous_topology.display_name}' changed to " +
"type '#{event.new_topology.display_name}'."
else
"There was a change in the members of the '#{event.new_topology.display_name}' " +
"topology."
end
end
end
class ServerClosedLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
"Server #{event.address} connection closed."
end
end
class TopologyClosedLogSubscriber < SDAMLogSubscriber
private
def format_event(event)
"Topology type '#{event.topology.display_name}' closed."
end
end

Para assinar eventos SDAM globalmente:

topology_opening_subscriber = TopologyOpeningLogSubscriber.new
server_opening_subscriber = ServerOpeningLogSubscriber.new
server_description_changed_subscriber = ServerDescriptionChangedLogSubscriber.new
topology_changed_subscriber = TopologyChangedLogSubscriber.new
server_closed_subscriber = ServerClosedLogSubscriber.new
topology_closed_subscriber = TopologyClosedLogSubscriber.new
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING,
topology_opening_subscriber)
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_OPENING,
server_opening_subscriber)
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_DESCRIPTION_CHANGED,
server_description_changed_subscriber)
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_CHANGED,
topology_changed_subscriber)
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_CLOSED,
server_closed_subscriber)
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::TOPOLOGY_CLOSED,
topology_closed_subscriber)

Assinar eventos SDAM para um único cliente é um pouco mais trabalhoso, pois os eventos podem ser publicados durante a construção do cliente:

topology_opening_subscriber = TopologyOpeningLogSubscriber.new
server_opening_subscriber = ServerOpeningLogSubscriber.new
server_description_changed_subscriber = ServerDescriptionChangedLogSubscriber.new
topology_changed_subscriber = TopologyChangedLogSubscriber.new
server_closed_subscriber = ServerClosedLogSubscriber.new
topology_closed_subscriber = TopologyClosedLogSubscriber.new
sdam_proc = Proc.new do |client|
client.subscribe(Mongo::Monitoring::TOPOLOGY_OPENING,
topology_opening_subscriber)
client.subscribe(Mongo::Monitoring::SERVER_OPENING,
server_opening_subscriber)
client.subscribe(Mongo::Monitoring::SERVER_DESCRIPTION_CHANGED,
server_description_changed_subscriber)
client.subscribe(Mongo::Monitoring::TOPOLOGY_CHANGED,
topology_changed_subscriber)
client.subscribe(Mongo::Monitoring::SERVER_CLOSED,
server_closed_subscriber)
client.subscribe(Mongo::Monitoring::TOPOLOGY_CLOSED,
topology_closed_subscriber)
end
client = Mongo::Client.new(['127.0.0.1:27017'], database: 'test',
sdam_proc: sdam_proc)

Saída de amostra:

D, [2018-10-09T13:58:03.489461 #22079] DEBUG -- : SDAM | Topology type 'Unknown' initializing.
D, [2018-10-09T13:58:03.489699 #22079] DEBUG -- : SDAM | Server 127.0.0.1:27100 initializing.
D, [2018-10-09T13:58:03.491384 #22079] DEBUG -- : SDAM | Server description for 127.0.0.1:27100 changed from 'unknown' to 'unknown'.
D, [2018-10-09T13:58:03.491642 #22079] DEBUG -- : SDAM | Server localhost:27100 initializing.
D, [2018-10-09T13:58:03.493199 #22079] DEBUG -- : SDAM | Server description for localhost:27100 changed from 'unknown' to 'primary'.
D, [2018-10-09T13:58:03.493473 #22079] DEBUG -- : SDAM | Server localhost:27101 initializing.
D, [2018-10-09T13:58:03.494874 #22079] DEBUG -- : SDAM | Server description for localhost:27101 changed from 'unknown' to 'secondary'.
D, [2018-10-09T13:58:03.495139 #22079] DEBUG -- : SDAM | Server localhost:27102 initializing.
D, [2018-10-09T13:58:03.496504 #22079] DEBUG -- : SDAM | Server description for localhost:27102 changed from 'unknown' to 'secondary'.
D, [2018-10-09T13:58:03.496777 #22079] DEBUG -- : SDAM | Topology type 'Unknown' changed to type 'ReplicaSetNoPrimary'.
D, [2018-10-09T13:58:03.497306 #22079] DEBUG -- : SDAM | Server 127.0.0.1:27100 connection closed.
D, [2018-10-09T13:58:03.497606 #22079] DEBUG -- : SDAM | Topology type 'ReplicaSetNoPrimary' changed to type 'ReplicaSetWithPrimary'.
# client.close
D, [2018-10-09T13:58:05.342057 #22079] DEBUG -- : SDAM | Server localhost:27100 connection closed.
D, [2018-10-09T13:58:05.342299 #22079] DEBUG -- : SDAM | Server localhost:27101 connection closed.
D, [2018-10-09T13:58:05.342565 #22079] DEBUG -- : SDAM | Server localhost:27102 connection closed.
D, [2018-10-09T13:58:05.342693 #22079] DEBUG -- : SDAM | Topology type 'ReplicaSetWithPrimary' closed.

Observação

:sdam_proc a opção do cliente se aplica apenas ao cliente durante cuja construção é fornecida. Quando determinadas opções do cliente são alteradas por meio da chamada Client#with , um novo cluster pode ser criado pelo driver com um conjunto padrão de assinantes de eventos. Se isso acontecer, o :sdam_proc fornecido não será chamado e o aplicativo poderá perder eventos.

O aplicativo pode ser notificado de cada pulsação do servidor assinando o tópico SERVER_HEARTBATE. Um ouvinte de pulsação do servidor deve implementar três métodos: started, succeeded e failed. Cada pulsação invoca o método started no ouvinte e, em seguida, o método succeeded ou failed , dependendo do resultado da pulsação.

Todos os eventos de pulsação contêm o endereço do servidor para o qual a pulsação foi enviada. Evento bem-sucedidos e com falha contêm o tempo de ida e volta para o comando hello ou legado hello. O evento com falha também contém a instância de exceção que foi gerada durante a execução do comando hello ou hello legado. Revise a documentação da API para ServerHeatbeatStarted, ServerHearbeatSucceeded e ServerHearbeatFailed para obter detalhes do atributo do evento.

Veja a seguir um exemplo de registro de assinante de eventos de pulsação:

class HeartbeatLogSubscriber
include Mongo::Loggable
def started(event)
log_debug("#{event.address} | STARTED")
end
def succeeded(event)
log_debug("#{event.address} | SUCCEEDED | #{event.duration}s")
end
def failed(event)
log_debug("#{event.address} | FAILED | #{event.error.class}: #{event.error.message} | #{event.duration}s")
end
private
def logger
Mongo::Logger.logger
end
def format_message(message)
format("HEARTBEAT | %s".freeze, message)
end
end

Da mesma forma que os eventos de comando, o aplicativo pode se inscrever em eventos de pulsação globalmente ou para um cliente específico:

subscriber = HeartbeatLogSubscriber.new
Mongo::Monitoring::Global.subscribe(Mongo::Monitoring::SERVER_HEARTBEAT, subscriber)
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test' )
client.subscribe( Mongo::Monitoring::SERVER_HEARTBEAT, subscriber )

Saída de amostra:

D, [2018-09-23T13:44:10.707018 #1739] DEBUG -- : HEARTBEAT | 127.0.0.1:27027 | STARTED
D, [2018-09-23T13:44:10.707778 #1739] DEBUG -- : HEARTBEAT | 127.0.0.1:27027 | SUCCEEDED | 0.000772381s

Quando conectado ao MongoDB 4.2 e a servidores anteriores, o driver Ruby, por padrão, emite pulsações a cada :heartbeat_frequency (opção do cliente Ruby) segundos, e as pulsações não se sobrepõem (é garantido que o evento bem-sucedido para uma pulsação seja publicados antes do evento iniciado para o o próximo heartbeat é publicados). Quando conectado ao MongoDB 4.4 e a servidores posteriores, o driver usa vários threads de monitoramento e um protocolo de pulsação mais complexo projetado para detectar alterações no estado do servidor mais rapidamente; como resultado, os intervalos de eventos de pulsação podem ser mais irregulares e os eventos de pulsação podem se sobrepor. Especificamente, uma pulsação esperada pode começar ou terminar enquanto uma pulsação não esperada está em andamento e vice-versa. Use os métodos ServerHeartbeatStarted#awaited?, ServerHeartbeatSucceeded#awaited? e ServerHeartbeatFailed#awaited? para distinguir entre pulsações não esperadas e aguardadas.

Quando um cliente está tentando executar uma operação e não tem um servidor adequado, a implantação é verificada com mais frequência - cada servidor pode ser pesquisado a cada 500 milissegundos. Também é possível que o aplicativo solicite uma verificação manual de um servidor específico; o driver força o intervalo mínimo de 500 milissegundos entre as verificações.

Cada cliente mantém um pool de conexões para cada servidor na implantação que conhece e publica eventos para pools de conexões e conexões individuais. Para assinar esses eventos, defina uma classe de assinante implementando o método pubished que usa um único parâmetro para o evento que está sendo publicados. Observe que versões futuras do driver podem introduzir eventos adicionais publicados por esse mecanismo.

Os seguintes eventos são atualmente implementados pelo condutor, seguindo a especificação CMAP:

  • PoolCreated

  • PoolLimpo

  • PoolClosed

  • connectionCreated

  • connectionReady

  • connectionClosed

  • connectionCheckOutStarted

  • connectionCheckOutFailed

  • ConnectionCheckOutSucceeded

  • connectionCheckedIn

O driver fornece um assinante de registro que pode ser usado para registrar todo o pool de conexões e eventos relacionados à conexão. Esse assinante não está habilitado por padrão porque criará entradas de registro para cada operação executada pelo aplicativo. Para habilitar este assinante globalmente ou por cliente:

Mongo::Monitoring::Global.subscribe(
Mongo::Monitoring::CONNECTION_POOL,
Mongo::Monitoring::CmapLogSubscriber.new)
client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test' )
subscriber = Mongo::Monitoring::CmapLogSubscriber.new
client.subscribe( Mongo::Monitoring::CONNECTION_POOL, subscriber )

Saída de amostra:

D, [2019-05-06T17:23:21.595412 #8576] DEBUG -- : MONGODB | EVENT: #<PoolCreated address=127.0.0.1:27741 options={...}>
D, [2019-05-06T17:23:21.595584 #8576] DEBUG -- : MONGODB | EVENT: #<PoolCleared address=127.0.0.1:27741>
D, [2019-05-06T17:23:21.603549 #8576] DEBUG -- : MONGODB | EVENT: #<PoolCreated address=localhost:27741 options={...}>
D, [2019-05-06T17:23:21.603616 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionCheckOutStarted address=localhost:27741>
D, [2019-05-06T17:23:21.603684 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionCreated address=localhost:27741 connection_id=1>
D, [2019-05-06T17:23:21.604079 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionCheckedOut address=localhost:27741 connection_id=1>
D, [2019-05-06T17:23:21.605759 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionReady address=localhost:27741 connection_id=1>
D, [2019-05-06T17:23:21.605784 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionCheckedIn address=localhost:27741 connection_id=1>
D, [2019-05-06T17:23:21.605817 #8576] DEBUG -- : MONGODB | EVENT: #<PoolCleared address=localhost:27741>
D, [2019-05-06T17:23:21.605852 #8576] DEBUG -- : MONGODB | EVENT: #<ConnectionClosed address=localhost:27741 connection_id=1 reason=stale>

Para desativar o monitoramento, defina a opção de monitoramento do cliente como false:

client = Mongo::Client.new([ '127.0.0.1:27017' ], :database => 'test', :monitoring => false )

O driver Ruby não publica e, ocasionalmente, edita alguns eventos por meio do mecanismo de monitoramento de comandos:

  1. Se o comando pertencer a um subconjunto específico de comandos editados ou contiver chaves que trigger a redação da carga útil, uma carga vazia será fornecida por motivos de segurança. O payload completo pode ser acessado definindo a variável de ambiente MONGO_RUBY_DRIVER_UNREDACT_EVENTS como 1, true ou yes. Os seguintes comandos são suprimidos:

    • authenticate

    • saslStart

    • saslContinue

    • getnonce

    • createUser

    • updateUser

    • copydbgetnonce

    • copydbsaslstart

    • copydb

  2. Se o comando for um comando de handshake, ismaster ou hello, em uma conexão de não monitoramento, nenhum evento será publicados.

  3. Os comandos enviados por conexões de monitoramento (como isMaster e hello) não publicam eventos de monitoramento de comandos. Em vez disso, toda vez que um servidor é marcado, um evento de pulsação do servidor é publicados. Os eventos de pulsação do servidor não incluem cargas úteis de comando ou resposta.

  4. Se o comando for um comando de handshake e as opções speculativeAuthenticate forem true, o comando será suprimido e uma carga útil vazia será fornecida.

Voltar

Autenticação