Monitorando erros e eventos no log do PostgreSQL (grok_exporter)

Boa tarde, colegas e habretchiki! Hoje, gostaria de compartilhar com você uma pequena nota sobre como você pode organizar o monitoramento operacional de erros e eventos que aparecem no log do PostgreSQL usando o Prometheus e o exportador de métricas grok_exporter.

Devo dizer imediatamente que este é obviamente um caso especial de utilização deste exportador. Então, por que é necessário e quem pode estar interessado?

Introdução


Quem precisa disso?


Se o Prometheus já estiver presente na sua infraestrutura e criar uma infraestrutura separada para coletar e analisar logs, como ELK ou Greylog, for caro e impraticável (se não houver Prometheus, não há problema, é fácil e rápido de instalar).

A ferramenta será útil não apenas para DBAs, mas também para administradores de aplicativos, em geral, para todos aqueles que de alguma forma trabalham com logs de aplicativos. Ele permite que você obtenha rapidamente informações sobre comportamento independente e tenha um determinado ponto de referência para uma análise mais aprofundada da situação.

Para que serve tudo isso?


Os logs de monitoramento permitirão que você tenha uma imagem mais completa e responda mais rapidamente a problemas emergentes, seja: tentativas de autorização (incluindo as que não tiveram êxito), vários erros ou eventos específicos.

uma boa lista aqui, formada por categorias de eventos (consulte a seção Categorias de eventos de log), que pode ser usada para criar regras no Prometheus.

grok_exporter


O exportador de métricas grok_exporter permite ler dados não estruturados da origem, convertendo-os em dados estruturados, de acordo com as regras, e devolvê-los como métricas em um formato que o Prometheus entende.

O exportador foi criado à imagem de um plug-in no ELK plug-ins-filtros-grok , que permite usar um conjunto de modelos de plug-ins-filtros-grok como estão.

Instalação


A instalação é direta e simples. Para fazer isso, basta seguir o link e baixar a versão que você gosta (e sim, todas são pré-lançamento e as versões mais recentes ainda estão no estágio candidato a lançamento) e descompacte o arquivo resultante.

Como resultado, obtemos o seguinte conjunto:

grok_exporter-1.0.0.RC3.linux-amd64
├── patterns
│   ├── ruby
│   ├── redis
│   ├── rails
│   ├── postgresql
│   ├── nagios
│   ├── mongodb
│   ├── mcollective-patterns
│   ├── mcollective
│   ├── linux-syslog
│   ├── junos
│   ├── java
│   ├── haproxy
│   ├── grok-patterns
│   ├── firewalls
│   ├── exim
│   ├── bro
│   ├── bacula
│   └── aws
├── grok_exporter
└── example
    ├── exim-rejected-RCPT-examples.log
    ├── config.yml
    └── config_logstash_http_input_ipv6.yml

Onde:

  • grok_exporter - executável do exportador
  • padrões - contém um conjunto de padrões
  • exemplo - contém um conjunto de dados de teste e um arquivo de configuração de exemplo

Para iniciar o exportador, basta executar o arquivo executável. O arquivo de configuração config.yml é pesquisado no diretório de onde o aplicativo é iniciado ou seu local é especificado pela opção -config



Configuração e preparação para o trabalho


PostgreSQL


, PostgreSQL. :


  1. grok_exporter . , pg_reload_conf.

    • alter system set log_directory to '/var/log/postgresql'; 
    • alter system set log_file_mode to '0644';
  2. log_line_prefix, . , . :

     alter system set log_line_prefix to '%t datname:%d,client:%h,app:%a,usename:%u,session:%c ';

grok_exporter


Primeiro, editaremos o modelo patterns / postgresql de acordo com o formato do nosso arquivo de log e adicionaremos construções auxiliares. Enfatizo mais uma vez que a sintaxe dos modelos é totalmente consistente com a usada em plugins-filters-grok , portanto, para todos os problemas relacionados à sintaxe, você pode e deve ir à documentação. Então, vamos trazer nosso modelo para o PostgreSQL para o formulário (o arquivo patterns / grok-patterns já contém um grande conjunto de modelos básicos):

#     - postgresql
PG_TIMESTAMP %{YEAR}-%{MONTHNUM}-%{MONTHDAY} %{HOUR}:%{MINUTE}:%{SECOND} [A-Z]{3,4}

