From 50246d3f0e4d03dc585bc8ee983b824e6ad88e05 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:20:59 -0400 Subject: [PATCH 01/19] Add new, faster overrideTags implementation --- lib/helpers.js | 38 ++++++++++++++++++++++++++++++++++++-- lib/statsd.js | 43 ++++++++++++++++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 11 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index 7ac979e..ad81a0e 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -28,7 +28,7 @@ function formatTags(tags, telegraf) { * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new * array. parent and child are not mutated. */ -function overrideTags (parent, child, telegraf) { +function overrideTags (parent, child, telegraf, tagSeparator) { const seenKeys = {}; const toAppend = []; @@ -58,7 +58,40 @@ function overrideTags (parent, child, telegraf) { } const tags = parentTags.concat(childTags); - return toAppend.length > 0 ? tags.concat(toAppend) : tags; + const result = toAppend.length > 0 ? tags.concat(toAppend) : tags; + return result.join(tagSeparator); +} + +// eslint-disable-next-line require-jsdoc +function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separator) { + let result = ''; + const usedGlobalKeys = new Set(); + for (const c of Object.keys(child)) { + // there is a global tag with the same name as the child tag - use child + const formattedChildKey = sanitizeTags(c); + if (Object.hasOwn(globalTags, formattedChildKey)) { + usedGlobalKeys.add(formattedChildKey); + } + const serializedTagWithValue = `${formattedChildKey}:${sanitizeTags(child[c], telegraf)}`; + if (result === '') { + result += serializedTagWithValue; + } + else { + result += separator + serializedTagWithValue; + } + } + if (usedGlobalKeys.size === 0) { + result += separator + globalTagsFullMemo; + } + else { + for (const g of Object.keys(globalTags)) { + if (!usedGlobalKeys.has(g)) { + const serializedTagWithValue = `${g}:${sanitizeTags(globalTags[g], telegraf)}`; + result = serializedTagWithValue + separator + result; + } + } + } + return result; } /** @@ -113,6 +146,7 @@ function getDefaultRoute() { module.exports = { formatTags: formatTags, overrideTags: overrideTags, + overrideTags2: overrideTags2, formatDate: formatDate, getDefaultRoute: getDefaultRoute, sanitizeTags: sanitizeTags diff --git a/lib/statsd.js b/lib/statsd.js index c011aa4..d22ee53 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -65,7 +65,8 @@ const Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, this.prefix = options.prefix || ''; this.suffix = options.suffix || ''; this.tagPrefix = options.tagPrefix || '#'; - this.tagSeparator = options.tagSeparator || ','; + this.telegraf = options.telegraf || false; + this.tagSeparator = this.telegraf ? ',' : options.tagSeparator || ','; this.mock = options.mock; this.globalTags = typeof options.globalTags === 'object' ? helpers.formatTags(options.globalTags, options.telegraf) : []; @@ -75,7 +76,12 @@ const Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, filter((item) => !availableDDEnvs.some(env => item.startsWith(`${DD_ENV_GLOBAL_TAGS_MAPPING[env]}:`))). concat(availableDDEnvs.map(env => `${DD_ENV_GLOBAL_TAGS_MAPPING[env]}:${helpers.sanitizeTags(process.env[env])}`)); } - this.telegraf = options.telegraf || false; + if (typeof this.globalTags === 'object') { + this.globalTagsMemo = helpers.overrideTags(this.globalTags, [], this.telegraf, this.tagSeparator); + } + else { + this.globalTagsMemo = ''; + } this.maxBufferSize = options.maxBufferSize || 0; this.sampleRate = options.sampleRate || 1; this.bufferFlushInterval = options.bufferFlushInterval || 1000; @@ -242,22 +248,41 @@ Client.prototype.sendStat = function (stat, value, type, sampleRate, tags, callb * @param callback {Function=} Callback when message is done being delivered (only if maxBufferSize == 0). Optional. */ Client.prototype.send = function (message, tags, callback) { - let mergedTags = this.globalTags; - if (tags && typeof tags === 'object') { - mergedTags = helpers.overrideTags(mergedTags, tags, this.telegraf); - } - if (mergedTags.length > 0) { + const tagsString = getTagString(this.globalTags, this.globalTagsMemo, tags, this.telegraf, this.tagSeparator); + if (tagsString.length > 0) { if (this.telegraf) { message = message.split(':'); - message = `${message[0]},${mergedTags.join(',').replace(/:/g, '=')}:${message.slice(1).join(':')}`; + message = `${message[0]},${tagsString.replace(/:/g, '=')}:${message.slice(1).join(':')}`; } else { - message += `|${this.tagPrefix}${mergedTags.join(this.tagSeparator)}`; + message += `|${this.tagPrefix}${tagsString}`; } } this._send(message, callback); }; +// eslint-disable-next-line require-jsdoc +function getTagString(globalTags, globalTagsMemo, tags, telegraf, tagSeparator) { + if (!tags) { + return globalTagsMemo; + } + const isTagsArray = Array.isArray(tags); + if (isTagsArray) { + if (tags.length === 0) { + return globalTagsMemo; + } + } + else if (Object.keys(tags).length === 0) { + return globalTagsMemo; + } + if (isTagsArray || Array.isArray(globalTags)) { + return helpers.overrideTags(globalTags, tags, telegraf, tagSeparator); + } + else { + return helpers.overrideTags2(globalTags, globalTagsMemo, tags, telegraf, tagSeparator); + } +} + /** * Send a stat or event across the wire * @param message {String} The constructed message without tags From c8b4bacf6a6859d0097ef9dec286bce9fdff2005 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:26:40 -0400 Subject: [PATCH 02/19] Add new, faster overrideTags implementation --- test/globalTags.js | 58 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/test/globalTags.js b/test/globalTags.js index 66d214b..ef22096 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -1,5 +1,6 @@ const assert = require('assert'); const helpers = require('./helpers/helpers.js'); +const libHelpers = require('../lib/helpers.js'); const closeAll = helpers.closeAll; const testTypes = helpers.testTypes; @@ -79,6 +80,32 @@ describe('#globalTags', () => { }); }); + it('only global tags - array, no metric tags', done => { + server = createServer(serverType, opts => { + statsd = createHotShotsClient(Object.assign(opts, { + global_tags: ['gtag:1', 'gtag:2', 'bar'], + }), clientType); + statsd.increment('test', 1337, {}); + }); + server.on('metrics', metrics => { + assert.strictEqual(metrics, `test:1337|c|#gtag:1,gtag:2,bar${metricEnd}`); + done(); + }); + }); + + it('only global tags - object, no metric tags', done => { + server = createServer(serverType, opts => { + statsd = createHotShotsClient(Object.assign(opts, { + global_tags: { gtag: 1, gtagb: 2, } + }), clientType); + statsd.increment('test', 1337, {}); + }); + server.on('metrics', metrics => { + assert.strictEqual(metrics, `test:1337|c|#gtag:1,gtagb:2${metricEnd}`); + done(); + }); + }); + it('should override global tags with metric tags', done => { server = createServer(serverType, opts => { statsd = createHotShotsClient(Object.assign(opts, { @@ -205,3 +232,34 @@ describe('#globalTags', () => { }); }); }); + + +describe.skip('#globalTags performance benchmarks', () => { + // eslint-disable-next-line require-jsdoc + function time(f, iterations, opName) { + const startTime = process.hrtime.bigint(); + for (let i = 0; i < iterations; ++i) { + f(); + } + const endTime = process.hrtime.bigint(); + const elapsedMs = Number(endTime - startTime) / 1e6; + console.log(opName + ' performance benchmark: %d ms', elapsedMs); + + } + it('adhoc performance benchmark - overrideTags', () => { + const globalTags = { gtag: '123', foo: 'bar', dfjkserhu: 'fasdfheasdf', sdfygthsf: 'asdfuhtbhadsf', aslfkah4thutuehtrheu: 'asdfhasuihetlhstjlkfsjlk;f' }; + const tags = { gtag: '234', asdfwer: 'weradfsdsf', foo: 'bar', asfiehtjasdflksf: 'asdfkljfeuhtbasf', bbuhrewiuhfasknjasdflkjsdfjlksdfjlkafdsljkadsfjlkdfsjlkdfsjlfsjlkfdsjlkdsfjlkdsfjlkdfsljkadfshkaghk: 'asdfuhthb', asdfhjkasdfhjafsjlhfdsjlfd: 'ashdfhuaewrlhkjareshljkarshjklfdshklj', asflkjasdfhjhthiuatwekjhashfkjlf: 'asdfhhkuawrehljkatelhkjatslhkjfshlk' }; + const ITERATIONS = 10000; + + const fakeMemo = JSON.stringify(globalTags); + const formattedGlobalTags = libHelpers.formatTags(globalTags, false); + time(() => { + libHelpers.overrideTags(formattedGlobalTags, tags, false, ','); + }, ITERATIONS, 'overrideTags'); + + time(() => { + libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); + }, ITERATIONS, 'overrideTags2'); + + }); +}); From 3a539518404c66a80a7f9eab22771fe397ad5638 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:39:48 -0400 Subject: [PATCH 03/19] Add new, faster overrideTags implementation --- lib/helpers.js | 11 ++++++++--- lib/statsd.js | 8 ++++---- 2 files changed, 12 insertions(+), 7 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index ad81a0e..c3f2452 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -28,7 +28,7 @@ function formatTags(tags, telegraf) { * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new * array. parent and child are not mutated. */ -function overrideTags (parent, child, telegraf, tagSeparator) { +function overrideTags (parent, child, telegraf) { const seenKeys = {}; const toAppend = []; @@ -58,8 +58,12 @@ function overrideTags (parent, child, telegraf, tagSeparator) { } const tags = parentTags.concat(childTags); - const result = toAppend.length > 0 ? tags.concat(toAppend) : tags; - return result.join(tagSeparator); + return toAppend.length > 0 ? tags.concat(toAppend) : tags; +} + +function overrideTagsToString(parent, child, telegraf, separator) { + const tags = overrideTags(parent, child, telegraf); + return tags.join(separator); } // eslint-disable-next-line require-jsdoc @@ -146,6 +150,7 @@ function getDefaultRoute() { module.exports = { formatTags: formatTags, overrideTags: overrideTags, + overrideTagsToString: overrideTagsToString, overrideTags2: overrideTags2, formatDate: formatDate, getDefaultRoute: getDefaultRoute, diff --git a/lib/statsd.js b/lib/statsd.js index d22ee53..7daa20e 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -77,7 +77,7 @@ const Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, concat(availableDDEnvs.map(env => `${DD_ENV_GLOBAL_TAGS_MAPPING[env]}:${helpers.sanitizeTags(process.env[env])}`)); } if (typeof this.globalTags === 'object') { - this.globalTagsMemo = helpers.overrideTags(this.globalTags, [], this.telegraf, this.tagSeparator); + this.globalTagsMemo = helpers.overrideTagsToString(this.globalTags, [], this.telegraf, this.tagSeparator); } else { this.globalTagsMemo = ''; @@ -276,7 +276,7 @@ function getTagString(globalTags, globalTagsMemo, tags, telegraf, tagSeparator) return globalTagsMemo; } if (isTagsArray || Array.isArray(globalTags)) { - return helpers.overrideTags(globalTags, tags, telegraf, tagSeparator); + return helpers.overrideTagsToString(globalTags, tags, telegraf, tagSeparator); } else { return helpers.overrideTags2(globalTags, globalTagsMemo, tags, telegraf, tagSeparator); @@ -513,6 +513,7 @@ Client.prototype._close = function (callback) { const ChildClient = function (parent, options) { options = options || {}; + const yy = typeof options.globalTags === 'object' ? helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags; Client.call(this, { isChild : true, socket : parent.socket, // Child inherits socket from parent. Parent itself can be a child. @@ -529,8 +530,7 @@ const ChildClient = function (parent, options) { globalize : false, // Only 'root' client can be global mock : parent.mock, // Append child's tags to parent's tags - globalTags : typeof options.globalTags === 'object' ? - helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, + globalTags : yy, maxBufferSize : parent.maxBufferSize, bufferFlushInterval: parent.bufferFlushInterval, telegraf : parent.telegraf, From d7bb460c9827256dc2aaaafb7f95bceee64cdb6c Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:41:29 -0400 Subject: [PATCH 04/19] Add new, faster overrideTags implementation --- lib/helpers.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/helpers.js b/lib/helpers.js index c3f2452..5efd5ba 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -61,6 +61,7 @@ function overrideTags (parent, child, telegraf) { return toAppend.length > 0 ? tags.concat(toAppend) : tags; } +// eslint-disable-next-line require-jsdoc function overrideTagsToString(parent, child, telegraf, separator) { const tags = overrideTags(parent, child, telegraf); return tags.join(separator); From a93228221da19dcb79a97905fdc859f27d64bc63 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:51:25 -0400 Subject: [PATCH 05/19] Add new, faster overrideTags implementation --- lib/helpers.js | 16 +++++++++++----- lib/statsFunctions.js | 2 +- lib/statsd.js | 3 ++- test/globalTags.js | 6 +++--- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index 5efd5ba..16de251 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -28,7 +28,7 @@ function formatTags(tags, telegraf) { * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new * array. parent and child are not mutated. */ -function overrideTags (parent, child, telegraf) { +function overrideTagsUnoptimized (parent, child, telegraf) { const seenKeys = {}; const toAppend = []; @@ -61,13 +61,19 @@ function overrideTags (parent, child, telegraf) { return toAppend.length > 0 ? tags.concat(toAppend) : tags; } -// eslint-disable-next-line require-jsdoc +/** + * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as a string. + */ function overrideTagsToString(parent, child, telegraf, separator) { - const tags = overrideTags(parent, child, telegraf); + const tags = overrideTagsUnoptimized(parent, child, telegraf); return tags.join(separator); } -// eslint-disable-next-line require-jsdoc +/** + * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as a string. + * + * More performant than overrideTagsUnoptimized. But it requires that globalTags and child are both objects, not arrays. + */ function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separator) { let result = ''; const usedGlobalKeys = new Set(); @@ -150,7 +156,7 @@ function getDefaultRoute() { module.exports = { formatTags: formatTags, - overrideTags: overrideTags, + overrideTagsUnoptimized: overrideTagsUnoptimized, overrideTagsToString: overrideTagsToString, overrideTags2: overrideTags2, formatDate: formatDate, diff --git a/lib/statsFunctions.js b/lib/statsFunctions.js index 3735346..aaf7893 100644 --- a/lib/statsFunctions.js +++ b/lib/statsFunctions.js @@ -250,7 +250,7 @@ function applyStatsFns (Client) { let mergedTags = this.globalTags; if (tags && typeof(tags) === 'object') { - mergedTags = helpers.overrideTags(mergedTags, tags, this.telegraf); + mergedTags = helpers.overrideTagsUnoptimized(mergedTags, tags, this.telegraf); } if (mergedTags.length > 0) { check.push(`#${mergedTags.join(',')}`); diff --git a/lib/statsd.js b/lib/statsd.js index 7daa20e..5bf2c30 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -530,7 +530,8 @@ const ChildClient = function (parent, options) { globalize : false, // Only 'root' client can be global mock : parent.mock, // Append child's tags to parent's tags - globalTags : yy, + globalTags : typeof options.globalTags === 'object' ? + helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, maxBufferSize : parent.maxBufferSize, bufferFlushInterval: parent.bufferFlushInterval, telegraf : parent.telegraf, diff --git a/test/globalTags.js b/test/globalTags.js index ef22096..7d6f4de 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -246,7 +246,7 @@ describe.skip('#globalTags performance benchmarks', () => { console.log(opName + ' performance benchmark: %d ms', elapsedMs); } - it('adhoc performance benchmark - overrideTags', () => { + it('adhoc performance benchmark - overrideTagsUnoptimized', () => { const globalTags = { gtag: '123', foo: 'bar', dfjkserhu: 'fasdfheasdf', sdfygthsf: 'asdfuhtbhadsf', aslfkah4thutuehtrheu: 'asdfhasuihetlhstjlkfsjlk;f' }; const tags = { gtag: '234', asdfwer: 'weradfsdsf', foo: 'bar', asfiehtjasdflksf: 'asdfkljfeuhtbasf', bbuhrewiuhfasknjasdflkjsdfjlksdfjlkafdsljkadsfjlkdfsjlkdfsjlfsjlkfdsjlkdsfjlkdsfjlkdfsljkadfshkaghk: 'asdfuhthb', asdfhjkasdfhjafsjlhfdsjlfd: 'ashdfhuaewrlhkjareshljkarshjklfdshklj', asflkjasdfhjhthiuatwekjhashfkjlf: 'asdfhhkuawrehljkatelhkjatslhkjfshlk' }; const ITERATIONS = 10000; @@ -254,8 +254,8 @@ describe.skip('#globalTags performance benchmarks', () => { const fakeMemo = JSON.stringify(globalTags); const formattedGlobalTags = libHelpers.formatTags(globalTags, false); time(() => { - libHelpers.overrideTags(formattedGlobalTags, tags, false, ','); - }, ITERATIONS, 'overrideTags'); + libHelpers.overrideTagsUnoptimized(formattedGlobalTags, tags, false, ','); + }, ITERATIONS, 'overrideTagsUnoptimized'); time(() => { libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); From f7b9ae325f374e19e58f98d065a479852725cddc Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:52:07 -0400 Subject: [PATCH 06/19] Add new, faster overrideTags implementation --- lib/helpers.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/lib/helpers.js b/lib/helpers.js index 16de251..5cf0efb 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -27,6 +27,8 @@ function formatTags(tags, telegraf) { /** * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as new * array. parent and child are not mutated. + * + * OverrideTags2 is faster, but it requires that the parent/child are both objects, not arrays. */ function overrideTagsUnoptimized (parent, child, telegraf) { const seenKeys = {}; From 5ff5ef4356d0a44fc78ef57e33b7431725c9e482 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:53:22 -0400 Subject: [PATCH 07/19] Add new, faster overrideTags implementation --- lib/statsd.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/statsd.js b/lib/statsd.js index 5bf2c30..80108e5 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -513,7 +513,6 @@ Client.prototype._close = function (callback) { const ChildClient = function (parent, options) { options = options || {}; - const yy = typeof options.globalTags === 'object' ? helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags; Client.call(this, { isChild : true, socket : parent.socket, // Child inherits socket from parent. Parent itself can be a child. From 3e31ae612708cb2b8ecd025037e7cc2eece62189 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 16:59:37 -0400 Subject: [PATCH 08/19] Add new, faster overrideTags implementation --- test/globalTags.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/globalTags.js b/test/globalTags.js index 7d6f4de..9e2d69f 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -234,7 +234,7 @@ describe('#globalTags', () => { }); -describe.skip('#globalTags performance benchmarks', () => { +describe('#globalTags performance benchmarks', () => { // eslint-disable-next-line require-jsdoc function time(f, iterations, opName) { const startTime = process.hrtime.bigint(); @@ -249,12 +249,12 @@ describe.skip('#globalTags performance benchmarks', () => { it('adhoc performance benchmark - overrideTagsUnoptimized', () => { const globalTags = { gtag: '123', foo: 'bar', dfjkserhu: 'fasdfheasdf', sdfygthsf: 'asdfuhtbhadsf', aslfkah4thutuehtrheu: 'asdfhasuihetlhstjlkfsjlk;f' }; const tags = { gtag: '234', asdfwer: 'weradfsdsf', foo: 'bar', asfiehtjasdflksf: 'asdfkljfeuhtbasf', bbuhrewiuhfasknjasdflkjsdfjlksdfjlkafdsljkadsfjlkdfsjlkdfsjlfsjlkfdsjlkdsfjlkdsfjlkdfsljkadfshkaghk: 'asdfuhthb', asdfhjkasdfhjafsjlhfdsjlfd: 'ashdfhuaewrlhkjareshljkarshjklfdshklj', asflkjasdfhjhthiuatwekjhashfkjlf: 'asdfhhkuawrehljkatelhkjatslhkjfshlk' }; - const ITERATIONS = 10000; + const ITERATIONS = 100000; const fakeMemo = JSON.stringify(globalTags); const formattedGlobalTags = libHelpers.formatTags(globalTags, false); time(() => { - libHelpers.overrideTagsUnoptimized(formattedGlobalTags, tags, false, ','); + libHelpers.overrideTagsToString(formattedGlobalTags, tags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized'); time(() => { From 60fa24d3f2b97e057ed3a6f340aadb0089747c2a Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 17:13:29 -0400 Subject: [PATCH 09/19] Add new, faster overrideTags implementation --- test/globalTags.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/test/globalTags.js b/test/globalTags.js index 9e2d69f..f254490 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -249,17 +249,24 @@ describe('#globalTags performance benchmarks', () => { it('adhoc performance benchmark - overrideTagsUnoptimized', () => { const globalTags = { gtag: '123', foo: 'bar', dfjkserhu: 'fasdfheasdf', sdfygthsf: 'asdfuhtbhadsf', aslfkah4thutuehtrheu: 'asdfhasuihetlhstjlkfsjlk;f' }; const tags = { gtag: '234', asdfwer: 'weradfsdsf', foo: 'bar', asfiehtjasdflksf: 'asdfkljfeuhtbasf', bbuhrewiuhfasknjasdflkjsdfjlksdfjlkafdsljkadsfjlkdfsjlkdfsjlfsjlkfdsjlkdsfjlkdsfjlkdfsljkadfshkaghk: 'asdfuhthb', asdfhjkasdfhjafsjlhfdsjlfd: 'ashdfhuaewrlhkjareshljkarshjklfdshklj', asflkjasdfhjhthiuatwekjhashfkjlf: 'asdfhhkuawrehljkatelhkjatslhkjfshlk' }; - const ITERATIONS = 100000; + const ITERATIONS = 10000; const fakeMemo = JSON.stringify(globalTags); const formattedGlobalTags = libHelpers.formatTags(globalTags, false); + time(() => { libHelpers.overrideTagsToString(formattedGlobalTags, tags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized'); - + time(() => { + const arrayTags = libHelpers.formatTags(tags, false); + libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); + }, ITERATIONS, 'overrideTagsUnoptimized for non-pre-made arrays'); + const arrayTags = libHelpers.formatTags(tags, false); + time(() => { + libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); + }, ITERATIONS, 'overrideTagsUnoptimized for pre-made arrays'); time(() => { libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); }, ITERATIONS, 'overrideTags2'); - }); }); From cf03ceb288b985202a336f652e5c70de7cc7113f Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 17:14:00 -0400 Subject: [PATCH 10/19] Add new, faster overrideTags implementation --- test/globalTags.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/test/globalTags.js b/test/globalTags.js index f254490..5d5d9d3 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -261,10 +261,6 @@ describe('#globalTags performance benchmarks', () => { const arrayTags = libHelpers.formatTags(tags, false); libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized for non-pre-made arrays'); - const arrayTags = libHelpers.formatTags(tags, false); - time(() => { - libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); - }, ITERATIONS, 'overrideTagsUnoptimized for pre-made arrays'); time(() => { libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); }, ITERATIONS, 'overrideTags2'); From 265583063c3b0cf5054faeebbf5001482cc68e02 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 17:26:11 -0400 Subject: [PATCH 11/19] Add new, faster overrideTags implementation --- test/globalTags.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/test/globalTags.js b/test/globalTags.js index 5d5d9d3..6aa4d60 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -258,6 +258,8 @@ describe('#globalTags performance benchmarks', () => { libHelpers.overrideTagsToString(formattedGlobalTags, tags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized'); time(() => { + // it's a fair comparison to include the formatTags call in the benchmark, because I expect + // most actual use-cases of the API will start with an object and convert it into an array. const arrayTags = libHelpers.formatTags(tags, false); libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized for non-pre-made arrays'); From 8db8a8dc6329f56469e37d200eb48be13a0b9f00 Mon Sep 17 00:00:00 2001 From: wes Date: Fri, 2 Aug 2024 17:26:51 -0400 Subject: [PATCH 12/19] Add new, faster overrideTags implementation --- lib/statsd.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/statsd.js b/lib/statsd.js index 80108e5..985721d 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -530,7 +530,7 @@ const ChildClient = function (parent, options) { mock : parent.mock, // Append child's tags to parent's tags globalTags : typeof options.globalTags === 'object' ? - helpers.overrideTags(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, + helpers.overrideTagsUnoptimized(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, maxBufferSize : parent.maxBufferSize, bufferFlushInterval: parent.bufferFlushInterval, telegraf : parent.telegraf, From 57c9d4522b5cda477df8479ed28b2a0ae429ca86 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 09:36:59 -0400 Subject: [PATCH 13/19] Add new, faster overrideTags implementation --- test/globalTags.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/globalTags.js b/test/globalTags.js index 6aa4d60..a5522c6 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -234,7 +234,7 @@ describe('#globalTags', () => { }); -describe('#globalTags performance benchmarks', () => { +describe.skip('#globalTags performance benchmarks', () => { // eslint-disable-next-line require-jsdoc function time(f, iterations, opName) { const startTime = process.hrtime.bigint(); From 9d979b1912f075660c413217713cbb1ff8616100 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 14:09:44 -0400 Subject: [PATCH 14/19] Add new, faster overrideTags implementation --- lib/helpers.js | 26 +++++++++++++++-------- lib/statsd.js | 53 +++++++++++++++++++++++----------------------- test/globalTags.js | 4 ++-- 3 files changed, 46 insertions(+), 37 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index 5cf0efb..b8d9503 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -66,7 +66,7 @@ function overrideTagsUnoptimized (parent, child, telegraf) { /** * Overrides tags in parent with tags from child with the same name (case sensitive) and return the result as a string. */ -function overrideTagsToString(parent, child, telegraf, separator) { +function overrideTagsToStringUnoptimized(parent, child, telegraf, separator) { const tags = overrideTagsUnoptimized(parent, child, telegraf); return tags.join(separator); } @@ -79,6 +79,19 @@ function overrideTagsToString(parent, child, telegraf, separator) { function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separator) { let result = ''; const usedGlobalKeys = new Set(); + // eslint-disable-next-line require-jsdoc + function addToResult(tag, addToFront) { + if (result === '') { + result += tag; + } + // this is just here to match the behavior of overrideTagsUnoptimized + else if (addToFront) { + result = tag + separator + result; + } + else { + result += separator + tag; + } + } for (const c of Object.keys(child)) { // there is a global tag with the same name as the child tag - use child const formattedChildKey = sanitizeTags(c); @@ -86,15 +99,10 @@ function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separat usedGlobalKeys.add(formattedChildKey); } const serializedTagWithValue = `${formattedChildKey}:${sanitizeTags(child[c], telegraf)}`; - if (result === '') { - result += serializedTagWithValue; - } - else { - result += separator + serializedTagWithValue; - } + addToResult(serializedTagWithValue); } if (usedGlobalKeys.size === 0) { - result += separator + globalTagsFullMemo; + addToResult(globalTagsFullMemo, true); } else { for (const g of Object.keys(globalTags)) { @@ -159,7 +167,7 @@ function getDefaultRoute() { module.exports = { formatTags: formatTags, overrideTagsUnoptimized: overrideTagsUnoptimized, - overrideTagsToString: overrideTagsToString, + overrideTagsToStringUnoptimized: overrideTagsToStringUnoptimized, overrideTags2: overrideTags2, formatDate: formatDate, getDefaultRoute: getDefaultRoute, diff --git a/lib/statsd.js b/lib/statsd.js index 985721d..186209d 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -68,20 +68,32 @@ const Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, this.telegraf = options.telegraf || false; this.tagSeparator = this.telegraf ? ',' : options.tagSeparator || ','; this.mock = options.mock; - this.globalTags = typeof options.globalTags === 'object' ? + /** + * this is always an array. + */ + this.globalTagsArray = typeof options.globalTags === 'object' ? helpers.formatTags(options.globalTags, options.telegraf) : []; const availableDDEnvs = Object.keys(DD_ENV_GLOBAL_TAGS_MAPPING).filter(key => process.env[key]); if (availableDDEnvs.length > 0) { - this.globalTags = this.globalTags. + this.globalTagsArray = this.globalTagsArray. filter((item) => !availableDDEnvs.some(env => item.startsWith(`${DD_ENV_GLOBAL_TAGS_MAPPING[env]}:`))). concat(availableDDEnvs.map(env => `${DD_ENV_GLOBAL_TAGS_MAPPING[env]}:${helpers.sanitizeTags(process.env[env])}`)); } - if (typeof this.globalTags === 'object') { - this.globalTagsMemo = helpers.overrideTagsToString(this.globalTags, [], this.telegraf, this.tagSeparator); - } - else { - this.globalTagsMemo = ''; + /** + * This is an object or `null`. It's populated if the original input is an object. + * We can't necessarily convert an array to an object, since array supports keys without values + */ + this.globalTagsObjectSanitized = null; + if (typeof options.globalTags === 'object' && !Array.isArray(options.globalTags)) { + this.globalTagsObjectSanitized = {}; + for (const key of Object.keys(options.globalTags)) { + const value = options.globalTags[key]; + const sanitizedKey = helpers.sanitizeTags(key); + const sanitizedVal = helpers.sanitizeTags(value); + this.globalTagsObjectSanitized[sanitizedKey] = sanitizedVal; + } } + this.globalTagsMemo = helpers.overrideTagsToStringUnoptimized(this.globalTagsArray, [], this.telegraf, this.tagSeparator); this.maxBufferSize = options.maxBufferSize || 0; this.sampleRate = options.sampleRate || 1; this.bufferFlushInterval = options.bufferFlushInterval || 1000; @@ -248,7 +260,7 @@ Client.prototype.sendStat = function (stat, value, type, sampleRate, tags, callb * @param callback {Function=} Callback when message is done being delivered (only if maxBufferSize == 0). Optional. */ Client.prototype.send = function (message, tags, callback) { - const tagsString = getTagString(this.globalTags, this.globalTagsMemo, tags, this.telegraf, this.tagSeparator); + const tagsString = getTagString(this.globalTagsArray, this.globalTagsObjectSanitized, this.globalTagsMemo, tags, this.telegraf, this.tagSeparator); if (tagsString.length > 0) { if (this.telegraf) { message = message.split(':'); @@ -262,25 +274,14 @@ Client.prototype.send = function (message, tags, callback) { }; // eslint-disable-next-line require-jsdoc -function getTagString(globalTags, globalTagsMemo, tags, telegraf, tagSeparator) { - if (!tags) { +function getTagString(globalTagsArray, globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator) { + if (!(tags && typeof tags === 'object')) { return globalTagsMemo; } - const isTagsArray = Array.isArray(tags); - if (isTagsArray) { - if (tags.length === 0) { - return globalTagsMemo; - } - } - else if (Object.keys(tags).length === 0) { - return globalTagsMemo; - } - if (isTagsArray || Array.isArray(globalTags)) { - return helpers.overrideTagsToString(globalTags, tags, telegraf, tagSeparator); - } - else { - return helpers.overrideTags2(globalTags, globalTagsMemo, tags, telegraf, tagSeparator); + if (globalTagsObject !== null && tags && !Array.isArray(tags)) { + return helpers.overrideTags2(globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator); } + return helpers.overrideTagsToStringUnoptimized(globalTagsArray, tags, telegraf, tagSeparator); } /** @@ -530,7 +531,7 @@ const ChildClient = function (parent, options) { mock : parent.mock, // Append child's tags to parent's tags globalTags : typeof options.globalTags === 'object' ? - helpers.overrideTagsUnoptimized(parent.globalTags, options.globalTags, parent.telegraf) : parent.globalTags, + helpers.overrideTagsUnoptimized(parent.globalTagsArray, options.globalTags, parent.telegraf) : parent.globalTagsArray, maxBufferSize : parent.maxBufferSize, bufferFlushInterval: parent.bufferFlushInterval, telegraf : parent.telegraf, @@ -545,7 +546,7 @@ util.inherits(ChildClient, Client); * @param options * @option prefix {String} An optional prefix to assign to each stat name sent * @option suffix {String} An optional suffix to assign to each stat name sent - * @option globalTags {Array=} Optional tags that will be added to every metric + * @option globalTagsArray {Array=} Optional tags that will be added to every metric */ Client.prototype.childClient = function (options) { return new ChildClient(this, options); diff --git a/test/globalTags.js b/test/globalTags.js index a5522c6..b02bdd9 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -255,13 +255,13 @@ describe.skip('#globalTags performance benchmarks', () => { const formattedGlobalTags = libHelpers.formatTags(globalTags, false); time(() => { - libHelpers.overrideTagsToString(formattedGlobalTags, tags, false, ','); + libHelpers.overrideTagsToStringUnoptimized(formattedGlobalTags, tags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized'); time(() => { // it's a fair comparison to include the formatTags call in the benchmark, because I expect // most actual use-cases of the API will start with an object and convert it into an array. const arrayTags = libHelpers.formatTags(tags, false); - libHelpers.overrideTagsToString(formattedGlobalTags, arrayTags, false, ','); + libHelpers.overrideTagsToStringUnoptimized(formattedGlobalTags, arrayTags, false, ','); }, ITERATIONS, 'overrideTagsUnoptimized for non-pre-made arrays'); time(() => { libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); From d4855bf90cc73de66f6e342cbb3f2243ab62596b Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 14:31:21 -0400 Subject: [PATCH 15/19] Add new, faster overrideTags implementation --- .github/workflows/node.js.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/node.js.yml b/.github/workflows/node.js.yml index dbd28f7..4c0633c 100644 --- a/.github/workflows/node.js.yml +++ b/.github/workflows/node.js.yml @@ -15,7 +15,7 @@ jobs: strategy: matrix: os: [ubuntu-latest, windows-latest] - node-version: [10.x, 12.x, 14.x, 16.x, 18.x] + node-version: [18.x] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ runs-on: ${{ matrix.os }} steps: From 45250aa0eb75a7dcb0168fa0645c19899800251b Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 15:17:52 -0400 Subject: [PATCH 16/19] Add new, faster overrideTags implementation --- lib/helpers.js | 1 + lib/statsd.js | 34 +++++++++++++++++----------------- 2 files changed, 18 insertions(+), 17 deletions(-) diff --git a/lib/helpers.js b/lib/helpers.js index b8d9503..98b6461 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -77,6 +77,7 @@ function overrideTagsToStringUnoptimized(parent, child, telegraf, separator) { * More performant than overrideTagsUnoptimized. But it requires that globalTags and child are both objects, not arrays. */ function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separator) { + throw new Error('ah'); let result = ''; const usedGlobalKeys = new Set(); // eslint-disable-next-line require-jsdoc diff --git a/lib/statsd.js b/lib/statsd.js index 186209d..1a71588 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -84,16 +84,16 @@ const Client = function (host, port, prefix, suffix, globalize, cacheDns, mock, * We can't necessarily convert an array to an object, since array supports keys without values */ this.globalTagsObjectSanitized = null; - if (typeof options.globalTags === 'object' && !Array.isArray(options.globalTags)) { - this.globalTagsObjectSanitized = {}; - for (const key of Object.keys(options.globalTags)) { - const value = options.globalTags[key]; - const sanitizedKey = helpers.sanitizeTags(key); - const sanitizedVal = helpers.sanitizeTags(value); - this.globalTagsObjectSanitized[sanitizedKey] = sanitizedVal; - } - } - this.globalTagsMemo = helpers.overrideTagsToStringUnoptimized(this.globalTagsArray, [], this.telegraf, this.tagSeparator); + // if (typeof options.globalTags === 'object' && !Array.isArray(options.globalTags)) { + // this.globalTagsObjectSanitized = {}; + // for (const key of Object.keys(options.globalTags)) { + // const value = options.globalTags[key]; + // const sanitizedKey = helpers.sanitizeTags(key); + // const sanitizedVal = helpers.sanitizeTags(value); + // this.globalTagsObjectSanitized[sanitizedKey] = sanitizedVal; + // } + // } + // this.globalTagsMemo = helpers.overrideTagsToStringUnoptimized(this.globalTagsArray, [], this.telegraf, this.tagSeparator); this.maxBufferSize = options.maxBufferSize || 0; this.sampleRate = options.sampleRate || 1; this.bufferFlushInterval = options.bufferFlushInterval || 1000; @@ -275,13 +275,13 @@ Client.prototype.send = function (message, tags, callback) { // eslint-disable-next-line require-jsdoc function getTagString(globalTagsArray, globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator) { - if (!(tags && typeof tags === 'object')) { - return globalTagsMemo; - } - if (globalTagsObject !== null && tags && !Array.isArray(tags)) { - return helpers.overrideTags2(globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator); - } - return helpers.overrideTagsToStringUnoptimized(globalTagsArray, tags, telegraf, tagSeparator); + // if (!(tags && typeof tags === 'object')) { + // return globalTagsMemo; + // } + // if (globalTagsObject !== null && tags && !Array.isArray(tags)) { + // return helpers.overrideTags2(globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator); + // } + return helpers.overrideTagsToStringUnoptimized(globalTagsArray, tags ? tags : [], telegraf, tagSeparator); } /** From 779044c655c697f5421ef1e3abbe2a7ddd379d59 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 15:19:31 -0400 Subject: [PATCH 17/19] Add new, faster overrideTags implementation --- lib/helpers.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/helpers.js b/lib/helpers.js index 98b6461..d9add43 100644 --- a/lib/helpers.js +++ b/lib/helpers.js @@ -77,7 +77,9 @@ function overrideTagsToStringUnoptimized(parent, child, telegraf, separator) { * More performant than overrideTagsUnoptimized. But it requires that globalTags and child are both objects, not arrays. */ function overrideTags2 (globalTags, globalTagsFullMemo, child, telegraf, separator) { - throw new Error('ah'); + if (globalTags || child) { + throw new Error('wat'); + } let result = ''; const usedGlobalKeys = new Set(); // eslint-disable-next-line require-jsdoc From 78e7616fccfd4b404ce3b283b507e8db06a120ac Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 15:27:51 -0400 Subject: [PATCH 18/19] Add new, faster overrideTags implementation --- lib/statsd.js | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/lib/statsd.js b/lib/statsd.js index 1a71588..d289d08 100644 --- a/lib/statsd.js +++ b/lib/statsd.js @@ -260,13 +260,25 @@ Client.prototype.sendStat = function (stat, value, type, sampleRate, tags, callb * @param callback {Function=} Callback when message is done being delivered (only if maxBufferSize == 0). Optional. */ Client.prototype.send = function (message, tags, callback) { - const tagsString = getTagString(this.globalTagsArray, this.globalTagsObjectSanitized, this.globalTagsMemo, tags, this.telegraf, this.tagSeparator); - if (tagsString.length > 0) { + // const tagsString = getTagString(this.globalTagsArray, this.globalTagsObjectSanitized, this.globalTagsMemo, tags, this.telegraf, this.tagSeparator); + // if (tagsString.length > 0) { + // if (this.telegraf) { + // message = message.split(':'); + // message = `${message[0]},${tagsString.replace(/:/g, '=')}:${message.slice(1).join(':')}`; + // } else { + // message += `|${this.tagPrefix}${tagsString}`; + // } + // } + let mergedTags = this.globalTagsArray; + if (tags && typeof tags === 'object') { + mergedTags = helpers.overrideTagsUnoptimized(mergedTags, tags, this.telegraf); + } + if (mergedTags.length > 0) { if (this.telegraf) { message = message.split(':'); - message = `${message[0]},${tagsString.replace(/:/g, '=')}:${message.slice(1).join(':')}`; + message = `${message[0]},${mergedTags.join(',').replace(/:/g, '=')}:${message.slice(1).join(':')}`; } else { - message += `|${this.tagPrefix}${tagsString}`; + message += `|${this.tagPrefix}${mergedTags.join(this.tagSeparator)}`; } } @@ -274,15 +286,15 @@ Client.prototype.send = function (message, tags, callback) { }; // eslint-disable-next-line require-jsdoc -function getTagString(globalTagsArray, globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator) { +// function getTagString(globalTagsArray, globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator) { // if (!(tags && typeof tags === 'object')) { // return globalTagsMemo; // } // if (globalTagsObject !== null && tags && !Array.isArray(tags)) { // return helpers.overrideTags2(globalTagsObject, globalTagsMemo, tags, telegraf, tagSeparator); // } - return helpers.overrideTagsToStringUnoptimized(globalTagsArray, tags ? tags : [], telegraf, tagSeparator); -} + // return helpers.overrideTagsToStringUnoptimized(globalTagsArray, tags ? tags : [], telegraf, tagSeparator); +// } /** * Send a stat or event across the wire From f22a836d9a7239123ac07a3b637b710466048504 Mon Sep 17 00:00:00 2001 From: wes Date: Mon, 5 Aug 2024 15:31:26 -0400 Subject: [PATCH 19/19] Add new, faster overrideTags implementation --- test/globalTags.js | 62 ---------------------------------------------- 1 file changed, 62 deletions(-) diff --git a/test/globalTags.js b/test/globalTags.js index b02bdd9..3930d84 100644 --- a/test/globalTags.js +++ b/test/globalTags.js @@ -80,32 +80,6 @@ describe('#globalTags', () => { }); }); - it('only global tags - array, no metric tags', done => { - server = createServer(serverType, opts => { - statsd = createHotShotsClient(Object.assign(opts, { - global_tags: ['gtag:1', 'gtag:2', 'bar'], - }), clientType); - statsd.increment('test', 1337, {}); - }); - server.on('metrics', metrics => { - assert.strictEqual(metrics, `test:1337|c|#gtag:1,gtag:2,bar${metricEnd}`); - done(); - }); - }); - - it('only global tags - object, no metric tags', done => { - server = createServer(serverType, opts => { - statsd = createHotShotsClient(Object.assign(opts, { - global_tags: { gtag: 1, gtagb: 2, } - }), clientType); - statsd.increment('test', 1337, {}); - }); - server.on('metrics', metrics => { - assert.strictEqual(metrics, `test:1337|c|#gtag:1,gtagb:2${metricEnd}`); - done(); - }); - }); - it('should override global tags with metric tags', done => { server = createServer(serverType, opts => { statsd = createHotShotsClient(Object.assign(opts, { @@ -232,39 +206,3 @@ describe('#globalTags', () => { }); }); }); - - -describe.skip('#globalTags performance benchmarks', () => { - // eslint-disable-next-line require-jsdoc - function time(f, iterations, opName) { - const startTime = process.hrtime.bigint(); - for (let i = 0; i < iterations; ++i) { - f(); - } - const endTime = process.hrtime.bigint(); - const elapsedMs = Number(endTime - startTime) / 1e6; - console.log(opName + ' performance benchmark: %d ms', elapsedMs); - - } - it('adhoc performance benchmark - overrideTagsUnoptimized', () => { - const globalTags = { gtag: '123', foo: 'bar', dfjkserhu: 'fasdfheasdf', sdfygthsf: 'asdfuhtbhadsf', aslfkah4thutuehtrheu: 'asdfhasuihetlhstjlkfsjlk;f' }; - const tags = { gtag: '234', asdfwer: 'weradfsdsf', foo: 'bar', asfiehtjasdflksf: 'asdfkljfeuhtbasf', bbuhrewiuhfasknjasdflkjsdfjlksdfjlkafdsljkadsfjlkdfsjlkdfsjlfsjlkfdsjlkdsfjlkdsfjlkdfsljkadfshkaghk: 'asdfuhthb', asdfhjkasdfhjafsjlhfdsjlfd: 'ashdfhuaewrlhkjareshljkarshjklfdshklj', asflkjasdfhjhthiuatwekjhashfkjlf: 'asdfhhkuawrehljkatelhkjatslhkjfshlk' }; - const ITERATIONS = 10000; - - const fakeMemo = JSON.stringify(globalTags); - const formattedGlobalTags = libHelpers.formatTags(globalTags, false); - - time(() => { - libHelpers.overrideTagsToStringUnoptimized(formattedGlobalTags, tags, false, ','); - }, ITERATIONS, 'overrideTagsUnoptimized'); - time(() => { - // it's a fair comparison to include the formatTags call in the benchmark, because I expect - // most actual use-cases of the API will start with an object and convert it into an array. - const arrayTags = libHelpers.formatTags(tags, false); - libHelpers.overrideTagsToStringUnoptimized(formattedGlobalTags, arrayTags, false, ','); - }, ITERATIONS, 'overrideTagsUnoptimized for non-pre-made arrays'); - time(() => { - libHelpers.overrideTags2(globalTags, fakeMemo, tags, false, ','); - }, ITERATIONS, 'overrideTags2'); - }); -});