Added ordering to tags and values, set tags as first in metrics to prevent overwriting very much needed metric labels.

This commit is contained in:
Rick van Drongelen 2025-07-01 12:03:50 +02:00
parent fe8c839237
commit 2e597c7697
No known key found for this signature in database

View file

@ -16,13 +16,13 @@ class Prometheus {
*/ */
constructor(monitor, tags) { constructor(monitor, tags) {
this.monitorLabelValues = { this.monitorLabelValues = {
...this.mapTagsToLabels(tags),
monitor_id: monitor.id, monitor_id: monitor.id,
monitor_name: monitor.name, monitor_name: monitor.name,
monitor_type: monitor.type, monitor_type: monitor.type,
monitor_url: monitor.url, monitor_url: monitor.url,
monitor_hostname: monitor.hostname, monitor_hostname: monitor.hostname,
monitor_port: monitor.port, monitor_port: monitor.port
...this.mapTagsToLabels(tags)
}; };
} }
@ -34,20 +34,22 @@ class Prometheus {
* @returns {Promise<void>} * @returns {Promise<void>}
*/ */
static async init() { static async init() {
const tags = (await R.findAll("tag")).map((tag) => { // Add all available tags as possible labels,
// and use Set to remove possible duplicates (for when multiple tags contain non-ascii characters, and thus are sanitized to the same label)
const tags = new Set((await R.findAll("tag")).map((tag) => {
return Prometheus.sanitizeForPrometheus(tag.name); return Prometheus.sanitizeForPrometheus(tag.name);
}).filter((tagName) => { }).filter((tagName) => {
return tagName !== ""; return tagName !== "";
}); }));
const commonLabels = [ const commonLabels = [
...tags,
"monitor_id", "monitor_id",
"monitor_name", "monitor_name",
"monitor_type", "monitor_type",
"monitor_url", "monitor_url",
"monitor_hostname", "monitor_hostname",
"monitor_port", "monitor_port",
...tags // Add all available tags as possible labels
]; ];
monitorCertDaysRemaining = new PrometheusClient.Gauge({ monitorCertDaysRemaining = new PrometheusClient.Gauge({
@ -84,13 +86,13 @@ class Prometheus {
static sanitizeForPrometheus(text) { static sanitizeForPrometheus(text) {
text = text.replace(/[^a-zA-Z0-9_]/g, ""); text = text.replace(/[^a-zA-Z0-9_]/g, "");
text = text.replace(/^[^a-zA-Z_]+/, ""); text = text.replace(/^[^a-zA-Z_]+/, "");
return text; return text.toLowerCase();
} }
/** /**
* Map the tags value to valid labels used in Prometheus. Sanitize them in the process. * Map the tags value to valid labels used in Prometheus. Sanitize them in the process.
* @param {Array<{name: string, value:?string}>} tags The tags to map * @param {Array<{name: string, value:?string}>} tags The tags to map
* @returns {Array<string, string>} The mapped tags, usable as labels * @returns {object} The mapped tags, usable as labels
*/ */
mapTagsToLabels(tags) { mapTagsToLabels(tags) {
let mappedTags = {}; let mappedTags = {};
@ -101,16 +103,22 @@ class Prometheus {
} }
if (mappedTags[sanitizedTag] === undefined) { if (mappedTags[sanitizedTag] === undefined) {
mappedTags[sanitizedTag] = "null"; mappedTags[sanitizedTag] = [];
} }
let tagValue = Prometheus.sanitizeForPrometheus(tag.value); let tagValue = Prometheus.sanitizeForPrometheus(tag.value);
if (tagValue !== "") { if (tagValue !== "") {
mappedTags[sanitizedTag] = mappedTags[sanitizedTag] !== "null" ? mappedTags[sanitizedTag] + `,${tagValue}` : tagValue; mappedTags[sanitizedTag].push(tagValue);
} }
mappedTags[sanitizedTag] = mappedTags[sanitizedTag].sort();
}); });
return mappedTags; // Order the tags alphabetically
return Object.keys(mappedTags).sort().reduce((obj, key) => {
obj[key] = mappedTags[key];
return obj;
}, {});
} }
/** /**