Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

boomcatch

Package Overview
Dependencies
Maintainers
1
Versions
45
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

boomcatch - npm Package Compare versions

Comparing version 1.1.2 to 1.2.0

src/mappers/har.js

6

HISTORY.md
# History
## 1.2.0
* Tidy up the data format.
* Implement HTTP archive data mapper.
* Add support for syslog-compatible logging.
## 1.1.2

@@ -4,0 +10,0 @@

10

package.json
{
"name": "boomcatch",
"version": "1.1.2",
"version": "1.2.0",
"description": "Standalone beacon server for boomerang.",

@@ -35,4 +35,10 @@ "homepage": "https://github.com/nature/boomcatch",

"get-off-my-log": "0.1.x",
"qs": "0.6.x"
"qs": "0.6.x",
"useragent": "2.0.x",
"yamlparser": "0.0.x",
"request": "2.34.x"
},
"optionalDependencies": {
"rconsole": "0.2.x"
},
"devDependencies": {

@@ -39,0 +45,0 @@ "jshint": "2.4.x",

15

README.md

@@ -10,3 +10,3 @@ # boomcatch

* **boomcatch version**: *1.1.2*
* **boomcatch version**: *1.2.0*
* **node.js versions**: *0.8, 0.10, 0.11*

@@ -89,2 +89,6 @@

* `--syslog <facility>`:
Use [syslog]-compatible logging,
with the specified facility level.
* `--validator <path>`:

@@ -173,5 +177,6 @@ Validator used to accept or reject request data.

for back-end stats consumers.
Currently, one mapper is available out-of-the-box,
which formats the metrics
as [statsd] timers.
Currently, two mappers are available out-of-the-box,
which format the metrics
as [statsd] timers
or as a reduced subset [HTTP archive][har].

@@ -346,3 +351,5 @@ Defining a custom data mapper

[require]: http://nodejs.org/api/globals.html#globals_require
[syslog]: http://en.wikipedia.org/wiki/Syslog
[statsd]: https://github.com/etsy/statsd/
[har]: http://www.softwareishard.com/blog/har-12-spec/
[mapper]: https://github.com/nature/boomcatch/blob/master/src/mappers/statsd.js

@@ -349,0 +356,0 @@ [forwarder]: https://github.com/nature/boomcatch/blob/master/src/forwarders/udp.js

@@ -20,3 +20,3 @@ #!/usr/bin/env node

/*globals require, process */
/*globals require, process, console */

@@ -42,2 +42,3 @@ 'use strict';

.option('-s, --silent', 'prevent the command from logging output to the console')
.option('-y, --syslog <facility>', 'use syslog-compatible logging, with the specified facility level')
.option('-v, --validator <path>', 'validator to use, default is permissive')

@@ -73,3 +74,3 @@ .option('-m, --mapper <path>', 'data mapper to use, default is statsd')

if (!cli.silent) {
cli.log = console.log.bind(console);
cli.log = getLog();
}

@@ -80,1 +81,33 @@

function getLog () {
if (cli.syslog) {
initialiseSyslog();
return console;
}
return getFallbackLog();
}
function initialiseSyslog () {
try {
require('rconsole');
console.set({
facility: cli.syslog,
title: 'boomcatch',
stdout: true,
stderr: true,
showLine: false,
showFile: false,
showTime: true
});
} catch (e) {
console.log('Failed to initialise syslog, exiting.');
process.exit(1);
}
}
function getFallbackLog () {
return require('get-off-my-log').initialise('boomcatch', console.log);
}

@@ -26,3 +26,2 @@ // Copyright © 2014 Nature Publishing Group

qs = require('qs'),
logger = require('get-off-my-log'),

@@ -37,8 +36,13 @@ defaults = {

maxSize: -1,
log: function () {},
log: {
info: function () {},
error: function () {}
},
validator: 'permissive',
mapper: 'statsd',
forwarder: 'udp'
};
},
normalisationMaps;
/**

@@ -58,5 +62,3 @@ * Public function `listen`.

* @option maxSize {number} Maximum body size for POST requests.
* @option log {function} Log function that expects a single string argument
* (without terminating newline character). Defaults to
* `function () {}`.
* @option log {object} Object with `info` and `error` log functions.
* @option validator {string} Validator used to accept or reject beacon requests.

@@ -117,6 +119,6 @@ * Defaults to 'permissive'.

check.verify.maybe.positiveNumber(options.maxSize, 'Invalid max size');
check.verify.maybe.fn(options.log, 'Invalid log function');
check.verify.maybe.unemptyString(options.validator, 'Invalid validator');
verifyOrigin(options.origin);
verifyLog(options.log);

@@ -141,2 +143,11 @@ verifyMapperOptions(options);

function verifyLog (log) {
check.verify.maybe.object(log, 'Invalid log object');
if (check.object(log)) {
check.verify.fn(log.info, 'Invalid log.info function');
check.verify.fn(log.error, 'Invalid log.error function');
}
}
function verifyMapperOptions (options) {

@@ -163,3 +174,3 @@ check.verify.maybe.unemptyString(options.mapper, 'Invalid data mapper');

function getLog (options) {
return logger.initialise('boomcatch', getOption('log', options));
return getOption('log', options);
}

@@ -243,3 +254,3 @@

function handleRequest (log, path, referer, origin, limit, maxSize, validator, mapper, forwarder, request, response) {
var queryIndex, requestPath, state;
var requestPath, remoteAddress, state;

@@ -254,4 +265,3 @@ logRequest(log, request);

queryIndex = request.url.indexOf('?');
requestPath = queryIndex === -1 ? request.url : request.url.substr(0, queryIndex);
requestPath = getRequestPath(request);

@@ -270,3 +280,5 @@ if (requestPath !== path) {

if (!checkLimit(limit, request)) {
remoteAddress = getRemoteAddress(request);
if (!checkLimit(limit, remoteAddress)) {
return fail(log, request, response, 429, 'Exceeded rate `' + limit.time + '`');

@@ -280,3 +292,3 @@ }

request.on('data', receive.bind(null, log, state, maxSize, request, response));
request.on('end', send.bind(null, log, state, validator, mapper, forwarder, request, response));
request.on('end', send.bind(null, log, state, remoteAddress, validator, mapper, forwarder, request, response));
}

@@ -320,2 +332,8 @@

function getRequestPath (request) {
var queryIndex = request.url.indexOf('?');
return queryIndex === -1 ? request.url : request.url.substr(0, queryIndex);
}
function isValidContentType (contentType) {

@@ -333,5 +351,21 @@ if (!contentType) {

function checkLimit (limit, request) {
var now, address, lastRequest, proxiedAddresses, proxy;
function getRemoteAddress (request) {
var proxiedAddresses = request.headers['x-forwarded-for'], filteredAddresses;
if (proxiedAddresses) {
filteredAddresses = proxiedAddresses.split(',').map(function (address) {
return address.trim();
}).filter(check.unemptyString);
if (filteredAddresses.length > 0) {
return filteredAddresses[0];
}
}
return request.socket.remoteAddress;
}
function checkLimit (limit, remoteAddress) {
var now, lastRequest;
if (limit === null) {

@@ -342,11 +376,4 @@ return true;

now = Date.now();
address = request.socket.remoteAddress;
lastRequest = limit.requests[address];
proxiedAddresses = request.headers['x-forwarded-for'];
lastRequest = limit.requests[remoteAddress];
if (check.object(lastRequest)) {
proxy = lastRequest;
lastRequest = lastRequest[proxiedAddresses || 'self'];
}
if (check.positiveNumber(lastRequest) && now <= lastRequest + limit.time) {

@@ -356,14 +383,4 @@ return false;

if (proxiedAddresses) {
if (!proxy) {
proxy = limit.requests[address] = {
self: lastRequest
};
}
limit.requests[remoteAddress] = now;
proxy[proxiedAddresses] = now;
} else {
limit.requests[address] = now;
}
return true;

@@ -384,3 +401,3 @@ }

function send (log, state, validator, mapper, forwarder, request, response) {
function send (log, state, remoteAddress, validator, mapper, forwarder, request, response) {
try {

@@ -416,3 +433,3 @@ var successStatus, data, mappedData;

mappedData = mapper(normaliseData(data), request.headers.referer);
mappedData = mapper(normaliseData(data), request.headers.referer, request.headers['user-agent'], remoteAddress);
if (mappedData === '') {

@@ -437,33 +454,38 @@ throw null;

function normaliseData (data) {
// TODO: Add metadata for URL, browser, geolocation
return {
boomerang: normaliseBoomerangData(data),
navtiming: normaliseNavigationTimingApiData(data),
restiming: normaliseResourceTimingApiData(data)
rt: normaliseRtData(data),
navtiming: normaliseNavtimingData(data),
restiming: normaliseRestimingData(data)
};
}
function normaliseBoomerangData (data) {
function normaliseRtData (data) {
/*jshint camelcase:false */
var startTime, timeToFirstByte, timeToLoad;
var start, timeToFirstByte, timeToLastByte, timeToLoad;
if (data['rt.tstart']) {
startTime = parseInt(data['rt.tstart']);
}
if (data.t_resp) {
timeToFirstByte = parseInt(data.t_resp);
}
start = getOptionalDatum(data, 'rt.tstart');
timeToFirstByte = getOptionalDatum(data, 't_resp');
timeToLastByte = getOptionalSum(data, 't_resp', 't_page');
timeToLoad = parseInt(data.t_done);
if (
check.maybe.positiveNumber(startTime) &&
check.maybe.positiveNumber(start) &&
check.maybe.positiveNumber(timeToFirstByte) &&
check.positiveNumber(timeToLoad)
check.maybe.positiveNumber(timeToLastByte) &&
check.positiveNumber(timeToLoad) &&
check.unemptyString(data.r)
) {
return {
start: startTime,
firstbyte: timeToFirstByte,
load: timeToLoad
timestamps: {
start: start
},
events: {},
durations: {
firstbyte: timeToFirstByte,
lastbyte: timeToLastByte,
load: timeToLoad
},
url: data.r
};

@@ -473,80 +495,151 @@ }

