Skip to content

Commit

Permalink
feat(metrics): log warning on empty metrics (#1397)
Browse files Browse the repository at this point in the history
  • Loading branch information
dreamorosi authored Apr 6, 2023
1 parent 9d53942 commit 31ae936
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 13 deletions.
6 changes: 6 additions & 0 deletions packages/metrics/src/Metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -330,6 +330,12 @@ class Metrics extends Utility implements MetricsInterface {
* ```
*/
public publishStoredMetrics(): void {
if (!this.shouldThrowOnEmptyMetrics && Object.keys(this.storedMetrics).length === 0) {
console.warn(
'No application metrics to publish. The cold-start metric may be published if enabled. ' +
'If application metrics should never be empty, consider using \'throwOnEmptyMetrics\'',
);
}
const target = this.serializeMetrics();
console.log(JSON.stringify(target));
this.clearMetrics();
Expand Down
61 changes: 60 additions & 1 deletion packages/metrics/tests/unit/Metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ describe('Class: Metrics', () => {
const event = dummyEvent.Custom.CustomEvent;

beforeEach(() => {
consoleSpy.mockClear();
jest.clearAllMocks();
});

beforeAll(() => {
Expand Down Expand Up @@ -464,6 +464,65 @@ describe('Class: Metrics', () => {
expect((<Error>e).message).toBe('The number of metrics recorded must be higher than zero');
}
});

test('when decorator is used with throwOnEmptyMetrics set to false, a warning should be logged', async () => {

// Prepare
const metrics = new Metrics({ namespace: 'test' });
class LambdaFunction implements LambdaInterface {
@metrics.logMetrics({ throwOnEmptyMetrics: false })
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
public async handler<TEvent, TResult>(
_event: TEvent,
_context: Context,
): Promise<void | TResult> {
return;
}
}
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();

// Act
await new LambdaFunction().handler(event, context);

// Assess
expect(consoleWarnSpy).toBeCalledTimes(1);
expect(consoleWarnSpy).toBeCalledWith(
'No application metrics to publish. The cold-start metric may be published if enabled. If application metrics should never be empty, consider using \'throwOnEmptyMetrics\'',
);

});

test('when decorator is used with throwOnEmptyMetrics set to false & captureColdStartMetric set to true, a warning should be logged', async () => {

// Prepare
const metrics = new Metrics({ namespace: 'test' });
class LambdaFunction implements LambdaInterface {
@metrics.logMetrics({
throwOnEmptyMetrics: false,
captureColdStartMetric: true
})
// eslint-disable-next-line @typescript-eslint/ban-ts-comment
// @ts-ignore
public async handler<TEvent, TResult>(
_event: TEvent,
_context: Context,
): Promise<void | TResult> {
return;
}
}
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();

// Act
await new LambdaFunction().handler(event, context);

// Assess
expect(consoleWarnSpy).toBeCalledTimes(1);
expect(consoleWarnSpy).toBeCalledWith(
'No application metrics to publish. The cold-start metric may be published if enabled. If application metrics should never be empty, consider using \'throwOnEmptyMetrics\'',
);

});
});

describe('Feature: Auto log at limit', () => {
Expand Down
25 changes: 13 additions & 12 deletions packages/metrics/tests/unit/middleware/middy.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,9 @@ import {
import { ExtraOptions } from '../../../src/types';

const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
const consoleWarnSpy = jest.spyOn(console, 'warn').mockImplementation();
const mockDate = new Date(1466424490000);
const dateSpy = jest.spyOn(global, 'Date').mockImplementation(() => mockDate);
jest.spyOn(global, 'Date').mockImplementation(() => mockDate);

describe('Middy middleware', () => {

Expand All @@ -40,8 +41,7 @@ describe('Middy middleware', () => {

beforeEach(() => {
jest.resetModules();
consoleSpy.mockClear();
dateSpy.mockClear();
jest.clearAllMocks();
});

describe('throwOnEmptyMetrics', () => {
Expand Down Expand Up @@ -80,21 +80,22 @@ describe('Middy middleware', () => {
}
});

test('should not throw on empty metrics if not set', async () => {
test('should not throw on empty metrics if not set, but should log a warning', async () => {

// Prepare
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' });

const lambdaHandler = (): void => {
const lambdaHandler = async (): Promise<void> => {
console.log('do nothing');
};

const handler = middy(lambdaHandler).use(logMetrics(metrics));

try {
await handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
} catch (e) {
fail(`Should not throw but got the following Error: ${e}`);
}
// Act & Assess
await expect(handler(dummyEvent, dummyContext)).resolves.not.toThrowError();
expect(consoleWarnSpy).toBeCalledTimes(1);
expect(consoleWarnSpy).toBeCalledWith(
'No application metrics to publish. The cold-start metric may be published if enabled. If application metrics should never be empty, consider using \'throwOnEmptyMetrics\'',
);

});
});

Expand Down

0 comments on commit 31ae936

Please sign in to comment.