Skip to content

Commit 9d2dffa

Browse files
author
Ilias Tsangaris
authored
Node v4.2.0 - Clamp bufferLength, better dev mode debugging, and flush queue on process exit (#284)
* feat(node): cap the buffer length at 100 logs * feat(node): ensure buffer length is between 1 and 30 and flush queue on process exit
1 parent 3825030 commit 9d2dffa

File tree

4 files changed

+41
-32
lines changed

4 files changed

+41
-32
lines changed

packages/node/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ app.use(readme.metrics('<<apiKey>>', req => ({
6060
| Option | Use |
6161
| :----------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
6262
| development | **default: false** If true, the log will be separate from normal production logs. This is great for separating staging or test data from data coming from customers. |
63-
| bufferLength | **default: 10** By default, we only send logs to ReadMe after 10 requests are made. Depending on the usage of your API it make make sense to send logs more or less frequently. |
63+
| bufferLength | **default: 1** By default, we perform a buffer flush to ReadMe after a single request is made. Depending on the usage of your API it make make sense to do this more or less frequently. The buffer will always flush after 30 logs are made, so any number that is larger will be ignored. Also keep in mind that any request over 1mb will receive a 413 response. |
6464
| denylist | **optional** An array of keys from your API requests, responses headers, and request bodies that you wish to not be sent to ReadMe.<br /><br />If you configure a `denylist`, it will override any `allowlist` configuration. |
6565
| allowlist | **optional** An array of keys from your API requests and responses headers and bodies that you only wish to send to ReadMe. |
6666
| baseLogUrl | **optional** This is the base URL for your ReadMe project. Normally this would be `https://projectName.readme.io` or `https://docs.yourdomain.com`, however if this value is not supplied, a request to the ReadMe API will be made once a day to retrieve it. This data is cached into `node_modules/.cache/readmeio`. |

packages/node/index.js

+37-28
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,15 @@ const crypto = require('crypto');
55
const config = require('./config');
66
const flatCache = require('flat-cache');
77
const findCacheDir = require('find-cache-dir');
8+
const clamp = require('lodash/clamp');
89
const pkg = require('./package.json');
910

1011
const constructPayload = require('./lib/construct-payload');
1112

13+
// Make sure we flush the queue if the process is exited
14+
let doSend = () => {};
15+
process.on('exit', doSend);
16+
1217
// We're doing this to buffer up the response body
1318
// so we can send it off to the metrics server
1419
// It's unfortunate that this isn't accessible
@@ -96,7 +101,8 @@ module.exports.metrics = (apiKey, group, options = {}) => {
96101
if (!apiKey) throw new Error('You must provide your ReadMe API key');
97102
if (!group) throw new Error('You must provide a grouping function');
98103

99-
const bufferLength = options.bufferLength || config.bufferLength;
104+
// Ensures the buffer length is between 1 and 30
105+
const bufferLength = clamp(options.bufferLength || config.bufferLength, 1, 30);
100106
const requestTimeout = config.timeout;
101107
const encodedApiKey = Buffer.from(`${apiKey}:`).toString('base64');
102108
let baseLogUrl = options.baseLogUrl || undefined;
@@ -116,48 +122,51 @@ module.exports.metrics = (apiKey, group, options = {}) => {
116122

117123
patchResponse(res);
118124

119-
function send() {
125+
doSend = () => {
126+
const json = queue.slice();
127+
queue = [];
128+
129+
const signal = timeoutSignal(requestTimeout);
130+
131+
fetch(`${config.host}/v1/request`, {
132+
method: 'post',
133+
body: JSON.stringify(json),
134+
headers: {
135+
Authorization: `Basic ${encodedApiKey}`,
136+
'Content-Type': 'application/json',
137+
'User-Agent': `${pkg.name}/${pkg.version}`,
138+
},
139+
signal,
140+
})
141+
.then(() => {})
142+
.catch(e => {
143+
// Silently discard errors and timeouts.
144+
if (options.development) throw e;
145+
})
146+
.finally(() => {
147+
timeoutSignal.clear(signal);
148+
});
149+
};
150+
151+
function startSend() {
120152
// This should in future become more sophisticated,
121153
// with flush timeouts and more error checking but
122154
// this is fine for now
123155
const payload = constructPayload(req, res, group, options, { logId, startedDateTime });
124156
queue.push(payload);
125-
if (queue.length >= bufferLength) {
126-
const json = queue.slice();
127-
queue = [];
128-
129-
const signal = timeoutSignal(requestTimeout);
130-
131-
fetch(`${config.host}/v1/request`, {
132-
method: 'post',
133-
body: JSON.stringify(json),
134-
headers: {
135-
Authorization: `Basic ${encodedApiKey}`,
136-
'Content-Type': 'application/json',
137-
'User-Agent': `${pkg.name}/${pkg.version}`,
138-
},
139-
signal,
140-
})
141-
.then(() => {})
142-
.catch(() => {
143-
// Silently discard errors and timeouts.
144-
})
145-
.finally(() => {
146-
timeoutSignal.clear(signal);
147-
});
148-
}
157+
if (queue.length >= bufferLength) doSend();
149158

150159
cleanup(); // eslint-disable-line no-use-before-define
151160
}
152161

153162
function cleanup() {
154-
res.removeListener('finish', send);
163+
res.removeListener('finish', startSend);
155164
res.removeListener('error', cleanup);
156165
res.removeListener('close', cleanup);
157166
}
158167

159168
// Add response listeners
160-
res.once('finish', send);
169+
res.once('finish', startSend);
161170
res.once('error', cleanup);
162171
res.once('close', cleanup);
163172

packages/node/package-lock.json

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/node/package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "readmeio",
33
"description": "Track your API metrics within ReadMe.",
4-
"version": "4.1.0",
4+
"version": "4.2.0",
55
"license": "ISC",
66
"homepage": "https://readme.com/metrics",
77
"bugs": {

0 commit comments

Comments
 (0)