> 웹 프론트엔드 > JS 튜토리얼 > Powertools for Lambda를 사용하여 오류 발생 시 자동으로 로그 버퍼링 및 플러시

Powertools for Lambda를 사용하여 오류 발생 시 자동으로 로그 버퍼링 및 플러시

Susan Sarandon
풀어 주다: 2024-12-19 20:23:15
원래의
262명이 탐색했습니다.

Buffer Logs and Flush Automatically on Error with Powertools for Lambda

AWS Powertools for Lambda의 최신 릴리스를 사용하면 사용자 지정 기능으로 Logger를 더 쉽게 확장할 수 있습니다.

Logger 클래스의 확장성이 더욱 향상되었습니다
이제 이전에 비공개였던 Logger 메서드 createAndPopulateLogItem, printLog 및 processLogItem을 덮어쓸 수 있습니다. 이를 통해 Logger를 확장하고 새로운 기능을 추가할 수 있습니다(예: 자체 메시지 버퍼 구현).
v2.12.0 출시

저는 이 새로운 확장성을 사용하여 로그 버퍼링 및 플러시라는 유용한 기능을 구현하고 있습니다. 아이디어는 간단합니다. 프로덕션 환경에서는 일반적으로 경고 및 오류와 같은 중요한 정보만 기록합니다. 로그 공간은 비용이 많이 들고 소음이 발생할 수 있기 때문입니다. 그러나 오류가 발생하면 가능한 모든 정보가 필요합니다. 즉, 함수 전체에 흩어져 있는 모든 디버그 및 정보 로그를 사용할 수 있어야 합니다. 하지만 로그 수준을 너무 낮게 설정해서 그런 것은 아닙니다.

버퍼 및 플러시

이러한 디버그 및 정보 로그를 모두 내부적으로 수집하고, 오류와 같은 중요한 이벤트가 발생하면 콘솔에 인쇄하면 어떻게 될까요? 저는 로그를 하위 로그와 상위 로그라는 두 가지 범주로 분류합니다. 구성된 로그 수준이 WARN인 경우 DEBUG 또는 INFO 로그는 낮은 수준이고 ERROR는 높은 수준 로그입니다.

이제 낮은 수준의 로그를 인쇄할 때 지금처럼 버리는 대신 내부 목록에 로그를 버퍼링합니다. 높은 수준의 로그가 있으면 즉시 버퍼링된 모든 로그를 콘솔로 플러시합니다.

구현

이 기능을 추가하기 위해 Powertools에서 Logger 클래스를 확장하고 processLogItem()을 재정의하는 새 클래스를 생성합니다. 이는 logger.debug()와 같은 다양한 로그 메소드에 의해 호출되는 중심 메소드입니다. 원래 구현에서는 로그 항목이 올바른 수준에 있는 경우 콘솔에 인쇄합니다. 이 방법을 재정의하면 로그 수준에 따라 로그를 버퍼링하고 플러시하는 특수 논리를 추가할 수 있습니다.

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);
  }
}
로그인 후 복사
로그인 후 복사

여기서 X-Ray Trace ID를 사용하는 이유가 궁금하실 수도 있습니다. 핸들러 함수 외부에서 Logger를 인스턴스화하는 것이 일반적입니다. 그러나 Lambda 실행 환경은 잠재적으로 여러 호출에 재사용되므로 버퍼에는 이전 호출의 로그 항목이 포함될 수 있습니다. 이것이 바로 버퍼가 단순한 배열이 아닌 객체로 구현되는 이유입니다. X-Ray 추적 ID를 식별자로 사용하여 동일한 호출의 로그 항목만 버퍼링합니다.
버퍼는 단순한 배열이 아닌 객체로 구현됩니다. 버퍼가 플러시되면 간단히 객체를 재설정하여 다른 호출에서 항목을 제거할 수 있습니다.

로컬에서 테스트

로컬에서 구현을 빠르게 검증해 보겠습니다.

// 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
로그인 후 복사

우리가 얻은 결과는 다음과 같습니다.

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);
  }
}
로그인 후 복사
로그인 후 복사

디버그 및 정보 로그가 버퍼링되었기 때문에 경고가 첫 번째 메시지입니다. 오류가 기록되면 오류가 실제로 인쇄되기 전에 버퍼링된 로그를 플러시하고 정보를 인쇄했습니다.

의견 요청

저의 단순한 구현에는 몇 가지 주의 사항이 있습니다. 가장 중요한 것은 버퍼 크기가 제한되지 않는다는 것입니다. 즉, 버퍼가 너무 커지면 메모리 문제가 발생할 수 있습니다. 예를 들어 가장 최근 로그만 유지하는 슬라이딩 창으로 버퍼를 구현하거나 총 버퍼 크기를 제한하는 등의 방법으로 이 문제를 완화할 수 있는 몇 가지 접근 방식이 있습니다.

또한 버퍼링된 로그는 logger.error()와 같이 제어된 경우에만 플러시되고 처리되지 않은 오류에서는 플러시되지 않습니다. 이 동작은 버퍼를 공개하고 Middy.js와 같은 미들웨어를 사용하면 쉽게 달성할 수 있습니다. Middy는 버퍼를 플러시하는 데 활용할 수 있는 onError 이벤트를 노출합니다.

공식 AWS Powertools for Lambda 리포지토리에 대한 이 의견 요청에서 이에 대해 더 광범위하게 작성했습니다.

이 기능이 Powertools for Lambda의 일부가 되는 것을 보고 싶으시면 거기에 아이디어와 피드백을 공유해 주세요.

위 내용은 Powertools for Lambda를 사용하여 오류 발생 시 자동으로 로그 버퍼링 및 플러시의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

원천:dev.to
본 웹사이트의 성명
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.
저자별 최신 기사
인기 튜토리얼
더>
최신 다운로드
더>
웹 효과
웹사이트 소스 코드
웹사이트 자료
프론트엔드 템플릿