#    
PG_ERROR_PATTERN (ERROR|WARNING|FATAL|PANIC)

# log_line_prefix   - PostgreSQL
PG_PREFIX %{PG_TIMESTAMP} datname:(%{DATA:datname})?,client:(%{DATA:client_host})?,app:(%{DATA:app_name})?,usename:(%{USER:usename})?,session:(%{DATA:session})?

#    log_level     
PG_ERROR_LEVEL %{PG_ERROR_PATTERN:log_level}:

#    
PG_EVENT_AUTH LOG:  connection authorized:

#      SIGHUP,   
PG_EVENT_RELOAD LOG:  received SIGHUP, reloading configuration files

O design ()?permite indicar que o valor é opcional.


Aqui, em detalhes suficientes, com exemplos, é descrito o processo de criação de um arquivo de configuração. Abaixo, apenas o que será usado é fornecido.


Uma breve descrição do arquivo de configuração (da documentação)
O arquivo de configuração é um arquivo no formato YAML e é dividido em seções:

  1. global - configurações globais
    • config_version — . grok_exporter, ≥ 1.0.0.RC3, 3
      retention_check_interval — . , .

  2. input — .

    • type — . : file, stdin, webhook. , file;
    • path|paths — c -(-). ;
    • readall — , .
      true — , . Prometheus .
      false — , grok_exporter;
    • fail_on_missing_logfile — -. true — , ;
  3. imports — , , . 2, , grok.

    • typegrok_patterns () metrics ();
    • file|dir — . , .

  4. grok_patterns — , .
  5. metrics — . — counter, gauge, histogram, or summary.
  6. server

      protocol: https
      host: localhost
      port: 9144
      path: /metrics
      cert: /path/to/cert
      key: /path/to/key
    



Na sintaxe da 3ª versão do arquivo de configuração, tornou-se possível importar métricas de arquivos individuais, permitindo agrupar as métricas por objetivo.

Em seguida, crie o arquivo de configuração base config.yml . Nele, definimos o caminho para os arquivos de log do PostgreSQL por máscara; importar modelos do diretório patterns e métricas do diretório metrics.d ; indicamos por qual protocolo e em qual porta é necessário aplicar as métricas.

config.yml
  config_version: 3
  retention_check_interval: 10s
input:
  type: file
  path: /var/log/postgresql/postgresql-*.log
  readall: false
imports:
- type: grok_patterns
  dir: ./patterns
- type: metrics
  dir: ./metrics.d
server:
  protocol: http
  port: 9144


, metrics.d postgresql.yml, .

, , .. ( retention, - 2 30 ) , . retention_check_interval.

, :

  • , ;
  • — GAUGE COUNTER, . .. GAUGE, ;
  • Se cumulativo for definido como verdadeiro, os valores das métricas com o mesmo conjunto de rótulos serão somados, que é o comportamento esperado. Uma situação inesperada pode surgir quando, na segunda solicitação, você pode obter a soma dos valores na solicitação mais o valor anterior.
  • Se cumulativo for definido como falso, se houver métricas com o mesmo conjunto de rótulos, apenas o último valor será exibido;

Foram muitas as cartas confusas e incompreensíveis em alguns lugares, mas tentarei divulgar isso nos exemplos abaixo.

E assim, temos um arquivo de configuração que pode retornar quatro métricas, três contadores e um valor arbitrário. De fato, os três primeiros consideram o número de correspondências do campo do modelo de correspondência com as seqüências recebidas da fonte, a quarta - exibe a soma dos valores.

postgresql.yaml
#  - 
- type:   counter
  name:   pg_grok_error_count
  help:   Count of line error
  match:  '%{PG_PREFIX} %{PG_ERROR_LEVEL}  %{GREEDYDATA:message}'
  labels:
    log_level:   '{{.log_level}}'
    usename:     '{{.usename}}'
    datname:     '{{.datname}}'
    app_name:    '{{.app_name}}'
    client_host: '{{.client_host}}'
    message:     '{{.message}}'

#   
- type:   counter
  name:   pg_grok_auth_succes_count
  help:   Count of connections authorized
  match:  '%{PG_PREFIX} %{PG_EVENT_AUTH}'
  labels:
    usename:     '{{.usename}}'
    datname:     '{{.datname}}'
    app_name:    '{{.app_name}}'
    client_host: '{{.client_host}}'

#   
- type:   counter
  name:   pg_grok_reload_conf_count
  help:   Count of call pg_reload_conf
  match:  '%{PG_PREFIX} %{PG_EVENT_RELOAD}'
  labels:
    session:     '{{.session}}'

#   
- type:       gauge
  name:       pg_grok_tpm_file_size_bytes
  help:       Size of tmp file created by time
  match:      '%{PG_PREFIX} %{PG_EVENT_TMP_FILE}'
  value:      '{{.size}}'
  cumulative: true
  retention:  5s
  labels:
    static:     'temp_file'


Prática


pg_grok_error_count


A métrica conta o número de eventos ERRO, AVISO, FATAL e PÂNICO, de acordo com o padrão. Pode ser útil para monitoramento e aviso em caso de emergência. Por exemplo, você pode configurar um alerta nos seguintes casos: tentativas de autorização sem êxito, excedendo o limite do número de erros por unidade de tempo ou quando o banco de dados está em um estado de recuperação após uma falha e muito mais ( Categorias de Eventos de Log ).

Por exemplo, configuraremos um alerta sobre tentativas de autorização com falha. Um exemplo de uma tentativa malsucedida de login no arquivo de log do PostgreSQL é semelhante a este:

2020-04-20 23:34:53 AEST datname:test,client:127.0.0.1,app:[unknown],usename:test_user,session:5e9da4fd.733 FATAL:  password authentication failed for user "test_user"
2020-04-20 23:34:53 AEST datname:test,client:127.0.0.1,app:[unknown],usename:test_user,session:5e9da4fd.733 DETAIL:  Password does not match for user "test_user".
        Connection matched pg_hba.conf line 86: "host    all             all             127.0.0.1/32            md5"

Na saída do grok_exporter, as tentativas de autenticação com falha podem ser identificadas pelo rótulo da mensagem que contém a autenticação da senha de substring com falha para ... :

pg_grok_error_count{app_name="[unknown]",client_host="127.0.0.1",datname="postgres",log_level="FATAL",message="password authentication failed for user "postgres"", usename="postgres"} 15
pg_grok_error_count{app_name="[unknown]",client_host="127.0.0.1",datname="test",log_level="FATAL",message="password authentication failed for user \"test_user\"",usename="test_user"} 5

Os dados obtidos ajudarão a formular uma regra para o Prometheus. A sensibilidade pode ser ajustada com base em suas próprias realidades.

groups:
- name: AuthAlert
  rules:
  - alert: AuthFail
    expr: sum(rate(pg_grok_error_count{message=~"password authentication failed for user.*"}[1m])) by (instance) > 0.1
    for: 30s
    labels:
      severity: warning
    annotations:
      summary: Too many fail authorization for {{ $labels.instance }}

pg_grok_reload_conf_count


Da mesma forma, você pode acompanhar a execução do comando pg_reload_conf. Além disso, vale a pena prestar atenção na lista de rótulos, ou melhor, no fato de que apenas um rótulo de sessão é usado. Isso se deve ao fato de o evento ser criado como parte do processo do servidor, e não da sessão do usuário.

No arquivo de log do PostgreSQL, esse evento se parece com o seguinte:

2020-04-21 01:20:26 AEST datname:,client:,app:,usename:,session:5e9d9371.564 LOG:  received SIGHUP, reloading configuration files

Essa. pode-se ver que os rótulos usados ​​no exemplo anterior estão vazios. Nesse caso, usaremos o identificador da sessão para identificação e ele não será alterado até que a instância do PostgreSQL seja parada ou reiniciada.

Uma situação semelhante será para outros casos semelhantes, por exemplo, parando uma instância:

2020-04-21 01:32:52 AEST datname:,client:,app:,usename:,session:5e9d9371.564 LOG:  received fast shutdown request
2020-04-21 01:32:53 AEST datname:,client:,app:,usename:,session:5e9d9371.564 LOG:  database system is shut down

Na saída do grok_exporter, obtemos:

# HELP pg_grok_reload_conf_count Count of call pg_reload_conf
# TYPE pg_grok_reload_conf_count counter
pg_grok_reload_conf_count{session="5e9d9371.564"} 5

A regra para a notificação, não há nenhum ponto em trazê-lo à tona, será semelhante ao discutido acima.

pg_grok_tpm_file_size_bytes


