diff --git a/packages/metrics/src/Metrics.ts b/packages/metrics/src/Metrics.ts index 168fa255c3..0a236db877 100644 --- a/packages/metrics/src/Metrics.ts +++ b/packages/metrics/src/Metrics.ts @@ -7,6 +7,7 @@ import { MAX_METRICS_SIZE, DEFAULT_NAMESPACE, COLD_START_METRIC, + MAX_METRIC_VALUES_SIZE, } from './constants'; import { MetricsOptions, @@ -662,7 +663,10 @@ class Metrics extends Utility implements MetricsInterface { } /** - * Stores a metric in the buffer + * Stores a metric in the buffer. + * + * If the buffer is full, or the metric reaches the maximum number of values, + * the buffer is published to stdout. * * @param name The name of the metric to store * @param unit The unit of the metric to store @@ -692,6 +696,9 @@ class Metrics extends Utility implements MetricsInterface { storedMetric.value = [storedMetric.value]; } storedMetric.value.push(value); + if (storedMetric.value.length === MAX_METRIC_VALUES_SIZE) { + this.publishStoredMetrics(); + } } } } diff --git a/packages/metrics/src/constants.ts b/packages/metrics/src/constants.ts index 0dcf9ff255..5cdbf6a955 100644 --- a/packages/metrics/src/constants.ts +++ b/packages/metrics/src/constants.ts @@ -1,4 +1,13 @@ -export const COLD_START_METRIC = 'ColdStart'; -export const DEFAULT_NAMESPACE = 'default_namespace'; -export const MAX_METRICS_SIZE = 100; -export const MAX_DIMENSION_COUNT = 29; +const COLD_START_METRIC = 'ColdStart'; +const DEFAULT_NAMESPACE = 'default_namespace'; +const MAX_METRICS_SIZE = 100; +const MAX_METRIC_VALUES_SIZE = 100; +const MAX_DIMENSION_COUNT = 29; + +export { + COLD_START_METRIC, + DEFAULT_NAMESPACE, + MAX_METRICS_SIZE, + MAX_METRIC_VALUES_SIZE, + MAX_DIMENSION_COUNT, +}; diff --git a/packages/metrics/tests/unit/Metrics.test.ts b/packages/metrics/tests/unit/Metrics.test.ts index b0f41073bf..42c5f2ded8 100644 --- a/packages/metrics/tests/unit/Metrics.test.ts +++ b/packages/metrics/tests/unit/Metrics.test.ts @@ -16,6 +16,7 @@ import { DEFAULT_NAMESPACE, MAX_DIMENSION_COUNT, MAX_METRICS_SIZE, + MAX_METRIC_VALUES_SIZE, } from '../../src/constants'; import { setupDecoratorLambdaHandler } from '../helpers/metricsUtils'; import { @@ -701,6 +702,34 @@ describe('Class: Metrics', () => { ); }); + test('it should publish metrics when the array of values reaches the maximum size', () => { + // Prepare + const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE }); + const consoleSpy = jest.spyOn(console, 'log'); + const metricName = 'test-metric'; + + // Act + for (let i = 0; i <= MAX_METRIC_VALUES_SIZE; i++) { + metrics.addMetric(`${metricName}`, MetricUnits.Count, i); + } + metrics.publishStoredMetrics(); + + // Assess + // 2 calls to console.log: 1 for the first batch of metrics, 1 for the second batch (explicit call) + expect(consoleSpy).toHaveBeenCalledTimes(2); + const firstMetricsJson = JSON.parse( + consoleSpy.mock.calls[0][0] + ) as EmfOutput; + const secondMetricsJson = JSON.parse( + consoleSpy.mock.calls[1][0] + ) as EmfOutput; + + // The first batch of values should be an array of size MAX_METRIC_VALUES_SIZE + expect(firstMetricsJson[metricName]).toHaveLength(MAX_METRIC_VALUES_SIZE); + // The second should be a single value (the last value added, which is 100 given we start from 0) + expect(secondMetricsJson[metricName]).toEqual(100); + }); + test('it should not publish metrics if stored metrics count has not reached max metric size threshold', () => { // Prepare const metrics: Metrics = new Metrics({ namespace: TEST_NAMESPACE });