Maison > interface Web > js tutoriel > Journaux tampons et vidage automatique en cas d'erreur avec Powertools pour Lambda

Journaux tampons et vidage automatique en cas d'erreur avec Powertools pour Lambda

Susan Sarandon
Libérer: 2024-12-19 20:23:15
original
262 Les gens l'ont consulté

Buffer Logs and Flush Automatically on Error with Powertools for Lambda

La dernière version d'AWS Powertools for Lambda facilite l'extension du Logger avec des fonctionnalités personnalisées :

La classe Logger est désormais plus extensible
Vous pouvez désormais remplacer les méthodes Logger createAndPopulateLogItem, printLog et processLogItem, qui étaient auparavant privées. Cela vous permet d'étendre le Logger et d'ajouter de nouvelles fonctionnalités, par exemple, implémenter votre propre tampon de messages.
Sortie v2.12.0

J'utilise cette nouvelle extensibilité pour implémenter une fonctionnalité utile : la mise en mémoire tampon et le vidage des journaux. L'idée est simple : dans un environnement de production, nous enregistrons généralement uniquement les informations importantes, telles que les avertissements et les erreurs, car l'espace de journalisation peut coûter cher et créer du bruit. Cependant, lorsqu'une erreur se produit, nous voulons toutes les informations possibles : tous ces journaux de débogage et d'informations dispersés dans une fonction doivent être disponibles. Mais ce n’est pas le cas parce que nous avons fixé notre niveau de journalisation trop bas.

Tampon et rinçage

Et si nous collections tous ces journaux de débogage et d'informations en interne, et si un événement important se produit comme une erreur, nous les imprimions sur la console ? Je classe les journaux en deux catégories : les journaux de bas niveau et les journaux de haut niveau. Si notre niveau de journalisation configuré est WARN, un journal DEBUG ou INFO serait de bas niveau et ERROR serait un journal de haut niveau.

Maintenant, lorsque nous imprimons un journal de bas niveau, au lieu de le supprimer tel qu'il est actuellement, nous mettons le journal en mémoire tampon dans une liste interne. Dès que nous avons un journal de haut niveau, nous vidons tous les journaux mis en mémoire tampon vers la console.

Mise en œuvre

Pour ajouter cette fonctionnalité, nous créons une nouvelle classe qui étend la classe Logger de Powertools et remplaçons processLogItem(). Il s'agit de la méthode centrale appelée par les différentes méthodes de journalisation comme logger.debug(). L'implémentation d'origine imprime l'élément de journal sur la console s'il se trouve au bon niveau. En remplaçant cette méthode, nous pouvons ajouter notre logique spéciale de mise en mémoire tampon et de vidage des journaux en fonction du niveau de journalisation.

import { LogItem, Logger as PowertoolsLogger } from '@aws-lambda-powertools/logger';
import type { LogItemExtraInput, LogItemMessage } from '@aws-lambda-powertools/logger/types';

export class Logger extends PowertoolsLogger {
  #buffer: Record<string, Array<[number, string]>> = {};

  get buffer(): Record<string, Array<[number, string]>> {
    return this.#buffer;
  }

  protected override processLogItem(logLevel: number, input: LogItemMessage, extraInput: LogItemExtraInput): void {
    const xRayTraceId = this['envVarsService'].getXrayTraceId() as string;

    // Flush buffer when log level is higher than the configured log level
    if (logLevel > this.level && xRayTraceId) {
      const buffer = this.#buffer[xRayTraceId] ?? [];

      // Print all log items in the buffer
      if (buffer.length) this.info(`Flushing buffer with ${buffer.length} log items`);

      for (const [bufferLogLevel, bufferLogItem] of buffer) {
        // Create a new LogItem from the stringified log item
        this.printLog(bufferLogLevel, new LogItem(JSON.parse(bufferLogItem)));
      }

      // Clear the buffer after flushing
      // This also removes entries from other X-Ray trace IDs
      this.#buffer = {};
    }

    // Buffer the log item when log level is lower than the configured log level
    if (logLevel < this.level && xRayTraceId) {
      const buffer = this.#buffer[xRayTraceId] ?? [];
      // Add the stringified log item to the buffer
      // Serializing the log item ensures it is not mutated after being added to the buffer
      buffer.push([logLevel, JSON.stringify(this.createAndPopulateLogItem(logLevel, input, extraInput))]);

      // Update the buffer with the new log item
      // This also removes other X-Ray trace IDs from the buffer
      this.#buffer = {
        [xRayTraceId]: buffer,
      };
    }

    // Call the parent method to ensure the log item is processed
    super.processLogItem(logLevel, input, extraInput);
  }
}
Copier après la connexion
Copier après la connexion

