1024pix/pix-db-stats

🐛 Les requĂȘtes SQL au texte trop long gĂ©nĂšrent des lignes de log trop longues pour ĂȘtre traitĂ©es

Closed this issue · 1 comments

💣 Problùme

Quand les statistiques de requĂȘtes collectĂ©es pĂ©riodiquement (Ă©vĂ©nements db-query-stats) incluent une requĂȘte donc le texte SQL dĂ©passe une certaine taille, la ligne de log JSON correspondante qui est gĂ©nĂ©rĂ©e par pix-db-stats se trouve "tronçonnĂ©e" en plusieurs lignes et Ă  l'arrivĂ©e sur Datadog elle n'est pas traitĂ©e puisque ce n'est plus du JSON valide. Ces requĂȘtes disparaissent donc complĂštement des statistiques — alors que leur taille mĂȘme devrait les rendre candidates Ă  un examen approfondi).

image

🔬 Analyse

La limite de taille documentée chez Datadog est de 1 Mo par ligne, et on est loin de cette taille pour les lignes qui posent problÚme. En revanche, en allant voir les logs à la source chez Scalingo (scalingo --region osc-secnum-fr1 -a pix-db-stats-production logs -n 100000|sort|awk '/\] [^{]/{print substr($0, 1, 100), length($0)}' pour lister les lignes ne commençant pas par { avec leur longueur), je constate que le découpage des lignes a déjà lieu chez Scalingo, à une longueur de 16384 (2^14) caractÚres. Bien que cette limitation ne semble pas documentée, il paraßt trÚs vraisemblable qu'elle soit appliquée par Scalingo et non dans l'application qui utilise simplement un console.log pour générer ces lignes :

console.log(JSON.stringify({ event, app, data }));

💡 Suggestion de solution

S'assurer que les lignes de log restent bien en-dessous des 16384 caractĂšres. C'est probablement compliquĂ© de trouver une solution gĂ©nĂ©rique qui pourrait s'appliquer au niveau du logger — on pourrait imaginer une variante de JSON.stringify qui prenne un paramĂštre de longueur maximale et qui garantisse la gĂ©nĂ©ration d'un JSON valide dans cette limite en appliquant par exemple un heuristique de troncature des chaĂźnes les plus longues
 c'est un programme de recherche intĂ©ressant mais peut-ĂȘtre excessif ici.

Pragmatiquement, appliquer une limite raisonnable Ă  la chaĂźne de requĂȘte SQL capturĂ©e ici :

queryStats.forEach((query) => logger.info({ event: 'db-query-stats', app: scalingoApp, data: query }))

devrait ĂȘtre suffisant. La partie tronquĂ©e pourrait ĂȘtre remplacĂ©e par 
, ou Ă©ventuellement de maniĂšre plus subtile par un hash des donnĂ©es tronquĂ©es afin d'Ă©viter de confondre plusieurs requĂȘtes qui auraient un prĂ©fixe commun.

On a changé l'événement db-query-stat pour renvoyer seulement ce qui nous intéresse. Nous n'avons plus ces problÚmes