diff options
Diffstat (limited to '')
-rw-r--r-- | src/exporting/prometheus/prometheus.c (renamed from exporting/prometheus/prometheus.c) | 170 |
1 files changed, 124 insertions, 46 deletions
diff --git a/exporting/prometheus/prometheus.c b/src/exporting/prometheus/prometheus.c index 6644e1799..037539572 100644 --- a/exporting/prometheus/prometheus.c +++ b/src/exporting/prometheus/prometheus.c @@ -1,6 +1,5 @@ // SPDX-License-Identifier: GPL-3.0-or-later -#define EXPORTINGS_INTERNALS #include "prometheus.h" // ---------------------------------------------------------------------------- @@ -375,59 +374,55 @@ static int print_host_variables_callback(const DICTIONARY_ITEM *item __maybe_unu struct host_variables_callback_options *opts = data; - if (rrdvar_flags(rv) & (RRDVAR_FLAG_CUSTOM_HOST_VAR | RRDVAR_FLAG_CUSTOM_CHART_VAR)) { - if (!opts->host_header_printed) { - opts->host_header_printed = 1; + if (!opts->host_header_printed) { + opts->host_header_printed = 1; - if (opts->output_options & PROMETHEUS_OUTPUT_HELP) { - buffer_sprintf(opts->wb, "\n# COMMENT global host and chart variables\n"); - } + if (opts->output_options & PROMETHEUS_OUTPUT_HELP) { + buffer_sprintf(opts->wb, "\n# COMMENT global host and chart variables\n"); } + } - NETDATA_DOUBLE value = rrdvar2number(rv); - if (isnan(value) || isinf(value)) { - if (opts->output_options & PROMETHEUS_OUTPUT_HELP) - buffer_sprintf( - opts->wb, "# COMMENT variable \"%s\" is %s. Skipped.\n", rrdvar_name(rv), (isnan(value)) ? "NAN" : "INF"); - - return 0; - } + NETDATA_DOUBLE value = rrdvar2number(rv); + if (isnan(value) || isinf(value)) { + if (opts->output_options & PROMETHEUS_OUTPUT_HELP) + buffer_sprintf( + opts->wb, "# COMMENT variable \"%s\" is %s. Skipped.\n", rrdvar_name(rv), (isnan(value)) ? "NAN" : "INF"); - char *label_pre = ""; - char *label_post = ""; - if (opts->labels && *opts->labels) { - label_pre = "{"; - label_post = "}"; - } + return 0; + } - prometheus_name_copy(opts->name, rrdvar_name(rv), sizeof(opts->name)); + char *label_pre = ""; + char *label_post = ""; + if (opts->labels && *opts->labels) { + label_pre = "{"; + label_post = "}"; + } - if (opts->output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) - buffer_sprintf( - opts->wb, - "%s_%s%s%s%s " NETDATA_DOUBLE_FORMAT " %llu\n", - opts->prefix, - opts->name, - label_pre, - opts->labels, - label_post, - value, - opts->now * 1000ULL); - else - buffer_sprintf( - opts->wb, - "%s_%s%s%s%s " NETDATA_DOUBLE_FORMAT "\n", - opts->prefix, - opts->name, - label_pre, - opts->labels, - label_post, - value); + prometheus_name_copy(opts->name, rrdvar_name(rv), sizeof(opts->name)); - return 1; - } + if (opts->output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) + buffer_sprintf( + opts->wb, + "%s_%s%s%s%s " NETDATA_DOUBLE_FORMAT " %llu\n", + opts->prefix, + opts->name, + label_pre, + opts->labels, + label_post, + value, + opts->now * 1000ULL); + else + buffer_sprintf( + opts->wb, + "%s_%s%s%s%s " NETDATA_DOUBLE_FORMAT "\n", + opts->prefix, + opts->name, + label_pre, + opts->labels, + label_post, + value); - return 0; + return 1; } struct gen_parameters { @@ -527,6 +522,86 @@ static void generate_as_collected_prom_metric(BUFFER *wb, buffer_sprintf(wb, "\n"); } +static void prometheus_print_os_info( + BUFFER *wb, + RRDHOST *host, + PROMETHEUS_OUTPUT_OPTIONS output_options) +{ + FILE *fp; + char filename[FILENAME_MAX + 1]; + char buf[BUFSIZ + 1]; + + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/etc/os-release"); + fp = fopen(filename, "r"); + if (!fp) { + /* Fallback to lsb-release */ + snprintfz(filename, FILENAME_MAX, "%s%s", netdata_configured_host_prefix, "/etc/lsb-release"); + fp = fopen(filename, "r"); + } + if (!fp) { + return; + } + + buffer_sprintf(wb, "netdata_os_info{instance=\"%s\"", rrdhost_hostname(host)); + + while (fgets(buf, BUFSIZ, fp)) { + char *in, *sanitized; + char *key, *val; + int in_val_part = 0; + + /* sanitize the line */ + sanitized = in = buf; + in_val_part = 0; + while (*in && *in != '\n') { + if (!in_val_part) { + /* Only accepts alphabetic characters and '_' + * in key part */ + if (isalpha(*in) || *in == '_') { + *(sanitized++) = tolower(*in); + } else if (*in == '=') { + in_val_part = 1; + *(sanitized++) = '='; + } + } else { + /* Don't accept special characters in + * value part */ + switch (*in) { + case '"': + case '\'': + case '\r': + case '\t': + break; + default: + if (isprint(*in)) { + *(sanitized++) = *in; + } + } + } + in++; + } + /* Terminate the string */ + *(sanitized++) = '\0'; + + /* Split key/val */ + key = buf; + val = strchr(buf, '='); + + /* If we have a key/value pair, add it as a label */ + if (val) { + *val = '\0'; + val++; + buffer_sprintf(wb, ",%s=\"%s\"", key, val); + } + } + + /* Finish the line */ + if (output_options & PROMETHEUS_OUTPUT_TIMESTAMPS) + buffer_sprintf(wb, "} 1 %llu\n", now_realtime_usec() / USEC_PER_MS); + else + buffer_sprintf(wb, "} 1\n"); + + fclose(fp); +} /** * Write metrics in Prometheus format to a buffer. * @@ -580,6 +655,9 @@ static void rrd_stats_api_v1_charts_allmetrics_prometheus( if (instance->labels_buffer) buffer_flush(instance->labels_buffer); + if (instance->config.options & EXPORTING_OPTION_SEND_AUTOMATIC_LABELS) + prometheus_print_os_info(wb, host, output_options); + // send custom variables set for the host if (output_options & PROMETHEUS_OUTPUT_VARIABLES) { |