diff --git a/packages/metrics/src/Metrics.ts b/packages/metrics/src/Metrics.ts index 7933b4ace5..c5f7dbc6be 100644 --- a/packages/metrics/src/Metrics.ts +++ b/packages/metrics/src/Metrics.ts @@ -25,7 +25,7 @@ class Metrics implements MetricsInterface { private isSingleMetric: boolean = false; private metadata: { [key: string]: string } = {}; private namespace?: string; - private raiseOnEmptyMetrics: boolean = false; + private shouldRaiseOnEmptyMetrics: boolean = false; private storedMetrics: StoredMetrics = {}; public constructor(options: MetricsOptions = {}) { @@ -80,9 +80,19 @@ class Metrics implements MetricsInterface { this.storedMetrics = {}; } + public captureColdStartMetric(): void { + this.captureColdStart(); + } + + public raiseOnEmptyMetrics(): void { + this.shouldRaiseOnEmptyMetrics = true; + } + public logMetrics(options: DecoratorOptions = {}): HandlerMethodDecorator { const { raiseOnEmptyMetrics, defaultDimensions, captureColdStartMetric } = options; - this.raiseOnEmptyMetrics = raiseOnEmptyMetrics || false; + if (raiseOnEmptyMetrics) { + this.raiseOnEmptyMetrics(); + } if (defaultDimensions !== undefined) { this.setDefaultDimensions(defaultDimensions); } @@ -114,7 +124,7 @@ class Metrics implements MetricsInterface { Name: metricDefinition.name, Unit: metricDefinition.unit, })); - if (metricDefinitions.length === 0 && this.raiseOnEmptyMetrics) { + if (metricDefinitions.length === 0 && this.shouldRaiseOnEmptyMetrics) { throw new RangeError('The number of metrics recorded must be higher than zero'); } diff --git a/packages/metrics/tests/unit/Metrics.test.ts b/packages/metrics/tests/unit/Metrics.test.ts index 4192d1be2c..a0ea1cf758 100644 --- a/packages/metrics/tests/unit/Metrics.test.ts +++ b/packages/metrics/tests/unit/Metrics.test.ts @@ -225,6 +225,25 @@ describe('Class: Metrics', () => { }); describe('Feature: Cold Start', () => { + test('Cold start metric should only be written out once and flushed automatically', async () => { + const metrics = new Metrics({ namespace: 'test' }); + + const handler = async (event: any, context: Context) => { + // Should generate only one log + metrics.captureColdStartMetric(); + }; + + await handler(dummyEvent, dummyContext); + await handler(dummyEvent, dummyContext); + const loggedData = [JSON.parse(consoleSpy.mock.calls[0][0])]; + + expect(console.log).toBeCalledTimes(1); + expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics.length).toBe(1); + expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics[0].Name).toBe('ColdStart'); + expect(loggedData[0]._aws.CloudWatchMetrics[0].Metrics[0].Unit).toBe('Count'); + expect(loggedData[0].ColdStart).toBe(1); + }); + test('Cold start metric should only be written out once', async () => { const metrics = new Metrics({ namespace: 'test' }); @@ -338,6 +357,23 @@ describe('Class: Metrics', () => { expect((e).message).toBe('The number of metrics recorded must be higher than zero'); } }); + + test('Error should be thrown on empty metrics when raiseOnEmptyMetrics() is callse', async () => { + expect.assertions(1); + + const metrics = new Metrics({ namespace: 'test' }); + const handler = async (event: any, context: Context) => { + metrics.raiseOnEmptyMetrics(); + // Logic goes here + metrics.purgeStoredMetrics(); + }; + + try { + await handler(dummyEvent, dummyContext); + } catch (e) { + expect((e).message).toBe('The number of metrics recorded must be higher than zero'); + } + }); }); describe('Feature: Auto log at limit', () => {