Skip to content

Commit dad0f20

Browse files
committed
feat(metrics): use case Storage Resolution key when not set (#1277)
1 parent a345831 commit dad0f20

File tree

4 files changed

+92
-28
lines changed

4 files changed

+92
-28
lines changed

packages/metrics/src/Metrics.ts

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import {
1717
const MAX_METRICS_SIZE = 100;
1818
const MAX_DIMENSION_COUNT = 29;
1919
const DEFAULT_NAMESPACE = 'default_namespace';
20-
const DEFAULT_METRIC_RESOLUTION = MetricResolution.Standard;
2120

2221
/**
2322
* ## Intro
@@ -170,9 +169,10 @@ class Metrics extends Utility implements MetricsInterface {
170169
* @param name
171170
* @param unit
172171
* @param value
172+
* @param resolution
173173
*/
174174

175-
public addMetric(name: string, unit: MetricUnit, value: number, resolution: MetricResolution = DEFAULT_METRIC_RESOLUTION): void {
175+
public addMetric(name: string, unit: MetricUnit, value: number, resolution?: MetricResolution): void {
176176
this.storeMetric(name, unit, value, resolution);
177177
if (this.isSingleMetric) this.publishStoredMetrics();
178178
}
@@ -322,11 +322,15 @@ class Metrics extends Utility implements MetricsInterface {
322322
* @returns {string}
323323
*/
324324
public serializeMetrics(): EmfOutput {
325-
const metricDefinitions = Object.values(this.storedMetrics).map((metricDefinition) => ({
325+
const metricDefinitions = Object.values(this.storedMetrics).map((metricDefinition) => metricDefinition.resolution ? ({
326326
Name: metricDefinition.name,
327327
Unit: metricDefinition.unit,
328328
StorageResolution: metricDefinition.resolution
329+
}): ({
330+
Name: metricDefinition.name,
331+
Unit: metricDefinition.unit
329332
}));
333+
330334
if (metricDefinitions.length === 0 && this.shouldThrowOnEmptyMetrics) {
331335
throw new RangeError('The number of metrics recorded must be higher than zero');
332336
}
@@ -483,7 +487,7 @@ class Metrics extends Utility implements MetricsInterface {
483487
}
484488
}
485489

486-
private storeMetric(name: string, unit: MetricUnit, value: number, resolution: MetricResolution): void {
490+
private storeMetric(name: string, unit: MetricUnit, value: number, resolution?: MetricResolution): void {
487491
if (Object.keys(this.storedMetrics).length >= MAX_METRICS_SIZE) {
488492
this.publishStoredMetrics();
489493
}
@@ -495,6 +499,7 @@ class Metrics extends Utility implements MetricsInterface {
495499
name,
496500
resolution
497501
};
502+
498503
} else {
499504
const storedMetric = this.storedMetrics[name];
500505
if (!Array.isArray(storedMetric.value)) {

packages/metrics/src/types/Metrics.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ type EmfOutput = {
2121
CloudWatchMetrics: {
2222
Namespace: string
2323
Dimensions: [string[]]
24-
Metrics: { Name: string; Unit: MetricUnit; StorageResolution: MetricResolution }[]
24+
Metrics: { Name: string; Unit: MetricUnit; StorageResolution?: MetricResolution }[]
2525
}[]
2626
}
2727
};
@@ -61,7 +61,7 @@ type StoredMetric = {
6161
name: string
6262
unit: MetricUnit
6363
value: number | number[]
64-
resolution: MetricResolution
64+
resolution?: MetricResolution
6565
};
6666

6767
type StoredMetrics = {

packages/metrics/tests/unit/Metrics.test.ts

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ import { Metrics, MetricUnits, MetricResolution } from '../../src/';
1212
const MAX_METRICS_SIZE = 100;
1313
const MAX_DIMENSION_COUNT = 29;
1414
const DEFAULT_NAMESPACE = 'default_namespace';
15-
const DEFAULT_METRIC_RESOLUTION = MetricResolution.Standard;
1615

1716
const consoleSpy = jest.spyOn(console, 'log').mockImplementation();
1817

@@ -556,8 +555,8 @@ describe('Class: Metrics', () => {
556555
const serializedMetrics = metrics.serializeMetrics();
557556

558557
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics).toStrictEqual([
559-
{ Name: 'test_name', Unit: 'Count', StorageResolution: DEFAULT_METRIC_RESOLUTION },
560-
{ Name: 'test_name2', Unit: 'Count', StorageResolution: DEFAULT_METRIC_RESOLUTION },
558+
{ Name: 'test_name', Unit: 'Count' },
559+
{ Name: 'test_name2', Unit: 'Count' },
561560
]);
562561

563562
expect(serializedMetrics['test_name']).toBe(1);
@@ -566,57 +565,53 @@ describe('Class: Metrics', () => {
566565
});
567566

568567
describe('Feature: Resolution of Metrics', ()=>{
569-
test('Should use default metric resolution `Standard, 60` if none is set',()=>{
568+
test('Should serialized metrics in EMF format not contain StorageResolution as key if none is set',()=>{
570569
const metrics = new Metrics();
571570
metrics.addMetric('test_name', MetricUnits.Seconds, 10);
572571
const serializedMetrics = metrics.serializeMetrics();
573572

574-
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(DEFAULT_METRIC_RESOLUTION);
575-
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(MetricResolution.Standard);
576-
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(60);
573+
expect(Object.keys(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0])).not.toContain('StorageResolution');
574+
expect(Object.keys(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0])).toContain('Name');
575+
expect(Object.keys(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0])).toContain('Unit');
577576

578577
});
579578

580-
test('Should use metric resolution `Standard, 60` if `Standard` is set',()=>{
579+
test('Should be StorageResolution 60 if MetricResolution is set to `Standard`',()=>{
581580
const metrics = new Metrics();
582581
metrics.addMetric('test_name', MetricUnits.Seconds, 10, MetricResolution.Standard);
583582
const serializedMetrics = metrics.serializeMetrics();
584583

585584
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(MetricResolution.Standard);
586585
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(60);
587-
588586
});
589587

590-
test('Should use metric resolution `Standard, 60` if `60` is set',()=>{
588+
test('Should be StorageResolution 60 if MetricResolution is set to `60`',()=>{
591589
const metrics = new Metrics();
592590
metrics.addMetric('test_name', MetricUnits.Seconds, 10, 60);
593591
const serializedMetrics = metrics.serializeMetrics();
594592

595593
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(MetricResolution.Standard);
596594
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(60);
597-
598595
});
599596

600-
test('Should use metric resolution `High, 1` if `1` is set',()=>{
597+
test('Should be StorageResolution 1 if MetricResolution is set to `High`',()=>{
601598
const metrics = new Metrics();
602-
metrics.addMetric('test_name', MetricUnits.Seconds, 10, 1);
599+
metrics.addMetric('test_name', MetricUnits.Seconds, 10, MetricResolution.High);
603600
const serializedMetrics = metrics.serializeMetrics();
604601

605602
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(MetricResolution.High);
606603
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(1);
607-
608604
});
609605

610-
test('Should use metric resolution `High, 1` if `High` is set',()=>{
606+
test('Should be StorageResolution 1 if MetricResolution is set to `1`',()=>{
611607
const metrics = new Metrics();
612-
metrics.addMetric('test_name', MetricUnits.Seconds, 10, MetricResolution.High);
608+
metrics.addMetric('test_name', MetricUnits.Seconds, 10, 1);
613609
const serializedMetrics = metrics.serializeMetrics();
614610

615611
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(MetricResolution.High);
616612
expect(serializedMetrics._aws.CloudWatchMetrics[0].Metrics[0].StorageResolution).toBe(1);
617613

618614
});
619-
620615
});
621616

622617
describe('Feature: Clearing Metrics ', () => {

packages/metrics/tests/unit/middleware/middy.test.ts

Lines changed: 69 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -178,7 +178,7 @@ describe('Middy middleware', () => {
178178
{
179179
Namespace: 'serverlessAirline',
180180
Dimensions: [['service']],
181-
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: MetricResolution.Standard }],
181+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count' }],
182182
},
183183
],
184184
},
@@ -215,7 +215,7 @@ describe('Middy middleware', () => {
215215
{
216216
Namespace: 'serverlessAirline',
217217
Dimensions: [[ 'service', 'environment', 'aws_region', 'function_name' ]],
218-
Metrics: [{ Name: 'ColdStart', Unit: 'Count', StorageResolution: MetricResolution.Standard }],
218+
Metrics: [{ Name: 'ColdStart', Unit: 'Count' }],
219219
},
220220
],
221221
},
@@ -235,7 +235,7 @@ describe('Middy middleware', () => {
235235
{
236236
Namespace: 'serverlessAirline',
237237
Dimensions: [[ 'service', 'environment', 'aws_region' ]],
238-
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: MetricResolution.Standard }],
238+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count' }],
239239
},
240240
],
241241
},
@@ -270,7 +270,7 @@ describe('Middy middleware', () => {
270270
{
271271
Namespace: 'serverlessAirline',
272272
Dimensions: [['service']],
273-
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: MetricResolution.Standard }],
273+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count' }],
274274
},
275275
],
276276
},
@@ -305,7 +305,71 @@ describe('Middy middleware', () => {
305305
{
306306
Namespace: 'serverlessAirline',
307307
Dimensions: [['service']],
308-
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: MetricResolution.Standard }],
308+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count' }],
309+
},
310+
],
311+
},
312+
service: 'orders',
313+
successfulBooking: 1,
314+
})
315+
);
316+
});
317+
});
318+
describe('Feature: Resolution of Metrics', ()=>{
319+
test('Should use metric resolution `Standard, 60` if `Standard` is set', async () => {
320+
// Prepare
321+
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' });
322+
323+
const lambdaHandler = (): void => {
324+
metrics.addMetric('successfulBooking', MetricUnits.Count, 1, MetricResolution.Standard);
325+
};
326+
327+
const handler = middy(lambdaHandler).use(logMetrics(metrics));
328+
329+
// Act
330+
await handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
331+
332+
// Assess
333+
expect(console.log).toHaveBeenCalledWith(
334+
JSON.stringify({
335+
_aws: {
336+
Timestamp: 1466424490000,
337+
CloudWatchMetrics: [
338+
{
339+
Namespace: 'serverlessAirline',
340+
Dimensions: [['service']],
341+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: 60 }],
342+
},
343+
],
344+
},
345+
service: 'orders',
346+
successfulBooking: 1,
347+
})
348+
);
349+
});
350+
test('Should use metric resolution `High, 1` if `High` is set', async () => {
351+
// Prepare
352+
const metrics = new Metrics({ namespace: 'serverlessAirline', serviceName: 'orders' });
353+
354+
const lambdaHandler = (): void => {
355+
metrics.addMetric('successfulBooking', MetricUnits.Count, 1, MetricResolution.High);
356+
};
357+
358+
const handler = middy(lambdaHandler).use(logMetrics(metrics));
359+
360+
// Act
361+
await handler(dummyEvent, dummyContext, () => console.log('Lambda invoked!'));
362+
363+
// Assess
364+
expect(console.log).toHaveBeenCalledWith(
365+
JSON.stringify({
366+
_aws: {
367+
Timestamp: 1466424490000,
368+
CloudWatchMetrics: [
369+
{
370+
Namespace: 'serverlessAirline',
371+
Dimensions: [['service']],
372+
Metrics: [{ Name: 'successfulBooking', Unit: 'Count', StorageResolution: 1 }],
309373
},
310374
],
311375
},

0 commit comments

Comments
 (0)