From bdc225a61f82987e1b1cdf3bc44250422feaf095 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 9 Jun 2024 17:26:52 +0600 Subject: [PATCH 01/17] feat: format timestamp with timezone offset If there is a timezone set, format the current timestamp with timezone offset --- packages/logger/src/formatter/LogFormatter.ts | 60 ++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index f3192ea43c..c38a869541 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -80,7 +80,10 @@ abstract class LogFormatter implements LogFormatterInterface { * @returns {string} */ public formatTimestamp(now: Date): string { - return now.toISOString(); + const timezone = this.envVarsService?.getTimezone() || process.env.TZ; + if (!timezone || timezone === 'UTC') return now.toISOString(); + + return this.#generateISOTimestampWithOffset(now, timezone); } /** @@ -108,6 +111,61 @@ abstract class LogFormatter implements LogFormatterInterface { return ''; } + + /** + * Generates a new Intl.DateTimeFormat object configured with the specified time zone + * and formatting options. The time is displayed in 24-hour format (hour12: false). + * + * @param {string} timeZone - the IANA time zone identifier (e.g., "Asia/Dhaka"). + */ + #getDateFormatter = (timeZone: string): Intl.DateTimeFormat => { + const twoDigitFormatOption = '2-digit'; + + return new Intl.DateTimeFormat('en', { + year: 'numeric', + month: twoDigitFormatOption, + day: twoDigitFormatOption, + hour: twoDigitFormatOption, + minute: twoDigitFormatOption, + second: twoDigitFormatOption, + hour12: false, + timeZone, + }); + }; + + /** + * Generates an ISO 8601 timestamp string with the specified time zone and the local time zone offset. + * + * @param {Date} date - the date to format + * @param {string} timeZone - the IANA time zone identifier (e.g., "Asia/Dhaka"). + */ + #generateISOTimestampWithOffset(date: Date, timeZone: string): string { + const { year, month, day, hour, minute, second } = this.#getDateFormatter( + timeZone + ) + .formatToParts(date) + .reduce( + (acc, item) => { + acc[item.type] = item.value; + + return acc; + }, + {} as Record + ); + const datePart = `${year}-${month}-${day}T${hour}:${minute}:${second}`; + const offset = -date.getTimezoneOffset(); + const offsetSign = offset >= 0 ? '+' : '-'; + const offsetHours = Math.abs(Math.floor(offset / 60)) + .toString() + .padStart(2, '0'); + const offsetMinutes = Math.abs(offset % 60) + .toString() + .padStart(2, '0'); + const millisecondPart = date.getMilliseconds().toString().padStart(3, '0'); + const offsetPart = `${offsetSign}${offsetHours}:${offsetMinutes}`; + + return `${datePart}.${millisecondPart}${offsetPart}`; + } } export { LogFormatter }; From d6f6a2824db05a7bef763600b0c3c177e8b93137 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Thu, 20 Jun 2024 20:08:36 +0600 Subject: [PATCH 02/17] test: formatTimestamp with different timezone --- .../formatter/PowertoolsLogFormatter.test.ts | 121 +++++++++++++++++- 1 file changed, 118 insertions(+), 3 deletions(-) diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index b4e8753cb7..193ec77acb 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -10,11 +10,17 @@ import type { UnformattedAttributes } from '../../../src/types/Logger.js'; import type { LogAttributes } from '../../../src/types/Log.js'; describe('Class: PowertoolsLogFormatter', () => { - const mockDate = new Date(1466424490000); - const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate); + const ENVIRONMENT_VARIABLES = process.env; beforeEach(() => { - dateSpy.mockClear(); + const mockDate = new Date(1466424490000); + jest.useFakeTimers().setSystemTime(mockDate); + process.env = { ...ENVIRONMENT_VARIABLES }; + }); + + afterAll(() => { + process.env = ENVIRONMENT_VARIABLES; + jest.useRealTimers(); }); describe('Method: formatAttributes', () => { @@ -309,6 +315,115 @@ describe('Class: PowertoolsLogFormatter', () => { // Assess expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); }); + + test('it formats the timestamp to ISO 8601, accounting for the `America/New_York` timezone offset', () => { + // Prepare + process.env.TZ = 'America/New_York'; + /* + Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. + The positive value indicates that `America/New_York` is behind UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T08:08:10.000-04:00'); + }); + + test('it formats the timestamp to ISO 8601 with correct milliseconds for `America/New_York` timezone', () => { + // Prepare + process.env.TZ = 'America/New_York'; + const mockDate = new Date('2016-06-20T12:08:10.910Z'); + jest.useFakeTimers().setSystemTime(mockDate); + /* + Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. + The positive value indicates that `America/New_York` is behind UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T08:08:10.910-04:00'); + }); + + test('it correctly formats the timestamp to ISO 8601, adjusting for `America/New_York` timezone, preserving milliseconds and accounting for date change', () => { + // Prepare + process.env.TZ = 'America/New_York'; + const mockDate = new Date('2016-06-20T00:08:10.910Z'); + jest.useFakeTimers().setSystemTime(mockDate); + /* + Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. + The positive value indicates that `America/New_York` is behind UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-19T20:08:10.910-04:00'); + }); + + test('it formats the timestamp to ISO 8601, accounting for the `Asia/Dhaka` timezone offset', () => { + // Prepare + process.env.TZ = 'Asia/Dhaka'; + /* + Difference between UTC and `Asia/Dhaka`(GMT +06.00) is 360 minutes. + The negative value indicates that `Asia/Dhaka` is ahead of UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T18:08:10.000+06:00'); + }); + + test('it formats the timestamp to ISO 8601 with correct milliseconds for `Asia/Dhaka` timezone', () => { + // Prepare + process.env.TZ = 'Asia/Dhaka'; + jest.useFakeTimers().setSystemTime(new Date('2016-06-20T12:08:10.910Z')); + /* + Difference between UTC and `Asia/Dhaka`(GMT +06.00) is 360 minutes. + The negative value indicates that `Asia/Dhaka` is ahead of UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T18:08:10.910+06:00'); + }); + + test('it correctly formats the timestamp to ISO 8601, adjusting for `Asia/Dhaka` timezone, preserving milliseconds and accounting for date change', () => { + // Prepare + process.env.TZ = 'Asia/Dhaka'; + const mockDate = new Date('2016-06-20T20:08:10.910Z'); + jest.useFakeTimers().setSystemTime(mockDate); + /* + Difference between UTC and `Asia/Dhaka`(GMT +06.00) is 360 minutes. + The negative value indicates that `Asia/Dhaka` is ahead of UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-21T02:08:10.910+06:00'); + }); }); describe('Method: getCodeLocation', () => { From 223837030b42874463293aba214242b2e7c99cb6 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 23 Jun 2024 11:58:31 +0600 Subject: [PATCH 03/17] feat: get timezone from `envVarsService` during formatting --- packages/logger/src/formatter/LogFormatter.ts | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index c38a869541..799ea3addf 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -74,16 +74,25 @@ abstract class LogFormatter implements LogFormatterInterface { } /** - * It formats a date into a string in simplified extended ISO format (ISO 8601). + * Formats a given date into an ISO 8601 string, considering the configured timezone. + * If `envVarsService` is set and the configured timezone differs from 'UTC', + * the date is formatted to that timezone. Otherwise, it defaults to 'UTC'. * * @param {Date} now * @returns {string} */ public formatTimestamp(now: Date): string { - const timezone = this.envVarsService?.getTimezone() || process.env.TZ; - if (!timezone || timezone === 'UTC') return now.toISOString(); + const defaultTimezone = 'UTC'; - return this.#generateISOTimestampWithOffset(now, timezone); + /** + * If a specific timezone is configured and it's not the default `UTC`, + * format the timestamp with the appropriate timezone offset. + **/ + const configuredTimezone = this.envVarsService?.getTimezone(); + if (configuredTimezone && configuredTimezone !== defaultTimezone) + return this.#generateISOTimestampWithOffset(now, configuredTimezone); + + return now.toISOString(); } /** From ae7464356d5589e02863fbdeafe84ec36bdafcf9 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 23 Jun 2024 12:30:06 +0600 Subject: [PATCH 04/17] fix: formatTimestamp tests when `envVarsService` is present --- .../formatter/PowertoolsLogFormatter.test.ts | 29 ++++++++++++++----- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index 193ec77acb..4d2c174875 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -8,6 +8,7 @@ import { PowertoolsLogFormatter } from '../../../src/formatter/PowertoolsLogForm import { LogItem } from '../../../src/index.js'; import type { UnformattedAttributes } from '../../../src/types/Logger.js'; import type { LogAttributes } from '../../../src/types/Log.js'; +import { EnvironmentVariablesService } from '../../../src/config/EnvironmentVariablesService.js'; describe('Class: PowertoolsLogFormatter', () => { const ENVIRONMENT_VARIABLES = process.env; @@ -324,7 +325,9 @@ describe('Class: PowertoolsLogFormatter', () => { The positive value indicates that `America/New_York` is behind UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); @@ -343,7 +346,9 @@ describe('Class: PowertoolsLogFormatter', () => { The positive value indicates that `America/New_York` is behind UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); @@ -352,7 +357,7 @@ describe('Class: PowertoolsLogFormatter', () => { expect(timestamp).toEqual('2016-06-20T08:08:10.910-04:00'); }); - test('it correctly formats the timestamp to ISO 8601, adjusting for `America/New_York` timezone, preserving milliseconds and accounting for date change', () => { + test('it formats the timestamp to ISO 8601, adjusting for `America/New_York` timezone, preserving milliseconds and accounting for date change', () => { // Prepare process.env.TZ = 'America/New_York'; const mockDate = new Date('2016-06-20T00:08:10.910Z'); @@ -362,7 +367,9 @@ describe('Class: PowertoolsLogFormatter', () => { The positive value indicates that `America/New_York` is behind UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); @@ -379,7 +386,9 @@ describe('Class: PowertoolsLogFormatter', () => { The negative value indicates that `Asia/Dhaka` is ahead of UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); @@ -397,7 +406,9 @@ describe('Class: PowertoolsLogFormatter', () => { The negative value indicates that `Asia/Dhaka` is ahead of UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); @@ -406,7 +417,7 @@ describe('Class: PowertoolsLogFormatter', () => { expect(timestamp).toEqual('2016-06-20T18:08:10.910+06:00'); }); - test('it correctly formats the timestamp to ISO 8601, adjusting for `Asia/Dhaka` timezone, preserving milliseconds and accounting for date change', () => { + test('it formats the timestamp to ISO 8601, adjusting for `Asia/Dhaka` timezone, preserving milliseconds and accounting for date change', () => { // Prepare process.env.TZ = 'Asia/Dhaka'; const mockDate = new Date('2016-06-20T20:08:10.910Z'); @@ -416,7 +427,9 @@ describe('Class: PowertoolsLogFormatter', () => { The negative value indicates that `Asia/Dhaka` is ahead of UTC. */ jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); - const formatter = new PowertoolsLogFormatter(); + const formatter = new PowertoolsLogFormatter({ + envVarsService: new EnvironmentVariablesService(), + }); // Act const timestamp = formatter.formatTimestamp(new Date()); From 35da8d5127a58502dddf4f661c540dec262f5915 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 23 Jun 2024 12:30:45 +0600 Subject: [PATCH 05/17] feat: formatTimestamp tests when `envVarsService` is not present --- .../formatter/PowertoolsLogFormatter.test.ts | 34 +++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index 4d2c174875..7b017fa8b5 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -437,6 +437,40 @@ describe('Class: PowertoolsLogFormatter', () => { // Assess expect(timestamp).toEqual('2016-06-21T02:08:10.910+06:00'); }); + + test('if `envVarsService` is not set, ensures timestamp is formatted to `UTC` even with `Asia/Dhaka` timezone', () => { + // Prepare + process.env.TZ = 'Asia/Dhaka'; + /* + Difference between UTC and `Asia/Dhaka`(GMT +06.00) is 360 minutes. + The negative value indicates that `Asia/Dhaka` is ahead of UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(-360); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); + }); + + test('if `envVarsService` is not set, ensures timestamp is formatted to `UTC` even with `America/New_York` timezone', () => { + // Prepare + process.env.TZ = 'America/New_York'; + /* + Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. + The positive value indicates that `America/New_York` is behind UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); + }); }); describe('Method: getCodeLocation', () => { From c1d0c61bd9bc3b7953a4df28e216a9e0c18048e4 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 23 Jun 2024 18:27:17 +0600 Subject: [PATCH 06/17] fix: update comparison as default `TZ` value is `:UTC` --- packages/logger/src/formatter/LogFormatter.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/logger/src/formatter/LogFormatter.ts b/packages/logger/src/formatter/LogFormatter.ts index 799ea3addf..3ba9ca88cd 100644 --- a/packages/logger/src/formatter/LogFormatter.ts +++ b/packages/logger/src/formatter/LogFormatter.ts @@ -89,7 +89,7 @@ abstract class LogFormatter implements LogFormatterInterface { * format the timestamp with the appropriate timezone offset. **/ const configuredTimezone = this.envVarsService?.getTimezone(); - if (configuredTimezone && configuredTimezone !== defaultTimezone) + if (configuredTimezone && !configuredTimezone.includes(defaultTimezone)) return this.#generateISOTimestampWithOffset(now, configuredTimezone); return now.toISOString(); From fc0cb73b1df64b9190e80c5f88d62e89cc08c6d9 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sun, 23 Jun 2024 19:11:59 +0600 Subject: [PATCH 07/17] docs: custom timezone section with examples --- docs/core/logger.md | 22 +++++++++++++++++++ examples/snippets/logger/customTimezone.ts | 11 ++++++++++ .../snippets/logger/customTimezoneOutput.json | 18 +++++++++++++++ 3 files changed, 51 insertions(+) create mode 100644 examples/snippets/logger/customTimezone.ts create mode 100644 examples/snippets/logger/customTimezoneOutput.json diff --git a/docs/core/logger.md b/docs/core/logger.md index c9b95b8b25..aa8425a45e 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -469,6 +469,28 @@ We prioritise log level settings in this order: In the event you have set a log level in Powertools to a level that is lower than the ACL setting, we will output a warning log message informing you that your messages will be discarded by Lambda. +### Setting timestamp to custom Timezone + +By default, this Logger and the standard logging library emit records with the default AWS Lambda timestamp in **UTC**. + + +If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an AWS Lambda environment variable or directly within your Lambda function settings. [Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. + + +=== "customTimezone.ts" + + ```typescript hl_lines="7" + --8<-- "examples/snippets/logger/customTimezone.ts" + ``` + + 1. You don't need to set the TZ variable again when configuring it as an environment variable in AWS Lambda. + +=== "customTimezoneOutput.json" + + ```json hl_lines="7 15" + --8<-- "examples/snippets/logger/customTimezoneOutput.json" + ``` + ### Using multiple Logger instances across your code The `createChild` method allows you to create a child instance of the Logger, which inherits all of the attributes from its parent. You have the option to override any of the settings and attributes from the parent logger, including [its settings](#utility-settings), any [persistent attributes](#appending-persistent-additional-log-keys-and-values), and [the log formatter](#custom-log-formatter-bring-your-own-formatter). diff --git a/examples/snippets/logger/customTimezone.ts b/examples/snippets/logger/customTimezone.ts new file mode 100644 index 0000000000..63a1320ae9 --- /dev/null +++ b/examples/snippets/logger/customTimezone.ts @@ -0,0 +1,11 @@ +import { Logger } from '@aws-lambda-powertools/logger'; + +export const handler = async (_event, _context): Promise => { + const loggerInUTC = new Logger({ serviceName: 'payment' }); + loggerInUTC.info('Logging with default AWS Lambda timezone: UTC time'); + + process.env.TZ = 'US/Eastern'; // (1) + + const logger = new Logger({ serviceName: 'order' }); + logger.info('Logging with US Eastern timezone'); +}; diff --git a/examples/snippets/logger/customTimezoneOutput.json b/examples/snippets/logger/customTimezoneOutput.json new file mode 100644 index 0000000000..c26cba49f9 --- /dev/null +++ b/examples/snippets/logger/customTimezoneOutput.json @@ -0,0 +1,18 @@ +[ + { + "level": "INFO", + "message": "Logging with default AWS Lambda timezone: UTC time", + "sampling_rate": 0, + "service": "payment", + "timestamp": "2024-06-23T12:29:34.721Z", + "xray_trace_id": "1-6678152e-4f2ffb716d51f4112ec21b1d" + }, + { + "level": "INFO", + "message": "Logging with US Eastern timezone", + "sampling_rate": 0, + "service": "order", + "timestamp": "2024-06-23T08:29:34.814-04:00", + "xray_trace_id": "1-6678152e-4f2ffb716d51f4112ec21b1d" + } +] From 0903e5a1635e39dd1a205a61a9f6eca37eb68482 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sat, 29 Jun 2024 17:39:08 +0600 Subject: [PATCH 08/17] doc: fix the special note --- examples/snippets/logger/customTimezone.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/snippets/logger/customTimezone.ts b/examples/snippets/logger/customTimezone.ts index 63a1320ae9..3fb56a0ed0 100644 --- a/examples/snippets/logger/customTimezone.ts +++ b/examples/snippets/logger/customTimezone.ts @@ -4,7 +4,7 @@ export const handler = async (_event, _context): Promise => { const loggerInUTC = new Logger({ serviceName: 'payment' }); loggerInUTC.info('Logging with default AWS Lambda timezone: UTC time'); - process.env.TZ = 'US/Eastern'; // (1) + process.env.TZ = 'US/Eastern'; // (1)! const logger = new Logger({ serviceName: 'order' }); logger.info('Logging with US Eastern timezone'); From 020e5d857ba3841bbf9132a202499aec70e0c3c1 Mon Sep 17 00:00:00 2001 From: arnabrahman Date: Sat, 29 Jun 2024 17:52:51 +0600 Subject: [PATCH 09/17] test: group the test cases close the each other --- .../formatter/PowertoolsLogFormatter.test.ts | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts index 7b017fa8b5..aa33c7368e 100644 --- a/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts +++ b/packages/logger/tests/unit/formatter/PowertoolsLogFormatter.test.ts @@ -378,6 +378,23 @@ describe('Class: PowertoolsLogFormatter', () => { expect(timestamp).toEqual('2016-06-19T20:08:10.910-04:00'); }); + test('if `envVarsService` is not set, ensures timestamp is formatted to `UTC` even with `America/New_York` timezone', () => { + // Prepare + process.env.TZ = 'America/New_York'; + /* + Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. + The positive value indicates that `America/New_York` is behind UTC. + */ + jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); + const formatter = new PowertoolsLogFormatter(); + + // Act + const timestamp = formatter.formatTimestamp(new Date()); + + // Assess + expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); + }); + test('it formats the timestamp to ISO 8601, accounting for the `Asia/Dhaka` timezone offset', () => { // Prepare process.env.TZ = 'Asia/Dhaka'; @@ -454,23 +471,6 @@ describe('Class: PowertoolsLogFormatter', () => { // Assess expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); }); - - test('if `envVarsService` is not set, ensures timestamp is formatted to `UTC` even with `America/New_York` timezone', () => { - // Prepare - process.env.TZ = 'America/New_York'; - /* - Difference between UTC and `America/New_York`(GMT -04.00) is 240 minutes. - The positive value indicates that `America/New_York` is behind UTC. - */ - jest.spyOn(Date.prototype, 'getTimezoneOffset').mockReturnValue(240); - const formatter = new PowertoolsLogFormatter(); - - // Act - const timestamp = formatter.formatTimestamp(new Date()); - - // Assess - expect(timestamp).toEqual('2016-06-20T12:08:10.000Z'); - }); }); describe('Method: getCodeLocation', () => { From 8d03e871aaaabf5ff57acf4ab3ce83aceb081482 Mon Sep 17 00:00:00 2001 From: Andrea Amorosi Date: Mon, 1 Jul 2024 13:19:06 +0200 Subject: [PATCH 10/17] Update docs/core/logger.md --- docs/core/logger.md | 2 -- 1 file changed, 2 deletions(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index d2b9508b59..86004f0897 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -532,8 +532,6 @@ If you prefer to log in a specific timezone, you can configure it by setting the ```typescript hl_lines="7" --8<-- "examples/snippets/logger/customTimezone.ts" ``` - - 1. You don't need to set the TZ variable again when configuring it as an environment variable in AWS Lambda. === "customTimezoneOutput.json" From 8b29c00e44e3bd04df4b717760dfcf7b3abb9c43 Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:31:45 +0600 Subject: [PATCH 11/17] Update docs/core/logger.md Co-authored-by: Andrea Amorosi --- docs/core/logger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 86004f0897..ebf53fd3a7 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -521,7 +521,7 @@ In the event you have set a log level in Powertools to a level that is lower tha ### Setting timestamp to custom Timezone -By default, this Logger and the standard logging library emit records with the default AWS Lambda timestamp in **UTC**. +By default, Logger emits records with the default Lambda timestamp in **UTC**, i.e. `2016-06-20T12:08:10.000Z` If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an AWS Lambda environment variable or directly within your Lambda function settings. [Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. From b92db994a8ae651cecbfe07204a8fab405b4c9bd Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:32:05 +0600 Subject: [PATCH 12/17] Update docs/core/logger.md Co-authored-by: Andrea Amorosi --- docs/core/logger.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index ebf53fd3a7..4d1ba1214e 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -524,7 +524,9 @@ In the event you have set a log level in Powertools to a level that is lower tha By default, Logger emits records with the default Lambda timestamp in **UTC**, i.e. `2016-06-20T12:08:10.000Z` -If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an AWS Lambda environment variable or directly within your Lambda function settings. [Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. +If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an environment variable or directly within your Lambda function settings. + +[Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. === "customTimezone.ts" From b58d58c6b2e93540161b398fc28b6bb573e431a4 Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:32:15 +0600 Subject: [PATCH 13/17] Update docs/core/logger.md Co-authored-by: Andrea Amorosi --- docs/core/logger.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 4d1ba1214e..0f7761d8c5 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -527,7 +527,6 @@ By default, Logger emits records with the default Lambda timestamp in **UTC**, i If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an environment variable or directly within your Lambda function settings. [Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. - === "customTimezone.ts" From 51bf3d77af2fca1e2615e927511ecfdb327eaf0f Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:32:23 +0600 Subject: [PATCH 14/17] Update docs/core/logger.md Co-authored-by: Andrea Amorosi --- docs/core/logger.md | 1 - 1 file changed, 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 0f7761d8c5..376804ba10 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -523,7 +523,6 @@ In the event you have set a log level in Powertools to a level that is lower tha By default, Logger emits records with the default Lambda timestamp in **UTC**, i.e. `2016-06-20T12:08:10.000Z` - If you prefer to log in a specific timezone, you can configure it by setting the `TZ` environment variable. You can do this either as an environment variable or directly within your Lambda function settings. [Click here](https://docs.aws.amazon.com/lambda/latest/dg/configuration-envvars.html#configuration-envvars-runtime){target="_blank"} for a comprehensive list of available Lambda environment variables. From 4e633acecff323126519e90c808745cfb653b8a7 Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:32:57 +0600 Subject: [PATCH 15/17] Update examples/snippets/logger/customTimezone.ts Co-authored-by: Andrea Amorosi --- examples/snippets/logger/customTimezone.ts | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/examples/snippets/logger/customTimezone.ts b/examples/snippets/logger/customTimezone.ts index 3fb56a0ed0..fb0cf20fbd 100644 --- a/examples/snippets/logger/customTimezone.ts +++ b/examples/snippets/logger/customTimezone.ts @@ -1,11 +1,13 @@ import { Logger } from '@aws-lambda-powertools/logger'; -export const handler = async (_event, _context): Promise => { - const loggerInUTC = new Logger({ serviceName: 'payment' }); - loggerInUTC.info('Logging with default AWS Lambda timezone: UTC time'); +const logger = new Logger({ serviceName: 'serverlessAirline' }); - process.env.TZ = 'US/Eastern'; // (1)! +export const handler = async (): Promise => { + logger.info('Hello, World!'); - const logger = new Logger({ serviceName: 'order' }); - logger.info('Logging with US Eastern timezone'); + process.env.TZ = 'Europe/Rome'; + + const childLogger = logger.createChild(); + + childLogger.info('Ciao, Mondo!'); }; From ed60848c8dac78a03bc0067ce49ad08c970a5bea Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:33:06 +0600 Subject: [PATCH 16/17] Update examples/snippets/logger/customTimezoneOutput.json Co-authored-by: Andrea Amorosi --- .../snippets/logger/customTimezoneOutput.json | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/examples/snippets/logger/customTimezoneOutput.json b/examples/snippets/logger/customTimezoneOutput.json index c26cba49f9..c8cf7f074f 100644 --- a/examples/snippets/logger/customTimezoneOutput.json +++ b/examples/snippets/logger/customTimezoneOutput.json @@ -1,18 +1,18 @@ [ { "level": "INFO", - "message": "Logging with default AWS Lambda timezone: UTC time", + "message": "Hello, World!", "sampling_rate": 0, - "service": "payment", - "timestamp": "2024-06-23T12:29:34.721Z", - "xray_trace_id": "1-6678152e-4f2ffb716d51f4112ec21b1d" + "service": "serverlessAirline", + "timestamp": "2024-07-01T11:00:37.886Z", + "xray_trace_id": "1-66828c55-2bb635c65eb609c820ebe7bc" }, { "level": "INFO", - "message": "Logging with US Eastern timezone", + "message": "Ciao, Mondo!", "sampling_rate": 0, - "service": "order", - "timestamp": "2024-06-23T08:29:34.814-04:00", - "xray_trace_id": "1-6678152e-4f2ffb716d51f4112ec21b1d" + "service": "serverlessAirline", + "timestamp": "2024-07-01T13:00:37.934+02:00", + "xray_trace_id": "1-66828c55-2bb635c65eb609c820ebe7bc" } ] From 1fb398e9d009175eb5c1c4d36b8ad2aca3a81d88 Mon Sep 17 00:00:00 2001 From: Asifur Rahman Arnab Date: Tue, 2 Jul 2024 19:33:46 +0600 Subject: [PATCH 17/17] Update docs/core/logger.md Co-authored-by: Andrea Amorosi --- docs/core/logger.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/core/logger.md b/docs/core/logger.md index 376804ba10..dae36c9a37 100644 --- a/docs/core/logger.md +++ b/docs/core/logger.md @@ -529,7 +529,7 @@ If you prefer to log in a specific timezone, you can configure it by setting the === "customTimezone.ts" - ```typescript hl_lines="7" + ```typescript hl_lines="8" --8<-- "examples/snippets/logger/customTimezone.ts" ```