Imediatamente, faça uma reserva de que este exemplo é da categoria "cavalo esférico no vácuo" e é fornecido em maior medida para mostrar como você pode alterar o comportamento das métricas.

O comportamento das métricas do medidor pode ser influenciado pela alteração dos parâmetros de retenção e cumulativos . De fato, diferentemente de um contador regular, que considera o número de linhas que correspondem ao padrão de correspondência, o medidor permite operar com dados do arquivo de log. Acontece que podemos acumulá-lo aumentando ou diminuindo o valor obtido, ou usá-lo como um valor que muda arbitrariamente. Assim, no primeiro caso, estaremos interessados ​​na magnitude do incremento, no segundo - o valor em si.

Vejamos alguns exemplos:

  1. , (cumulative: true). , , . , retention_check_interval + retention <= scrape_interval — Prometheus.

    - PostgreSQL :

    2020-04-21 02:51:15 AEST datname:,client:,app:,usename:,session:5e9dd2f3.1278 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4728.0", size 46931968
    2020-04-21 02:51:15 AEST datname:,client:,app:,usename:,session:5e9dd2f3.1279 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4729.0", size 46276608
    2020-04-21 02:51:15 AEST datname:postgres,client:[local],app:psql,usename:postgres,session:5e9dc0a8.112c LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4396.14", size 47194112
    

    , :

    pg_grok_tpm_file_size_bytes{static="temp_file"} 1.40402688e+08
    

    .

    , :

    pg_grok_tpm_file_size_bytes{static="temp_file"} 1.1911168e+07
    

    : , .
  2. , , (retention) (cumulative: true)
    , - PostgreSQL :


    2020-04-21 03:03:40 AEST datname:,client:,app:,usename:,session:5e9dd5dc.12c6 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4806.0", size 46260224
    2020-04-21 03:03:40 AEST datname:,client:,app:,usename:,session:5e9dd5dc.12c5 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4805.0", size 46833664
    2020-04-21 03:03:40 AEST datname:postgres,client:[local],app:psql,usename:postgres,session:5e9dc0a8.112c LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4396.15", size 47316992
    

    :

    pg_grok_tpm_file_size_bytes{static="temp_file"} 1.40402688e+08
    

    , . :

    2020-04-21 03:10:40 AEST datname:,client:,app:,usename:,session:5e9dd76e.1325 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4901.0", size 46776320
    2020-04-21 03:10:40 AEST datname:,client:,app:,usename:,session:5e9dd76e.1324 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4900.0", size 45768704
    2020-04-21 03:10:40 AEST datname:postgres,client:[local],app:psql,usename:postgres,session:5e9dc0a8.112c LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4396.18", size 47841280
    

    :

    pg_grok_tpm_file_size_bytes{static="temp_file"} 2.80772608e+08
    

    , . , .
  3. , cumulative false , .

    :

    2020-04-21 03:41:04 AEST datname:,client:,app:,usename:,session:5e9ddea4.1393 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp5011.0", size 11763712
    2020-04-21 03:41:04 AEST datname:,client:,app:,usename:,session:5e9ddea4.1392 LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp5010.0", size 11501568
    2020-04-21 03:41:04 AEST datname:postgres,client:[local],app:psql,usename:postgres,session:5e9dc0a8.112c LOG:  temporary file: path "base/pgsql_tmp/pgsql_tmp4396.19", size 11911168
    

    :

    # HELP pg_grok_tpm_file_size_bytes Size of tmp file created by time
    # TYPE pg_grok_tpm_file_size_bytes gauge
    pg_grok_tpm_file_size_bytes{static="temp_file"} 1.1911168e+07
    

    , . , .


Sem dúvida, o grok_exporter é a ferramenta certa para monitorar aplicativos. Ele permite que você examine o "difícil acesso", para monitorar sistemas, locais e enriquecer o monitoramento com métricas adicionais (controle), mantendo-se bastante simples, funcional e leve.

Ao mesmo tempo, também será útil para os desenvolvedores, pois fornece pelo menos acesso indireto aos logs do aplicativo por meio de um sistema de monitoramento. Onde você pode correlacionar métricas de várias fontes.

Outro ponto positivo é que o projeto está em desenvolvimento e adquire novas funcionalidades.

Por sua vez, espero que esta breve nota seja útil, inclusive para o próprio projeto. Mais estrelas, mais trabalho divertido!

Obrigado a todos!

Source: https://habr.com/ru/post/undefined/


All Articles