Vous pourriez vous demander pourquoi nous utilisons l'identifiant X-Ray Trace ici. Il est courant d'instancier le Logger en dehors de la fonction de gestionnaire. Toutefois, étant donné que l'environnement d'exécution Lambda est réutilisé pour des appels potentiellement multiples, le tampon peut contenir des éléments de journal des appels précédents. C'est la raison pour laquelle le tampon est implémenté comme un objet plutôt que comme un simple tableau. Nous utilisons l'ID de trace X-Ray comme identifiant pour mettre en mémoire tampon uniquement les éléments de journal provenant de la même invocation.
Le tampon est implémenté comme un objet plutôt que comme un simple tableau. Lorsque le tampon est vidé, nous pouvons simplement réinitialiser l'objet et donc purger les éléments des autres invocations.

Tester localement

Vérifions rapidement la mise en œuvre localement :

// set X-Ray Trace ID manually if running locally
process.env._X_AMZN_TRACE_ID = '1-abcdef12-3456abcdef123456abcdef12';

// log level = WARN
const logger = new Logger({ logLevel: 'WARN' });

logger.debug('debug'); // < log level
logger.info('info');   // < log level
logger.warn('warn');   // = log level
logger.error('error'); // > log level
Copier après la connexion

Voici le résultat que nous obtenons :

import { LogItem, Logger as PowertoolsLogger } from '@aws-lambda-powertools/logger';
import type { LogItemExtraInput, LogItemMessage } from '@aws-lambda-powertools/logger/types';

export class Logger extends PowertoolsLogger {
  #buffer: Record<string, Array<[number, string]>> = {};

  get buffer(): Record<string, Array<[number, string]>> {
    return this.#buffer;
  }

  protected override processLogItem(logLevel: number, input: LogItemMessage, extraInput: LogItemExtraInput): void {
    const xRayTraceId = this['envVarsService'].getXrayTraceId() as string;

    // Flush buffer when log level is higher than the configured log level
    if (logLevel > this.level && xRayTraceId) {
      const buffer = this.#buffer[xRayTraceId] ?? [];

      // Print all log items in the buffer
      if (buffer.length) this.info(`Flushing buffer with ${buffer.length} log items`);

      for (const [bufferLogLevel, bufferLogItem] of buffer) {
        // Create a new LogItem from the stringified log item
        this.printLog(bufferLogLevel, new LogItem(JSON.parse(bufferLogItem)));
      }

      // Clear the buffer after flushing
      // This also removes entries from other X-Ray trace IDs
      this.#buffer = {};
    }

    // Buffer the log item when log level is lower than the configured log level
    if (logLevel < this.level && xRayTraceId) {
      const buffer = this.#buffer[xRayTraceId] ?? [];
      // Add the stringified log item to the buffer
      // Serializing the log item ensures it is not mutated after being added to the buffer
      buffer.push([logLevel, JSON.stringify(this.createAndPopulateLogItem(logLevel, input, extraInput))]);

      // Update the buffer with the new log item
      // This also removes other X-Ray trace IDs from the buffer
      this.#buffer = {
        [xRayTraceId]: buffer,
      };
    }

    // Call the parent method to ensure the log item is processed
    super.processLogItem(logLevel, input, extraInput);
  }
}
Copier après la connexion
Copier après la connexion

L'avertissement est le premier message car les journaux de débogage et d'informations ont été mis en mémoire tampon. Lorsque l'erreur a été enregistrée, nous avons vidé les journaux mis en mémoire tampon (et imprimé une information) avant que l'erreur ne soit réellement imprimée.

Demande de commentaires

Mon implémentation naïve comporte quelques mises en garde. Plus important encore, la taille du tampon n’est pas limitée, ce qui signifie que cela pourrait entraîner des problèmes de mémoire si le tampon devient trop volumineux. Il existe plusieurs approches pour atténuer ce problème, par exemple en implémentant le tampon sous forme de fenêtre coulissante qui ne conserve que les journaux les plus récents ou en limitant la taille totale du tampon.

De plus, les journaux mis en mémoire tampon ne sont vidés que dans des cas contrôlés comme sur logger.error(), mais pas en cas d'erreurs non gérées. Ce comportement pourrait facilement être obtenu si nous rendons le tampon public et utilisons un middleware comme Middy.js. Middy expose un événement onError que nous pourrions utiliser pour vider le tampon.

J'ai écrit à ce sujet plus en détail dans cette demande de commentaires sur le référentiel officiel AWS Powertools for Lambda.

Si vous souhaitez voir cette fonctionnalité devenir une partie de Powertools pour Lambda, veuillez partager vos idées et vos commentaires ici ?

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

source:dev.to
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal