Surveillance des erreurs et des événements dans le journal PostgreSQL (grok_exporter)

Bonjour, collègues et habretchiki! Aujourd'hui, je voudrais partager avec vous une petite note sur la façon dont vous pouvez organiser la surveillance opérationnelle des erreurs et des événements qui apparaissent dans le journal PostgreSQL en utilisant Prometheus et l'exportateur de métriques grok_exporter.

Je dois dire tout de suite qu'il s'agit bien sûr d'un cas particulier d'utilisation de cet exportateur. Alors pourquoi est-il nécessaire et qui pourrait être intéressé?

introduction


Qui en a besoin?


Si Prometheus est déjà présent dans votre infrastructure et que la création d'une infrastructure distincte pour la collecte et l'analyse des journaux, tels que ELK ou Greylog, est coûteuse et peu pratique (s'il n'y a pas de Prometheus, ce n'est pas un problème, c'est facile et rapide à installer).

L'outil sera utile non seulement pour les administrateurs de base de données, mais aussi pour les administrateurs d'application, en général, pour tous ceux qui travaillent d'une manière ou d'une autre avec les journaux d'application. Il vous permet d'obtenir rapidement des informations sur le comportement des indépendants et d'avoir un certain point de référence pour une analyse plus approfondie de la situation.

À quoi tout cela sert-il?


La surveillance des journaux vous permettra d'avoir une image plus complète et de répondre plus rapidement aux problèmes émergents, qu'il s'agisse de tentatives d'autorisation (y compris infructueuses), de diverses erreurs ou d'événements spécifiques.

Il y a une bonne liste ici, formée par catégories d'événements (voir la section Log Event Categories), elle peut être utilisée pour créer des règles dans Prometheus.

grok_exporter


L'exportateur de métriques grok_exporter vous permet de lire les données non structurées de la source, de les convertir en données structurées, conformément aux règles, et de les renvoyer sous forme de métriques dans un format que Prometheus comprend.

L'exportateur a été créé à l'image d'un plug-in dans ELK plugins-filters-grok , qui vous permet d'utiliser un ensemble de modèles de plugins-filters-grok tels quels.

Installation


L'installation est simple et directe. Pour ce faire, il suffit de suivre le lien et de télécharger la version que vous aimez (et oui, ce sont toutes des versions préliminaires, et les dernières versions sont encore au stade de la version candidate) et décompressez l'archive résultante.

En conséquence, nous obtenons l'ensemble suivant:

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

où:

  • grok_exporter - exécutable d'exportateur
  • motifs - contient un ensemble de motifs
  • exemple - contient un ensemble de données de test et un exemple de fichier de configuration

Pour démarrer l'exportateur, exécutez simplement le fichier exécutable. Le fichier de configuration config.yml est recherché dans le répertoire à partir duquel l'application est lancée ou son emplacement est spécifié par l'option -config



Installation et préparation au travail


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


Tout d'abord, nous éditerons le modèle patterns / postgresql conformément au format de notre fichier journal et ajouterons des constructions auxiliaires. Je souligne une fois de plus que la syntaxe des modèles est entièrement cohérente avec celle utilisée dans plugins-filters-grok , par conséquent, pour tous les problèmes liés à la syntaxe, vous pouvez et devez consulter sa documentation. Alors, apportons notre modèle pour PostgreSQL au formulaire (le fichier patterns / grok-patterns contient déjà un grand ensemble de modèles de base):

#     - 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

La conception ()?vous permet d'indiquer que la valeur est facultative.


Ici, avec suffisamment d'exemples, avec des exemples, le processus de création d'un fichier de configuration est décrit. Ci-dessous, seul ce qui sera utilisé est indiqué.


Une brève description du fichier de configuration (à partir de la documentation)
Le fichier de configuration est un fichier au format YAML et est divisé en sections:

  1. global - paramètres globaux
    • 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
    



Dans la syntaxe de la 3ème version du fichier de configuration, il est devenu possible d'importer des métriques à partir de fichiers individuels, cela vous permettra de regrouper les métriques par objectif.

Ensuite, créez le fichier de configuration de base config.yml . Dans ce document, nous: définissons le chemin d'accès aux fichiers journaux de PostgreSQL par masque; importer des modèles à partir du répertoire des modèles et des métriques à partir du répertoire metrics.d ; nous indiquons par quel protocole et sur quel port il est nécessaire de demander des métriques.

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, ;
  • Si cumulatif est défini sur true, les valeurs des métriques avec le même ensemble d'étiquettes seront additionnées, ce qui correspond au comportement attendu. Une situation inattendue peut survenir lorsque, à la deuxième demande, vous pouvez obtenir la somme des valeurs de la demande plus la valeur précédente.
  • Si cumulatif est défini sur false, s'il existe des métriques avec le même ensemble d'étiquettes, seule la dernière valeur sera affichée;

