Skip to content

Commit 3e8ff54

Browse files
fix: issue where the same logs would get sent multiple times (#8)
* fix: issue where the same logs would get sent multiple times This is caused by us only clearing out the queue when the metrics response came back * Prettier * fix: test coverage * test: improving the tests for queue flushing * test: delaying for 1s, not 1ms * fix: removing an unused test callback that was put in place for mocha * test: making requests slightly more unique to avoid test date flakiness Co-authored-by: Dom Harrington <[email protected]>
1 parent e60f154 commit 3e8ff54

File tree

3 files changed

+53
-17
lines changed

3 files changed

+53
-17
lines changed

packages/node/__tests__/index.test.js

+47-8
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
const express = require('express');
22
const request = require('supertest');
33
const nock = require('nock');
4+
const crypto = require('crypto');
45
const { isValidUUIDV4 } = require('is-valid-uuid-v4');
56
const config = require('../config');
67

78
const middleware = require('..');
89

9-
const apiKey = 'OUW3RlI4gUCwWGpO10srIo2ufdWmMhMH';
10+
const apiKey = 'fakeApiKey';
11+
const group = '5afa21b97011c63320226ef3';
1012

1113
expect.extend({
1214
toHaveLogHeader(res) {
@@ -50,8 +52,6 @@ describe('#metrics', () => {
5052
});
5153

5254
it('should send a request to the metrics server', async function test() {
53-
const group = '5afa21b97011c63320226ef3';
54-
5555
const mock = nock(config.host)
5656
.post('/v1/request', ([body]) => {
5757
expect(body.group).toBe(group);
@@ -75,8 +75,6 @@ describe('#metrics', () => {
7575

7676
describe('#bufferLength', () => {
7777
it('should send requests when number hits `bufferLength` size', async function test() {
78-
const group = '5afa21b97011c63320226ef3';
79-
8078
const mock = nock(config.host)
8179
.post('/v1/request', body => {
8280
expect(body).toHaveLength(3);
@@ -123,6 +121,47 @@ describe('#metrics', () => {
123121
expect(mock.isDone()).toBe(true);
124122
mock.done();
125123
});
124+
125+
it('should clear out the queue when sent', () => {
126+
const numberOfLogs = 20;
127+
const numberOfMocks = 4;
128+
const bufferLength = numberOfLogs / numberOfMocks;
129+
130+
const seenLogs = [];
131+
132+
const mocks = [...new Array(numberOfMocks).keys()].map(() =>
133+
nock(config.host)
134+
.post('/v1/request', body => {
135+
expect(body).toHaveLength(bufferLength);
136+
137+
// Ensure that our executed requests and the buffered queue they're in remain unique.
138+
body.forEach(req => {
139+
const requestHash = crypto.createHash('md5').update(JSON.stringify(req)).digest('hex');
140+
expect(seenLogs).not.toContain(requestHash);
141+
seenLogs.push(requestHash);
142+
});
143+
144+
return true;
145+
})
146+
// This is the important part of this test,
147+
// the delay mimics the latency of a real
148+
// HTTP request
149+
.delay(1000)
150+
.reply(200)
151+
);
152+
153+
const app = express();
154+
app.use(middleware.metrics(apiKey, () => group, { bufferLength }));
155+
app.get('/test', (req, res) => res.sendStatus(200));
156+
157+
return Promise.all(
158+
[...new Array(numberOfLogs).keys()].map(i => {
159+
return request(app).get(`/test?log=${i}`).expect(200);
160+
})
161+
).then(() => {
162+
mocks.map(mock => mock.done());
163+
});
164+
});
126165
});
127166

128167
describe('`res._body`', () => {
@@ -139,7 +178,7 @@ describe('#metrics', () => {
139178
it('should buffer up res.write() calls', async function test() {
140179
const mock = createMock();
141180
const app = express();
142-
app.use(middleware.metrics(apiKey, () => '123'));
181+
app.use(middleware.metrics(apiKey, () => group));
143182
app.get('/test', (req, res) => {
144183
res.write('{"a":1,');
145184
res.write('"b":2,');
@@ -155,7 +194,7 @@ describe('#metrics', () => {
155194
it('should buffer up res.end() calls', async function test() {
156195
const mock = createMock();
157196
const app = express();
158-
app.use(middleware.metrics(apiKey, () => '123'));
197+
app.use(middleware.metrics(apiKey, () => group));
159198
app.get('/test', (req, res) => res.end(JSON.stringify(responseBody)));
160199

161200
await request(app)
@@ -169,7 +208,7 @@ describe('#metrics', () => {
169208
it('should work for res.send() calls', async function test() {
170209
const mock = createMock();
171210
const app = express();
172-
app.use(middleware.metrics(apiKey, () => '123'));
211+
app.use(middleware.metrics(apiKey, () => group));
173212
app.get('/test', (req, res) => res.send(responseBody));
174213

175214
await request(app)

packages/node/config/default.json

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
22
"host": "https://metrics.readme.io",
3-
"readmeUrl": "https://dash.readme.io",
43
"bufferLength": 1
54
}

packages/node/index.js

+6-8
Original file line numberDiff line numberDiff line change
@@ -49,14 +49,12 @@ module.exports.metrics = (apiKey, group, options = {}) => {
4949
const payload = constructPayload(req, res, group, options, { logId, startedDateTime });
5050
queue.push(payload);
5151
if (queue.length >= bufferLength) {
52-
request
53-
.post(`${config.host}/v1/request`, {
54-
headers: { authorization: `Basic ${encoded}` },
55-
json: queue,
56-
})
57-
.response.then(() => {
58-
queue = [];
59-
});
52+
const json = queue.slice();
53+
queue = [];
54+
request.post(`${config.host}/v1/request`, {
55+
headers: { authorization: `Basic ${encoded}` },
56+
json,
57+
});
6058
}
6159

6260
cleanup(); // eslint-disable-line no-use-before-define

0 commit comments

Comments
 (0)