-
Notifications
You must be signed in to change notification settings - Fork 374
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
improve performance of registry.metrics() #373
Changes from all commits
266dcd7
7227147
3c4c748
a1a3675
3c0ad3a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,84 @@ | ||
'use strict'; | ||
|
||
function getFormatter(metric, defaultLabels) { | ||
const defaultLabelNames = Object.keys(defaultLabels); | ||
const name = metric.name; | ||
const help = escapeString(metric.help); | ||
const type = metric.type; | ||
const labelsCode = getLabelsCode(metric, defaultLabelNames, defaultLabels); | ||
|
||
// eslint-disable-next-line no-new-func | ||
return new Function( | ||
'item', | ||
'escapeLabelValue', | ||
'getValueAsString', | ||
` | ||
const info = '# HELP ${name} ${help}\\n# TYPE ${name} ${type}\\n'; | ||
let values = ''; | ||
for (const val of item.values || []) { | ||
val.labels = val.labels || {}; | ||
let metricName = val.metricName || '${name}'; | ||
const labels = \`${labelsCode}\`; | ||
const hasLabels = labels.length > 0; | ||
metricName += \`\${hasLabels ? '{' : ''}\${labels}\${hasLabels ? '}' : ''}\`; | ||
let line = \`\${metricName} \${getValueAsString(val.value)}\`; | ||
values += \`\${line}\\n\`; | ||
} | ||
return info + values; | ||
`, | ||
); | ||
} | ||
|
||
function getLabelsCode(metric, defaultLabelNames, defaultLabels) { | ||
const labelString = []; | ||
const labelNames = getLabelNames(metric, defaultLabelNames); | ||
for (let index = 0; index < labelNames.length; index++) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ⭐ It's valid to only set values for a subset of labels when a metric is updated. With this test: it('should allow subsetse of labels', () => {
instance = new Gauge({
name: 'name_2',
help: 'help',
labelNames: ['code', 'success'],
});
instance.inc({ code: '200' }, 10);
const str = globalRegistry.getSingleMetricAsString('name_2');
console.log(str);
}); in this PR, you get
whereas in master, you get
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. should add this as a test, no? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, of course. I’ll fix it There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The above test case passes, but now if the first label is undefined, there's a stray leading comma:
prints
(notice last two lines) Something like these should both be committed as test cases. Do you feel like adding them please? Just checked, benchmarks still look significantly faster despite the new branch added in the last commits. 👍 |
||
const comma = index > 0 ? ',' : ''; | ||
const labelName = labelNames[index]; | ||
if (labelName === 'quantile') { | ||
labelString.push( | ||
`\${val.labels.quantile != null ? \`${comma}quantile="\${escapeLabelValue(val.labels.quantile)}"\` : ''}`, | ||
); | ||
} else if (labelName === 'le') { | ||
labelString.push( | ||
`\${val.labels.le != null ? \`${comma}le="\${escapeLabelValue(val.labels.le)}"\` : ''}`, | ||
); | ||
} else { | ||
const defaultLabelValue = defaultLabels[labelName]; | ||
if (typeof defaultLabelValue === 'undefined') { | ||
labelString.push( | ||
`\${val.labels['${labelName}'] != null ? \`${comma}${labelName}="\${escapeLabelValue(val.labels['${labelName}'])}"\` : ''}`, | ||
); | ||
} else { | ||
labelString.push( | ||
`${comma}${labelName}="\${escapeLabelValue(val.labels['${labelName}'] || '${defaultLabelValue}')}"`, | ||
); | ||
} | ||
} | ||
} | ||
return labelString.join(''); | ||
} | ||
|
||
function getLabelNames(metric, defaultLabelNames) { | ||
const labelNames = [...metric.labelNames]; | ||
for (const labelName of defaultLabelNames) { | ||
if (!labelNames.includes(labelName)) { | ||
labelNames.push(labelName); | ||
} | ||
} | ||
if (metric.type === 'summary') { | ||
labelNames.push('quantile'); | ||
} | ||
if (metric.type === 'histogram') { | ||
labelNames.push('le'); | ||
} | ||
return labelNames; | ||
} | ||
|
||
function escapeString(str) { | ||
return str.replace(/\n/g, '\\\\n').replace(/\\(?!n)/g, '\\\\\\\\'); | ||
} | ||
|
||
module.exports = { | ||
getFormatter, | ||
}; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
⭐ This is going to make it impossible to implement #298/landing #368. As you can tell from the comments in those, I'm not certain what the fate of that issue is though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you clarify what do you mean? Should I rewrite it or implement inside generated function?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@zbjornson can you take a look on this?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the nudge, will review this PR this weekend.
On this particular comment: I'd (strongly) lean toward making the formatter work with dynamically declared labels. #298 has quite a bit of support so I suspect #368 will land. The main (probably minor) thing holding it up is #298 (comment).
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This eliminate the main idea of
formatter
- build labels string once.I need to think how to rewrite this.