Il s'est avéré que beaucoup de lettres, déroutantes et incompréhensibles par endroits, mais je vais essayer de le révéler dans les exemples ci-dessous.

Et donc, nous avons un fichier de configuration qui peut retourner quatre mesures, trois compteurs et une valeur arbitraire. En fait, les trois premiers considèrent le nombre de correspondances du champ de modèle de correspondance avec les chaînes reçues de la source, le quatrième - affiche la somme des valeurs.

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'


Entraine toi


pg_grok_error_count


La métrique compte le nombre d'événements ERREUR, AVERTISSEMENT, FATAL et PANIQUE, selon le modèle. Il peut être utile pour la surveillance et l'alerte en cas d'urgence. Par exemple, vous pouvez configurer une alerte dans les cas suivants: tentatives d'autorisation infructueuse, dépassement du seuil du nombre d'erreurs par unité de temps, ou lorsque la base de données est dans un état de récupération après un échec, et bien plus encore ( catégories d'événements de journal ).

Par exemple, nous allons configurer une alerte en cas d'échec des tentatives d'autorisation. Un exemple d'une tentative de connexion infructueuse dans le fichier journal de PostgreSQL ressemble à ceci:

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"

Dans la sortie de grok_exporter, les tentatives d'authentification échouées peuvent être identifiées par l'étiquette de message contenant l' authentification par mot de passe de la sous-chaîne a échoué pour ... :

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

Les données obtenues aideront à formuler une règle pour Prométhée. La sensibilité peut être ajustée en fonction de vos propres réalités.

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


De même, vous pouvez suivre l'exécution de la commande pg_reload_conf. De plus, il convient de prêter attention à la liste des libellés, ou plutôt, au fait qu'un seul libellé de session est utilisé. Cela est dû au fait que l'événement est créé dans le cadre du processus serveur et non de la session utilisateur.

Dans le fichier journal de PostgreSQL, cet événement ressemble à ceci:

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

Ceux. on peut voir que les étiquettes utilisées dans l'exemple précédent sont vides. Dans ce cas, nous utiliserons l'identifiant de session pour l'identification, et il ne changera pas tant que l'instance de PostgreSQL n'aura pas été arrêtée ou redémarrée.

Une situation similaire sera pour d'autres cas similaires, par exemple, l'arrêt d'une instance:

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

Dans la sortie de grok_exporter, nous obtenons:

# 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

La règle de notification, cela ne sert à rien de l’évoquer, elle sera similaire à celle évoquée plus haut.

pg_grok_tpm_file_size_bytes


Faites immédiatement une réserve que cet exemple soit de la catégorie des «chevaux sphériques dans le vide» et soit donné dans une plus large mesure afin de montrer comment vous pouvez changer le comportement des métriques.

Le comportement des mesures de jauge peut être influencé par la modification des paramètres de rétention et cumulatifs . En effet, contrairement à un compteur classique, qui considère le nombre de lignes correspondant au modèle de correspondance, la jauge vous permet d'opérer sur les données du fichier journal. Il s'avère que nous pouvons l'accumuler en augmentant ou en diminuant de la valeur obtenue, ou l'utiliser comme une valeur changeant arbitrairement. Ainsi, dans le premier cas, nous nous intéresserons à l'ampleur de l'incrément, dans le second - la valeur en soi.

Regardons quelques exemples:

  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
    

    , . , .


Sans aucun doute grok_exporter est le bon outil pour surveiller les applications. Il permet de se pencher sur les "difficiles d'accès", pour les systèmes de surveillance, les lieux et d'enrichir la surveillance avec des métriques (de contrôle) supplémentaires, tout en restant assez simple, fonctionnel et léger.

Dans le même temps, il sera également utile pour les développeurs, car il donne au moins un accès indirect aux journaux d'application via un système de surveillance. Où vous pouvez corréler les métriques de différentes sources.

Un autre point positif est que le projet se développe et acquiert de nouvelles fonctionnalités.

En retour, j'espère que cette courte note sera utile, y compris pour le projet lui-même. Plus d'étoiles, plus de travail amusant!

Merci à tous!

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


All Articles