// SPDX-License-Identifier: GPL-3.0-or-later
#define BACKENDS_INTERNALS
#include "backend_prometheus.h"
// ----------------------------------------------------------------------------
// PROMETHEUS
// /api/v1/allmetrics?format=prometheus and /api/v1/allmetrics?format=prometheus_all_hosts
static struct prometheus_server {
const char *server;
uint32_t hash;
RRDHOST *host;
time_t last_access;
struct prometheus_server *next;
} *prometheus_server_root = NULL;
static inline time_t prometheus_server_last_access(const char *server, RRDHOST *host, time_t now) {
static netdata_mutex_t prometheus_server_root_mutex = NETDATA_MUTEX_INITIALIZER;
uint32_t hash = simple_hash(server);
netdata_mutex_lock(&prometheus_server_root_mutex);
struct prometheus_server *ps;
for(ps = prometheus_server_root; ps ;ps = ps->next) {
if (host == ps->host && hash == ps->hash && !strcmp(server, ps->server)) {
time_t last = ps->last_access;
ps->last_access = now;
netdata_mutex_unlock(&prometheus_server_root_mutex);
return last;
}
}
ps = callocz(1, sizeof(struct prometheus_server));
ps->server = strdupz(server);
ps->hash = hash;
ps->host = host;
ps->last_access = now;
ps->next = prometheus_server_root;
prometheus_server_root = ps;
netdata_mutex_unlock(&prometheus_server_root_mutex);
return 0;
}
static inline size_t backends_prometheus_name_copy(char *d, const char *s, size_t usable) {
size_t n;
for(n = 0; *s && n < usable ; d++, s++, n++) {
register char c = *s;
if(!isalnum(c)) *d = '_';
else *d = c;
}
*d = '\0';
return n;
}
static inline size_t backends_prometheus_label_copy(char *d, const char *s, size_t usable) {
size_t n;
// make sure we can escape one character without overflowing the buffer
usable--;
for(n = 0; *s && n < usable ; d++, s++, n++) {
register char c = *s;
if(unlikely(c == '"' || c == '\\' || c == '\n')) {
*d++ = '\\';
n++;
}
*d = c;
}
*d = '\0';
return n;
}
static inline char *backends_prometheus_units_copy(char *d, const char *s, size_t usable, int showoldunits) {
const char *sorig = s;
char *ret = d;
size_t n;
// Fix for issue 5227
if (unlikely(showoldunits)) {
static struct {
const char *newunit;
uint32_t hash;
const char *oldunit;
} units[] = {
{"KiB/s", 0, "kilobytes/s"}
, {"MiB/s", 0, "MB/s"}
, {"GiB/s", 0, "GB/s"}
, {"KiB" , 0, "KB"}
, {"MiB" , 0, "MB"}
, {"GiB" , 0, "GB"}
, {"inodes" , 0, "Inodes"}
, {"percentage" , 0, "percent"}
, {"faults/s" , 0, "page faults/s"}
, {"KiB/operation", 0, "kilobytes per operation"}
, {"milliseconds/operation", 0, "ms per operation"}
, {NULL, 0, NULL}
};
static int initialized = 0;
int i;
if(unlikely(!initialized)) {
for (i = 0; units[i].newunit; i++)
units[i].hash = simple_hash(units[i].newunit);
initialized = 1;
}
uint32_t hash = simple_hash(s);
for(i = 0; units[i].newunit ; i++) {
if(unlikely(hash == units[i].hash && !strcmp(s, units[i].newunit))) {
// info("matched extension for filename '%s': '%s'", filename, last_dot);
s=units[i].oldunit;
sorig = s;
break;
}
}
}
*d