Traces et journalisation
Requêtes à la base de données
D’une façon générale, les outils d’ORM peuvent paraître parfois obscurs sur leur façon de produire les ordres SQL, ou bien, même si on pense avoir compris la documentation et écrit un code correct, on voudrait se rassurer sur son interprétation en ayant une visibilité sur l’ordre SQL construit. Ce chapitre va donner quelques moyens pour parvenir à voir cette construction et pour mieux comprendre comment son exécution est planifiée. Accéder à cette connaissance peut parfois aider à diagnostiquer des dysfonctionnements ou des faiblesses de performances.
1. Plan d’exécution
Le plan d’exécution d’un ordre SQL est un rapport fourni par le gestionnaire de base de données pour détailler de quelle façon celui-ci compte exécuter cet ordre. La plupart du temps, on ne se préoccupe pas d’orienter ses choix et on se fie à ses algorithmes pour faire au mieux, même s’il faut reconnaître que c’est plutôt par absence de maîtrise des options qu’il faudrait poser. L’observation d’un plan doit permettre de comprendre par exemple : si un index est mis à contribution et lequel lorsque plusieurs peuvent satisfaire au besoin ; quelles sont éventuellement les jointures mises en œuvre ; quels sont les volumes estimés et les efforts de traitement (plus difficiles à comprendre).
Il faut admettre que c’est par nature un rapport technique, souvent abscons et qui tourne au jargon pour un lecteur occasionnel.
Hors Django
Pour aborder le sujet, commençons par faire des manipulations avec les outils disponibles directement sous le gestionnaire PostgreSQL et son pgAdmin.
Avec pgAdmin, sur la table messenger_message, il faut ouvrir un onglet d’interrogation (menu Tools/Query Tool ou clic droit et Query Tool…), car l’onglet habituel Edit Data ne donne pas accès à l’outil visé.
Copiez cet ordre SQL :
SELECT * FROM messenger_message WHERE sender_id > 1;
Demandez un Explain (F7) dans le sous-menu des exécutions :
On peut se passer des Explain Options > Verbose, Costs, Buffers, Timing, car elles ne vont pas être déterminantes...
Pose de traces personnalisées
Dans la section précédente, il a été exploité des informations mises à disposition par un enregistreur intégré, mais tout est basé sur le module standard de journalisation de Python. Il suffit donc de suivre ce schéma d’implémentation pour parsemer son propre code avec des points de traces.
Des traces aident à remplir des objectifs variés, dont voici quelques exemples :
-
S’assurer en cours de développement que les comportements se réalisent conformément aux prévisions.
-
Mémoriser des situations exceptionnelles dont on ne sait pas quoi faire et qui en principe ne devraient jamais arriver.
-
Déclencher des actions de communication à propos d’événements notables, typiquement par un envoi de courriel. On pense naturellement à des cas de défauts attendus, mais il peut aussi bien s’agir de circonstances positives.
-
Disposer de métriques sur l’usage de l’application.
-
Garder un œil sur la bonne santé de l’application et sur son environnement (par exemple ressources disponibles, quotas, qualité du réseau, etc.).
Pour disposer d’un système de traces efficace, maîtrisé et qui apporte une réelle valeur, il faut notamment réfléchir à ces points :
-
Placer les observations à des endroits stratégiques.
-
Doser les quantités : pas assez de traces engendre de la frustration, car on n’a pas la visibilité espérée, et trop de traces noie le lecteur dans du superflu pouvant aller jusqu’à le décourager.
-
Être à la fois concis et ne pas basculer dans le sibyllin.
-
Faire une savante répartition entre les niveaux de gravité, autant pour les productions des messages de trace que pour leur filtrage et leur orientation vers des consommateurs.
-
En cas d’écriture sur un espace de stockage, prévoir un mécanisme automatique pour faire du nettoyage afin d’éviter de tomber dans le piège du disque plein.
1. Noms des enregistreurs
Un enregistreur est identifié par un nom, à la fois pour sa configuration et pour son emploi. Prendre le nom fourni par la variable __name__, c’est-à-dire le nom du module...