Skip to content

feat(metric): bring feature parity between decorator and utility function #291

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Dec 13, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 13 additions & 3 deletions packages/metrics/src/Metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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 = {}) {
Expand Down Expand Up @@ -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);
}
Expand Down Expand Up @@ -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');
}

Expand Down
36 changes: 36 additions & 0 deletions packages/metrics/tests/unit/Metrics.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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' });

Expand Down Expand Up @@ -338,6 +357,23 @@ describe('Class: Metrics', () => {
expect((<Error>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((<Error>e).message).toBe('The number of metrics recorded must be higher than zero');
}
});
});

describe('Feature: Auto log at limit', () => {
Expand Down