function normaliseNavigationTimingApiData (data) {
function getOptionalDatum (data, key) {
if (data[key]) {
return parseInt(data[key]);
}
}
function getOptionalSum (data, aKey, bKey) {
if (data[aKey] && data[bKey]) {
return parseInt(data[aKey]) + parseInt(data[bKey]);
}
}
function normaliseNavtimingData (data) {
/*jshint camelcase:false */
var result = normaliseCategory(normalisationMaps.navtiming, data, 'nt_nav_st');
var startTime, redirectDuration, dnsDuration, connectDuration, timeToFirstByte, timeToDomLoad, timeToLoad;
if (result) {
result.type = data.nt_nav_type;
}
startTime = parseInt(data.nt_nav_st);
redirectDuration = parseInt(data.nt_red_end) - parseInt(data.nt_red_st);
dnsDuration = parseInt(data.nt_dns_end) - parseInt(data.nt_dns_st);
connectDuration = parseInt(data.nt_con_end) - parseInt(data.nt_con_st);
timeToFirstByte = parseInt(data.nt_res_st) - parseInt(data.nt_fet_st);
timeToDomLoad = parseInt(data.nt_domcontloaded_st) - parseInt(data.nt_fet_st);
timeToLoad = parseInt(data.nt_load_st) - parseInt(data.nt_fet_st);
return result;
}
if (
check.positiveNumber(startTime) &&
check.number(redirectDuration) &&
check.number(dnsDuration) &&
check.number(connectDuration) &&
check.positiveNumber(timeToFirstByte) &&
check.positiveNumber(timeToDomLoad) &&
check.positiveNumber(timeToLoad)
) {
normalisationMaps = {
navtiming: {
timestamps: [
{ key: 'nt_nav_st', name: 'start' },
{ key: 'nt_fet_st', name: 'fetchStart' },
{ key: 'nt_ssl_st', name: 'sslStart', optional: true },
{ key: 'nt_req_st', name: 'requestStart' },
{ key: 'nt_domint', name: 'domInteractive' }
],
events: [
{ start: 'nt_unload_st', end: 'nt_unload_end', name: 'unload' },
{ start: 'nt_red_st', end: 'nt_red_end', name: 'redirect' },
{ start: 'nt_dns_st', end: 'nt_dns_end', name: 'dns' },
{ start: 'nt_con_st', end: 'nt_con_end', name: 'connect' },
{ start: 'nt_res_st', end: 'nt_res_end', name: 'response' },
{ start: 'nt_domloading', end: 'nt_domcomp', name: 'dom' },
{ start: 'nt_domcontloaded_st', end: 'nt_domcontloaded_end', name: 'domContent' },
{ start: 'nt_load_st', end: 'nt_load_end', name: 'load' }
],
durations: []
},
restiming: {
timestamps: [
{ key: 'rt_st', name: 'start' },
{ key: 'rt_fet_st', name: 'fetchStart' },
{ key: 'rt_scon_st', name: 'sslStart', optional: true },
{ key: 'rt_req_st', name: 'requestStart', optional: true }
],
events: [
{ start: 'rt_red_st', end: 'rt_red_end', name: 'redirect', optional: true },
{ start: 'rt_dns_st', end: 'rt_dns_end', name: 'dns', optional: true },
{ start: 'rt_con_st', end: 'rt_con_end', name: 'connect', optional: true },
{ start: 'rt_res_st', end: 'rt_res_end', name: 'response', optional: true }
],
durations: []
}
};
function normaliseCategory (map, data, startKey) {
try {
return {
start: startTime,
redirect: redirectDuration,
dns: dnsDuration,
connect: connectDuration,
firstbyte: timeToFirstByte,
domload: timeToDomLoad,
load: timeToLoad
timestamps: normaliseTimestamps(map, data),
events: normaliseEvents(map, data),
durations: normaliseDurations(map, data, startKey)
};
} catch (e) {
}
}
function normaliseResourceTimingApiData (data) {
/*jshint camelcase:false */
function normaliseTimestamps (map, data) {
return map.timestamps.reduce(function (result, timestamp) {
var value, verify;
var startTime, redirectDuration, dnsDuration, connectDuration, timeToFirstByte, timeToLoad;
if (data[timestamp.key]) {
value = parseInt(data[timestamp.key]);
}
verify = timestamp.optional ? check.verify.maybe : check.verify;
verify.positiveNumber(value);
if (value) {
result[timestamp.name] = value;
}
return result;
}, {});
}
function normaliseEvents (map, data) {
return map.events.reduce(function (result, event) {
var start, end, verify;
if (data[event.start] && data[event.end]) {
start = parseInt(data[event.start]);
end = parseInt(data[event.end]);
}
verify = event.optional ? check.verify.maybe : check.verify;
verify.positiveNumber(start);
verify.positiveNumber(end);
if (start && end) {
result[event.name] = {
start: start,
end: end
};
}
return result;
}, {});
}
function normaliseDurations (map, data, startKey) {
var start = parseInt(data[startKey]);
return map.durations.reduce(function (result, duration) {
var value, verify;
if (data[duration.end]) {
value = parseInt(data[duration.end]) - start;
}
verify = duration.optional ? check.verify.maybe : check.verify;
verify.number(value);
check.verify.not.negativeNumber(value);
if (value) {
result[duration.name] = value;
}
return result;
}, {});
}
function normaliseRestimingData (data) {
/*jshint camelcase:false */
if (check.array(data.restiming)) {
return data.restiming.map(function (resource) {
// NOTE: We are wilfully reducing precision here from 1/1000th of a millisecond,
// for consistency with the Navigation Timing API. Open a pull request if
// you think that is the wrong decision! :)
startTime = parseInt(resource.rt_st);
redirectDuration = getOptionalResourceTiming(resource, 'rt_red_end', 'rt_red_st');
dnsDuration = getOptionalResourceTiming(resource, 'rt_dns_end', 'rt_dns_st');
connectDuration = getOptionalResourceTiming(resource, 'rt_con_end', 'rt_con_st');
timeToFirstByte = getOptionalResourceTiming(resource, 'rt_res_st', 'rt_st');
timeToLoad = parseInt(resource.rt_dur);
return data.restiming.map(function (datum) {
var result = normaliseCategory(normalisationMaps.restiming, datum, 'rt_st');
// HACK: Google Chrome sometimes reports a zero responseEnd timestamp (which is not
// conformant behaviour), leading to a negative duration. A negative duration
// is manifestly nonsense, so force it to zero instead. Bug report:
// https://code.google.com/p/chromium/issues/detail?id=346960
if (timeToLoad < 0) {
timeToLoad = 0;
if (result) {
result.name = datum.rt_name;
result.type = datum.rt_in_type;
}
if (
check.positiveNumber(startTime) &&
check.maybe.number(redirectDuration) &&
check.maybe.number(dnsDuration) &&
check.maybe.number(connectDuration) &&
check.maybe.positiveNumber(timeToFirstByte) &&
check.number(timeToLoad)
) {
return {
name: resource.rt_name,
type: resource.rt_in_type,
start: startTime,
redirect: redirectDuration,
dns: dnsDuration,
connect: connectDuration,
firstbyte: timeToFirstByte,
load: timeToLoad
};
}
return result;
});

@@ -556,8 +649,2 @@ }

function getOptionalResourceTiming (data, endKey, startKey) {
if (data[endKey] && data[startKey]) {
return parseInt(data[endKey]) - parseInt(data[startKey]);
}
}
function pass (log, response, status, bytes) {

@@ -564,0 +651,0 @@ log.info('sent ' + bytes + ' bytes');

@@ -48,9 +48,9 @@ // Copyright © 2014 Nature Publishing Group

Object.keys(metrics).forEach(function (category) {
if (data.hasOwnProperty(category)) {
if (category === 'restiming') {
mapper = mapResourceTimingMetrics;
} else {
mapper = mapMetrics;
}
if (category === 'restiming') {
mapper = mapRestimingMetrics;
} else {
mapper = mapMetrics;
}
if (data[category]) {
result += mapper(metrics[category], prefix + category + '.', data[category], referer);

@@ -63,5 +63,4 @@ }

function mapResourceTimingMetrics (metrics, prefix, data, referer) {
function mapRestimingMetrics (metrics, prefix, data, referer) {
return data.map(function (resource, index) {
/*jshint camelcase:false */
return mapMetrics(metrics, [

@@ -83,13 +82,12 @@ prefix + base36Encode(referer),

function mapMetrics (metrics, prefix, data) {
return mapTimestamps(metrics, prefix, data) + mapDurations(metrics, prefix, data);
return mapEvents(metrics, prefix, data) +
mapDurations(metrics, prefix, data);
}
function mapTimestamps (metrics, prefix, data) {
return mapStuff(metrics.timestamps, prefix, data, 'g');
}
function mapEvents (metrics, prefix, data) {
return metrics.events.map(function (metric) {
var datum = data.events[metric];
function mapStuff (metrics, prefix, data, suffix) {
return metrics.map(function (metric) {
if (check.number(data[metric])) {
return prefix + metric + ':' + data[metric] + '|' + suffix + '\n';
if (check.object(datum)) {
return mapMetric(prefix, metric, datum.end - datum.start);
}

@@ -101,5 +99,17 @@

function mapMetric (prefix, name, value) {
return prefix + name + ':' + value + '|ms' + '\n';
}
function mapDurations (metrics, prefix, data) {
return mapStuff(metrics.durations, prefix, data, 'ms');
return metrics.durations.map(function (metric) {
var datum = data.durations[metric];
if (check.number(datum)) {
return mapMetric(prefix, metric, datum);
}
return '';
}).join('');
}

@@ -23,15 +23,29 @@ // Copyright © 2014 Nature Publishing Group

module.exports = {
boomerang: {
// Metric definitions for use by data mappers. There are currently three categories
// of metric, corresponding to three different boomerang plugins: rt, navtiming and
// restiming.
//
// Within each category, there are three types of metric that are available for
// data mappers: timestamps, durations and events.
//
// * timestamps: milliseconds since the epoch for some event.
// * events: an object with `start` and `end` timestamp properties.
// * durations: milliseconds difference between the start timestamp and some
// other point.
rt: {
timestamps: [ 'start' ],
durations: [ 'firstbyte', 'load' ]
events: [],
durations: [ 'firstbyte', 'lastbyte', 'load' ]
},
navtiming: {
timestamps: [ 'start' ],
durations: [ 'redirect', 'dns', 'connect', 'firstbyte', 'domload', 'load' ]
timestamps: [ 'start', 'fetchStart', 'sslStart', 'requestStart', 'domInteractive' ],
events: [ 'unload', 'redirect', 'dns', 'connect', 'response', 'dom', 'domContent', 'load' ],
durations: []
},
restiming: {
timestamps: [ 'start' ],
durations: [ 'redirect', 'dns', 'connect', 'firstbyte', 'load' ]
timestamps: [ 'start', 'fetchStart', 'sslStart', 'requestStart' ],
events: [ 'redirect', 'dns', 'connect', 'response' ],
durations: []
}
};

@@ -107,36 +107,69 @@ // Copyright © 2014 Nature Publishing Group

result = mapper({
boomerang: {
start: 1,
firstbyte: 2,
load: 3
rt: {
timestamps: {
start: 1
},
events: {},
durations: {
firstbyte: 2,
lastbyte: 3,
load: 4
},
r: 'http://www.example.com/foo'
},
navtiming: {
start: 4,
redirect: 5,
dns: 6,
connect: 7,
firstbyte: 8,
domload: 9,
load: 10
timestamps: {
start: 5,
fetchStart: 6,
sslStart: 7,
requestStart: 8,
domInteractive: 9
},
events: {
unload: { start: 10, end: 20 },
redirect: { start: 11, end: 22 },
dns: { start: 12, end: 24 },
connect: { start: 13, end: 26 },
response: { start: 14, end: 28 },
dom: { start: 15, end: 30 },
domContent: { start: 16, end: 32 },
load: { start: 17, end: 34 }
},
durations: {},
type: 'bar'
},
restiming: [
{
name: 'http://www.example.com/foo',
type: 'css',
start: 11,
redirect: 12,
dns: 13,
connect: 14,
firstbyte: 15,
load: 16
timestamps: {
start: 18,
fetchStart: 19,
sslStart: 20,
requestStart: 21
},
events: {
redirect: { start: 22, end: 44 },
dns: { start: 23, end: 46 },
connect: { start: 24, end: 48 },
response: { start: 25, end: 50 }
},
durations: {},
name: 'http://www.example.com/baz',
type: 'css'
},
{
name: 'foo bar baz qux',
type: 'img',
start: 17,
redirect: 18,
dns: 19,
connect: 20,
firstbyte: 21,
load: 22
timestamps: {
start: 26,
fetchStart: 27,
sslStart: 28,
requestStart: 29
},
events: {
redirect: { start: 30, end: 60 },
dns: { start: 31, end: 62 },
connect: { start: 32, end: 64 },
response: { start: 33, end: 66 }
},
durations: {},
name: 'http://www.example.com/qux',
type: 'img'
}

@@ -153,24 +186,21 @@ ]

assert.strictEqual(result, [
'boomerang.start:1|g',
'boomerang.firstbyte:2|ms',
'boomerang.load:3|ms',
'navtiming.start:4|g',
'navtiming.redirect:5|ms',
'navtiming.dns:6|ms',
'navtiming.connect:7|ms',
'navtiming.firstbyte:8|ms',
'navtiming.domload:9|ms',
'navtiming.load:10|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.start:11|g',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.redirect:12|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.dns:13|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.connect:14|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.firstbyte:15|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2u3333.load:16|ms',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.start:17|g',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.redirect:18|ms',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.dns:19|ms',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.connect:20|ms',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.firstbyte:21|ms',
'restiming.3b2x2q2q302t.1.img.2u3333w2q2p36w2q2p3ew35393c.load:22|ms',
'rt.firstbyte:2|ms',
'rt.lastbyte:3|ms',
'rt.load:4|ms',
'navtiming.unload:10|ms',
'navtiming.redirect:11|ms',
'navtiming.dns:12|ms',
'navtiming.connect:13|ms',
'navtiming.response:14|ms',
'navtiming.dom:15|ms',
'navtiming.domContent:16|ms',
'navtiming.load:17|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2q2p3e.redirect:22|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2q2p3e.dns:23|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2q2p3e.connect:24|ms',
'restiming.3b2x2q2q302t.0.css.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b2q2p3e.response:25|ms',
'restiming.3b2x2q2q302t.1.img.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b35393c.redirect:30|ms',
'restiming.3b2x2q2q302t.1.img.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b35393c.dns:31|ms',
'restiming.3b2x2q2q302t.1.img.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b35393c.connect:32|ms',
'restiming.3b2x2q2q302t.1.img.2w3838341m1b1b3b3b3b1a2t3c2p3134302t1a2r33311b35393c.response:33|ms',
''

@@ -186,13 +216,8 @@ ].join('\n'));

result = mapper({
navtiming: {
start: 111,
redirect: 222,
dns: 333,
connect: 444,
firstbyte: 555,
domload: 666,
load: 777
},
boomerang: {
load: 888
rt: {
timestamps: {},
events: {},
durations: {
load: 10
}
}

@@ -207,13 +232,3 @@ });

test('result was correct', function () {
assert.strictEqual(result, [
'boomerang.load:888|ms',
'navtiming.start:111|g',
'navtiming.redirect:222|ms',
'navtiming.dns:333|ms',
'navtiming.connect:444|ms',
'navtiming.firstbyte:555|ms',
'navtiming.domload:666|ms',
'navtiming.load:777|ms',
''
].join('\n'));
assert.strictEqual(result, 'rt.load:10|ms\n');
});

@@ -261,4 +276,8 @@ });

result = mapper({
boomerang: {
load: 1
rt: {
timestamps: {},
events: {},
durations: {
load: 1
}
}

@@ -273,3 +292,3 @@ });

test('result was correct', function () {
assert.strictEqual(result, 'foo.boomerang.load:1|ms\n');
assert.strictEqual(result, 'foo.rt.load:1|ms\n');
});

@@ -301,4 +320,8 @@ });

result = mapper({
boomerang: {
load: 2
rt: {
timestamps: {},
events: {},
durations: {
load: 2
}
}

@@ -313,3 +336,3 @@ });

test('result was correct', function () {
assert.strictEqual(result, 'bar.boomerang.load:2|ms\n');
assert.strictEqual(result, 'bar.rt.load:2|ms\n');
});

@@ -316,0 +339,0 @@ });

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc