From 1926cc0c2d71999ee050459f4456617bd3fd7bcc Mon Sep 17 00:00:00 2001 From: lassic Date: Mon, 11 Sep 2023 22:45:19 +0300 Subject: [PATCH 1/4] perf: improve getMetricAsString further for long strings + less allocations --- lib/registry.js | 36 +++++++++++++++++++++++++++++++++--- 1 file changed, 33 insertions(+), 3 deletions(-) diff --git a/lib/registry.js b/lib/registry.js index 9ba0194f..6de3d5c5 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -2,6 +2,10 @@ const { getValueAsString } = require('./util'); +function REPLACE_FUNC(dict) { + return char => dict[char] || ''; +} + class Registry { static get PROMETHEUS_CONTENT_TYPE() { return 'text/plain; version=0.0.4; charset=utf-8'; @@ -11,6 +15,27 @@ class Registry { return 'application/openmetrics-text; version=1.0.0; charset=utf-8'; } + static get ESCAPE_STRING_REPLACE_MAP() { + return { + '\\': '\\\\', + '\n': '\\n', + }; + } + + static get ESCAPE_LABEL_VALUE_REPLACE_MAP() { + return Object.assign({}, Registry.ESCAPE_STRING_REPLACE_MAP, { + '"': '\\\\"', + }); + } + + static get ESCAPE_REPLACE_REGEXP() { + // return new RegExp( + // Object.keys(Registry.ESCAPE_LABEL_VALUE_REPLACE_MAP).join('|'), + // 'g', + // ); + return /\\|\n|"/g; + } + constructor(regContentType = Registry.PROMETHEUS_CONTENT_TYPE) { this._metrics = {}; this._collectors = []; @@ -234,10 +259,15 @@ function escapeLabelValue(str) { if (typeof str !== 'string') { return str; } - return escapeString(str).replace(/"/g, '\\"'); + + return escapeString(str, Registry.ESCAPE_LABEL_VALUE_REPLACE_MAP); } -function escapeString(str) { - return str.replace(/\\/g, '\\\\').replace(/\n/g, '\\n'); +function escapeString(str, extraReplaceDict) { + const fullDict = extraReplaceDict + ? extraReplaceDict + : Registry.ESCAPE_STRING_REPLACE_MAP; + + return str.replace(Registry.ESCAPE_REPLACE_REGEXP, REPLACE_FUNC(fullDict)); } function standardizeCounterName(name) { return name.replace(/_total$/, ''); From f0b9cf4b477f147fc56d2322f748e9e464c0e41a Mon Sep 17 00:00:00 2001 From: lassic Date: Mon, 11 Sep 2023 23:14:43 +0300 Subject: [PATCH 2/4] remove commented attempt to generalize regex for now --- lib/registry.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/lib/registry.js b/lib/registry.js index 6de3d5c5..f9ffe6de 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -1,3 +1,4 @@ +/* eslint-disable prettier/prettier */ 'use strict'; const { getValueAsString } = require('./util'); @@ -29,10 +30,6 @@ class Registry { } static get ESCAPE_REPLACE_REGEXP() { - // return new RegExp( - // Object.keys(Registry.ESCAPE_LABEL_VALUE_REPLACE_MAP).join('|'), - // 'g', - // ); return /\\|\n|"/g; } From 0ad0b0afd97ec7014f4944cc99135683d1f93a11 Mon Sep 17 00:00:00 2001 From: lassic Date: Mon, 11 Sep 2023 23:17:08 +0300 Subject: [PATCH 3/4] cleanup prettier comment --- lib/registry.js | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/registry.js b/lib/registry.js index f9ffe6de..b84e7823 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -1,4 +1,3 @@ -/* eslint-disable prettier/prettier */ 'use strict'; const { getValueAsString } = require('./util'); From fe4a561570eea720213432b1c197d25d51a02ddb Mon Sep 17 00:00:00 2001 From: lassic Date: Tue, 12 Sep 2023 10:23:16 +0300 Subject: [PATCH 4/4] address PR comments #1 --- lib/registry.js | 35 +++++++++++++++-------------------- 1 file changed, 15 insertions(+), 20 deletions(-) diff --git a/lib/registry.js b/lib/registry.js index b84e7823..a07c68f2 100644 --- a/lib/registry.js +++ b/lib/registry.js @@ -2,6 +2,18 @@ const { getValueAsString } = require('./util'); +const ESCAPE_STRING_REPLACE_MAP = { + '\\': '\\\\', + '\n': '\\n', +}; + +const ESCAPE_LABEL_VALUE_REPLACE_MAP = { + ...ESCAPE_STRING_REPLACE_MAP, + '"': '\\\\"', +}; + +const ESCAPE_REPLACE_REGEXP = /\\|\n|"/g; + function REPLACE_FUNC(dict) { return char => dict[char] || ''; } @@ -15,23 +27,6 @@ class Registry { return 'application/openmetrics-text; version=1.0.0; charset=utf-8'; } - static get ESCAPE_STRING_REPLACE_MAP() { - return { - '\\': '\\\\', - '\n': '\\n', - }; - } - - static get ESCAPE_LABEL_VALUE_REPLACE_MAP() { - return Object.assign({}, Registry.ESCAPE_STRING_REPLACE_MAP, { - '"': '\\\\"', - }); - } - - static get ESCAPE_REPLACE_REGEXP() { - return /\\|\n|"/g; - } - constructor(regContentType = Registry.PROMETHEUS_CONTENT_TYPE) { this._metrics = {}; this._collectors = []; @@ -256,14 +251,14 @@ function escapeLabelValue(str) { return str; } - return escapeString(str, Registry.ESCAPE_LABEL_VALUE_REPLACE_MAP); + return escapeString(str, ESCAPE_LABEL_VALUE_REPLACE_MAP); } function escapeString(str, extraReplaceDict) { const fullDict = extraReplaceDict ? extraReplaceDict - : Registry.ESCAPE_STRING_REPLACE_MAP; + : ESCAPE_STRING_REPLACE_MAP; - return str.replace(Registry.ESCAPE_REPLACE_REGEXP, REPLACE_FUNC(fullDict)); + return str.replace(ESCAPE_REPLACE_REGEXP, REPLACE_FUNC(fullDict)); } function standardizeCounterName(name) { return name.replace(/_total$/, '');