Skip to content

Commit

Permalink
feat: improve performance of getMetricAsPrometheusString (#542)
Browse files Browse the repository at this point in the history
Co-authored-by: Dan Shappir <[email protected]>
  • Loading branch information
Dan Shappir and Dan Shappir authored Mar 4, 2023
1 parent 081d8a0 commit cf5173c
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 31 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ project adheres to [Semantic Versioning](http://semver.org/).

### Changed

- Refactor `getMetricAsPrometheusString` method in the `Registry` class to use `Array.prototype.join`
instead of loop of string concatenations.
- Also use `Array.prototype.map`, and object spread instead of an explicit `for` loop
- changed: updated the sample output in `example/default-metrics.js`

### Added
Expand Down
49 changes: 18 additions & 31 deletions lib/registry.js
Original file line number Diff line number Diff line change
Expand Up @@ -27,40 +27,27 @@ class Registry {
const name = escapeString(item.name);
const help = `# HELP ${name} ${escapeString(item.help)}`;
const type = `# TYPE ${name} ${item.type}`;
const defaultLabelNames = Object.keys(this._defaultLabels);

let values = '';
for (const val of item.values || []) {
val.labels = val.labels || {};

if (defaultLabelNames.length > 0) {
// Make a copy before mutating
val.labels = Object.assign({}, val.labels);

for (const labelName of defaultLabelNames) {
val.labels[labelName] =
val.labels[labelName] || this._defaultLabels[labelName];
}
}

let metricName = val.metricName || item.name;

const keys = Object.keys(val.labels);
const size = keys.length;
if (size > 0) {
let labels = '';
let i = 0;
for (; i < size - 1; i++) {
labels += `${keys[i]}="${escapeLabelValue(val.labels[keys[i]])}",`;
}
labels += `${keys[i]}="${escapeLabelValue(val.labels[keys[i]])}"`;
metricName += `{${labels}}`;
}
const defaultLabels =
Object.keys(this._defaultLabels).length > 0 ? this._defaultLabels : null;

const values = [help, type];
for (const { metricName = item.name, value, labels = {} } of item.values ||
[]) {
const labelsWithDefaults = defaultLabels
? { ...labels, ...defaultLabels, ...labels }
: labels;

const formattedLabels = Object.entries(labelsWithDefaults).map(
([n, v]) => `${n}="${escapeLabelValue(v)}"`,
);
const labelsString = formattedLabels.length
? `{${formattedLabels.join(',')}}`
: '';

values += `${metricName} ${getValueAsString(val.value)}\n`;
values.push(`${metricName}${labelsString} ${getValueAsString(value)}`);
}

return `${help}\n${type}\n${values}`.trim();
return values.join('\n');
}

async metrics() {
Expand Down

0 comments on commit cf5173c

Please sign in to comment.