Skip to content

Commit cb6e5d2

Browse files
committed
disallow duplicate dimensions sets
Closes #20
1 parent 6132122 commit cb6e5d2

File tree

3 files changed

+86
-12
lines changed

3 files changed

+86
-12
lines changed

src/logger/MetricsContext.ts

Lines changed: 28 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -88,8 +88,34 @@ export class MetricsContext {
8888
*
8989
* @param dimensions
9090
*/
91-
public putDimensions(dimensions: Record<string, string>): void {
92-
this.dimensions.push(dimensions);
91+
public putDimensions(incomingDimensionSet: Record<string, string>): void {
92+
if (this.dimensions.length === 0) {
93+
this.dimensions.push(incomingDimensionSet);
94+
return;
95+
}
96+
97+
for (let i = 0; i < this.dimensions.length; i++) {
98+
const existingDimensionSet = this.dimensions[i];
99+
100+
// check for duplicate dimensions when putting
101+
// this is an O(n^2) operation, but since we never expect to have more than
102+
// 10 dimensions, this is acceptable for almost all cases.
103+
// This makes re-using loggers much easier.
104+
const existingDimensionSetKeys = Object.keys(existingDimensionSet);
105+
const incomingDimensionSetKeys = Object.keys(incomingDimensionSet);
106+
if (existingDimensionSetKeys.length !== incomingDimensionSetKeys.length) {
107+
this.dimensions.push(incomingDimensionSet);
108+
return;
109+
}
110+
111+
for (let j = 0; j < existingDimensionSetKeys.length; j++) {
112+
if (!incomingDimensionSetKeys.includes(existingDimensionSetKeys[j])) {
113+
// we're done now because we know that the dimensions keys are not identical
114+
this.dimensions.push(incomingDimensionSet);
115+
return;
116+
}
117+
}
118+
}
93119
}
94120

95121
/**

src/logger/__tests__/MetricsContext.test.ts

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,53 @@ test('putDimension adds key to dimension and sets the dimension as a property',
2929
expect(context.getDimensions()[0]).toStrictEqual(expectedDimension);
3030
});
3131

32+
test('putDimension will not duplicate dimensions', () => {
33+
// arrange
34+
const context = MetricsContext.empty();
35+
const dimension = faker.random.word();
36+
const expectedDimension = { dimension };
37+
38+
// act
39+
context.putDimensions({ dimension });
40+
context.putDimensions({ dimension });
41+
42+
// assert
43+
expect(context.getDimensions().length).toBe(1);
44+
expect(context.getDimensions()[0]).toStrictEqual(expectedDimension);
45+
});
46+
47+
test('putDimension will not duplicate dimensions, multiple in different order', () => {
48+
// arrange
49+
const context = MetricsContext.empty();
50+
const dimension1 = faker.random.word();
51+
const dimension2 = faker.random.word();
52+
const expectedDimension = { dimension1, dimension2 };
53+
54+
// act
55+
context.putDimensions({ dimension1, dimension2 });
56+
context.putDimensions({ dimension2, dimension1 });
57+
58+
// assert
59+
expect(context.getDimensions().length).toBe(1);
60+
expect(context.getDimensions()[0]).toStrictEqual(expectedDimension);
61+
});
62+
63+
test('putDimension accepts multiple unique dimension sets', () => {
64+
// arrange
65+
const context = MetricsContext.empty();
66+
const expectedDimension1 = { d1: faker.random.word(), d2: faker.random.word() };
67+
const expectedDimension2 = { d2: faker.random.word(), d3: faker.random.word() };
68+
69+
// act
70+
context.putDimensions(expectedDimension1);
71+
context.putDimensions(expectedDimension2);
72+
73+
// assert
74+
expect(context.getDimensions().length).toBe(2);
75+
expect(context.getDimensions()[0]).toStrictEqual(expectedDimension1);
76+
expect(context.getDimensions()[1]).toStrictEqual(expectedDimension2);
77+
});
78+
3279
test('getDimensions returns default dimensions if custom dimensions not set', () => {
3380
// arrange
3481
const context = MetricsContext.empty();

test/integ/agent/end-to-end.integ.ts

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -90,16 +90,17 @@ test(
9090

9191
Configuration.agentEndpoint = 'tcp://0.0.0.0:25888';
9292

93-
const doWork = metricScope(metrics => () => {
94-
metrics.putDimensions(dimensions);
95-
metrics.putMetric(metricName, 100, 'Milliseconds');
96-
metrics.setProperty('RequestId', '422b1569-16f6-4a03-b8f0-fe3fd9b100f8');
97-
});
98-
99-
// act
100-
doWork();
101-
await Sleep(idleTimeout);
102-
doWork();
93+
const doWork = metricScope(metrics => () => {
94+
metrics.putDimensions(dimensions);
95+
metrics.putMetric(metricName, 100, 'Milliseconds');
96+
metrics.setProperty('RequestId', '422b1569-16f6-4a03-b8f0-fe3fd9b100f8');
97+
});
98+
99+
// act
100+
doWork();
101+
doWork();
102+
await Sleep(idleTimeout);
103+
doWork();
103104

104105
// assert
105106
await waitForMetricExistence(metricName, expectedSamples);

0 commit comments

Comments
 (0)