powertools-lambda-typescript icon indicating copy to clipboard operation
powertools-lambda-typescript copied to clipboard

Feature request: Provide ability to refernce and modify Log Level Numerical Thresholds

Open OffensiveBias-08-145 opened this issue 9 months ago • 3 comments

Use case

Currently our logging standard has both the numerical and string representations of the Log Level. The usage of both allow us to have increased efficiency when retrieving or searching logs from storage.

Indexing the numerical value is more efficient that its string counterpart.

{
  level: 'INFO',
  level_index: 12,
}

Currently it is difficult to directly access the prescribed log levels when extending the Logger class or utilizing a custom log format.

Some of the workarounds include:

  • Extending UnformattedAttributes to include the LogLevel Numerical Value (Works but adds another custom interface I then need to manage)
  • Manually mapping LogLevel (str) to its corresponding numerical value (Works but extra code is required)
    • With TS, this also means that we also have to force uppercase matching (Less LOC than a switch) since LogLevel used in UnformattedAttributes allows for upper and lowercase values.'
    • Since one cannot directly access the perscribed LogLevel thresholds, one must copy it manually and later update it should it change.
  class CustomLogFormatter extends LogFormatter {
    private getLogLevelNumberFromName(level: LogLevel): number {
      let found = 0;
      for (const [key, value] of Object.entries({
        DEBUG: 8,
        INFO: 12,
        WARN: 16,
        ERROR: 20,
        CRITICAL: 24,
        SILENT: 28,
      })) {
        if (key.toUpperCase() === level) {
          found = value;
          break;
        }
      }
      return found;
    }

    override formatAttributes(
      attributes: UnformattedAttributes,
      additionalLogAttributes: LogAttributes
    ): LogItem {
      const baseAttributes = {
        timestamp: this.formatTimestamp(new Date()),
        level: attributes.logLevel.toUpperCase(),
        level_index: this.getLogLevelNumberFromName(attributes.logLevel),
  
     //........

If I am missing something evident please let me know. I would be happy to open an PR for this.

Solution/User Experience

Ideal Solutions:

  • logLevelThresholds changed from private to protected OR utilize a "getter"
  • Add an additional property to UnformattedAttributes or PowertoolsLogData that represents the numerical LogLevel.

This way the numerical log level is easily passed to any Custom log Formatter instead of having to map it using LogAttributes or some other workaround.

Adding this in the other libraries would be beneficial as well!

//Open to feedback on the prop name

type PowertoolsLogData = LogAttributes & {
    environment?: Environment;
    serviceName: string;
    sampleRateValue: number;
    lambdaContext?: LambdaFunctionContext;
    xRayTraceId?: string;
    awsRegion: string;
    logLevelIndex?: number; //OPTION #1 
};
type UnformattedAttributes = PowertoolsLogData & {
    error?: Error;
    logLevel: LogLevel;
    logLevelIndex: number; //OPTION #2
    timestamp: Date;
    message: string;
};

Alternative solutions

Creating a helper function in a Custom Log Formatter to map the string LogLevel to its numerical counterpart.


  class CustomLogFormatter extends LogFormatter {
    private getLogLevelNumberFromName(level: LogLevel): number {
      let found;
      for (const [key, value] of Object.entries({
        DEBUG: 8,
        INFO: 12,
        WARN: 16,
        ERROR: 20,
        CRITICAL: 24,
        SILENT: 28,
      })) {
        if (key.toUpperCase() === level) {
          found = value;
          break;
        }
      }
      return found ?? 0;
    }

    override formatAttributes(
      attributes: UnformattedAttributes,
      additionalLogAttributes: LogAttributes
    ): LogItem {
      const baseAttributes = {
        timestamp: this.formatTimestamp(new Date()),
        level: attributes.logLevel.toUpperCase(),
        level_index: this.getLogLevelNumberFromName(attributes.logLevel),
  
     //........

Acknowledgment

Future readers

Please react with 👍 and your use case to help us understand customer demand.

OffensiveBias-08-145 avatar May 14 '24 23:05 OffensiveBias-08-145