Skip to content

Maintenance: replace EnvironmentVariablesService class with helper functions in Logger #4116

@svozza

Description

@svozza

Summary

In #3945 we added new zero-dependency functional utilities to read and parse environment variables. These new functions supersede the old class based environment service approach. We should should refactor any use of the class based system to the new function based approach.

Why is this needed?

The rationale for the introduction of these utilities as per #3945 is as follows:

[M]ost of the advantage to customers will come in the form of smaller utilities over time, since we'll be able to use these helpers across other Powertools for AWS utilities and replace the existing EnvironmentVariablesService class-based model which is extremely verbose and requires props drilling if you want to access env variables deep into an inheritance stack.

This change will help us to eventually remove the EnvironmentVariablesService entirely from the code base.

Which area does this relate to?

Logger

Solution

The logger currently extends the EnvironmentVariablesService class with logger specific environment variable methods. The main usage of this class is in the Logger.ts file in the setOptions method. This method is called by the constructor on instantiation and ensures that the environment variables are only read once.

import { EnvironmentVariablesService } from '@aws-lambda-powertools/commons';

// ...

public constructor(options: ConstructorOptions = {}) {
    super();
    const { customConfigService, ...rest } = options;
    this.setCustomConfigService(customConfigService);
    this.setOptions(rest);
    // ...
  }

private setOptions(
    options: Omit<ConstructorOptions, 'customConfigService'>
  ): this {
    const {
      logLevel,
      serviceName,
      sampleRateValue,
      logFormatter,
      persistentKeys,
      persistentLogAttributes, // deprecated in favor of persistentKeys
      environment,
      jsonReplacerFn,
      logRecordOrder,
      logBufferOptions,
      correlationIdSearchFn,
    } = options;
    
   // ...

    // configurations that affect Logger behavior
    const AlcLogLevel = this.getEnvVarsService().getAwsLogLevel();
    if (this.isValidLogLevel(AlcLogLevel)) {
      this.#alcLogLevel = AlcLogLevel;
    }
    
    this.setLogEvent();
    this.setInitialLogLevel(logLevel);
    this.setInitialSampleRate(sampleRateValue);

    // configurations that affect how logs are printed
    this.setLogFormatter(logFormatter, logRecordOrder);
    this.setConsole();
    this.setLogIndentation();
    this.#jsonReplacerFn = jsonReplacerFn;
    this.#setLogBuffering(logBufferOptions);
    this.#correlationIdSearchFn = correlationIdSearchFn;

    return this;
  }

Note that the multiple set* methods called in setOptions also read from the environment such as setLogEvent:

private setLogEvent(): void {
    if (this.getEnvVarsService().getLogEvent()) {
      this.logEvent = true;
    }
  }

We could refactor this call to the this.getEnvVarsService() method like so:

import { getBooleanFromEnv } from '@aws-lambda-powertools/commons/utils/env';

private setLogEvent(): void {
    if (getBooleanFromEnv('POWERTOOLS_LOGGER_LOG_EVENT')) {
      this.logEvent = true;
    }
  }

Other calls to this.getEnvVarsService() could be refactored similarly using the new functional utilities.

Acknowledgment

Future readers

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

Metadata

Metadata

Assignees

Labels

completedThis item is complete and has been merged/shippedloggerThis item relates to the Logger Utility

Type

No type

Projects

Status

Shipped

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions