Monitoramento de queries no Neo4j

Marlon Alves
Neo4j
Published in
5 min readJul 5, 2020

Olá galerinha, neste post iremos falar sobre como analisar e configurar o monitoramento de queries no Neo4J.

É importante supervisionar o andamento da suas queries para que não ocorra interrupções na sua base de dados, e garantir que suas transações sejam concluídas permanecendo íntegras.

Monitorando por log

Uma boa maneira para manter um registro de transações feitas no Neo4j é guardar informações de queries que possam ser prejudiciais à estabilidade da sua base de dados. O Neo4j trás três grandes tipos de log, vocês podem verificar clicando neste link NEO4J LOGS. Aqui iremos trabalhar com o query.log, que nada mais é que consultas executadas no banco.

PS.: Infelizmente o monitoramento através do query.log funciona apenas na versão enterprise do Neo4j.

Com a versão enterprise, o primeiro passo é entrar na pasta do neo4j instalada e abrir o arquivo query.log, situado na pasta conf.

A primeira tag que iremos demonstrar é a dbms.logs.query.enabled, na qual habilita o log de queries no arquivo, de início vamos modificar ele para true no arquivo neo4j.conf:

dbms.logs.query.enabled=true

Próximo passo iremos executar uma query e iremos verificar se ela aparece no arquivo de configuração do Neo4j.

Abrindo o query.log é possível ver uma linha indicando a execução da query acima:

É recomendável habilitar o log apenas para queries que ameaçam a disponibilidade da sua base. E é aí que entra o dbms.logs.query.threshold, ele é responsável por registrar consultas que demorem um X número de tempo, que é especificado no arquivo conf.log também.

Iremos configurá-lo com um tempo de 1000ms:

dbms.logs.query.enabled=true
dbms.logs.query.threshold=1000ms

PS.:Lembre-se que depois de cada mudança é necessário dar restart no Neo4j.

Feito isto, uma query que tenha um tempo menor que 1000ms não irá aparecer no log.

Há outras tags para controle do log, as mais importantes são:

dbms.logs.query.time_logging_enabled=true
Mostra o tempo de execução detalhada da consulta. Ex.:(planning: 272, waiting: 0)
dbms.track_query_cpu_time=true
Mostra o consumo de cpu. Ex.: cpu: 937
dbms.logs.query.page_logging_enabled=true
Resultados de páginas do log de execução. Ex.: 3715 page hits

Uma outra forma de permitir uma base mais estável é definir um tempo limite para uma transação no Neo4j, tendo em vista limitar um certo tempo para a execução da query.

dbms.transaction.timeout=1s

Irei inserir esta tag no neo4j.conf determinando que queries que passem de 1s sejam terminadas.

Exemplo de execução de uma query que não foi terminada no tempo de 1 segundo

PS.: Uma boa notícia é que este comando funciona para a versão community!

O Neo4j recomenda a utilização da tag dbms.lock.acquisition.timeout quando utilizado a tag do timeout, pois as queries usam um bloqueio para finalizar as transações, e como elas aguardam este bloqueio, pode ser que em algum momento este bloqueio não seja feito automaticamente e a transação pode não ser encerrada. Segundo eles, o timeout deve ser definido como um valor maior que o valor do tempo limite do bloqueio como no exemplo abaixo:

dbms.transaction.timeout=1s
dbms.lock.acquisition.timeout=10ms

Uma outra maneira de monitorar as transações é usando as queries nativas do Neo4j enterprise.

CALL dbms.listQueries()

Exibe as queries que estão sendo executadas no momento, é possível ver informações importantes como endereço de quem a executou, o status atual da query, a data e hora em que ela foi rodada, o usuário pertencente, dentre outras.

:queries

Permite a visualização das queries que estão sendo executadas também, porém com menos informações, mas com o acréscimo da possibilidade da finalização da transação.

Para finalizar uma query listada é preciso clicar no botão Kill na linha desejada e confirmar a exclusão, outro ponto interessante é a possibilidade de deixar esta visualização em tempo real com a opção de AUTO-REFRESH no canto inferior direito.

Outro modo de finalização da query é usando o comando CALL dbms.killQuery(‘query-id’), que funciona da mesma maneira que a forma visual, neste caso é necessário informar o id da query que pode ser encontrada no comando CALL dbms.listQueries().

CALL dbms.listTransactions()

Muito parecida com o comando CALL dbms.listQueries(), porém em um nível de transação, qualquer tipo de transação que esteja rodando no momento é mostrado aqui:

Importante salientar que estes comandos são definidos ao nível do usuário, por exemplo, o usuário definido como admin tem acesso à todas as transações, diferente do usuário com perfil normal que mostra somente as suas transações.

O Neo4j dá uma dica para automatizar as finalizações de queries longas usando a query abaixo:

CALL dbms.listQueries() YIELD query, elapsedTimeMillis, queryId, username
WHERE elapsedTimeMillis > 1000
WITH query, collect(queryId) AS q, username
CALL dbms.killQueries(q) YIELD queryId
RETURN query, queryId, username

Fazendo um teste rodando uma query que demore mais que o 1000ms configurado temos o seguinte retorno.

E aqui está o retorno da query sugerida pelo Neo4j:

Bom, chegamos ao final deste post, esperem que gostem, como referência usei informações disponibilizadas oficialmente no site do Neo4j e do curso gratuito Neo4j Admnistration Online Course.

https://neo4j.com/docs/operations-manual/3.5/monitoring/logging/query-logging/

https://neo4j.com/graphacademy/online-training/neo4j-administration/

See you!

--

--