#include "collectd.h"
-#include "common.h"
#include "plugin.h"
-#include "utils_avltree.h"
+#include "utils/avltree/avltree.h"
+#include "utils/common/common.h"
#include "utils_complain.h"
#include "utils_time.h"
static c_avl_tree_t *metrics;
static pthread_mutex_t metrics_lock = PTHREAD_MUTEX_INITIALIZER;
+static char *httpd_host = NULL;
static unsigned short httpd_port = 9103;
static struct MHD_Daemon *httpd;
#define LABEL_BUFFER_SIZE (LABEL_KEY_SIZE + LABEL_VALUE_SIZE + 4)
char *labels[3] = {
- (char[LABEL_BUFFER_SIZE]){0}, (char[LABEL_BUFFER_SIZE]){0},
+ (char[LABEL_BUFFER_SIZE]){0},
+ (char[LABEL_BUFFER_SIZE]){0},
(char[LABEL_BUFFER_SIZE]){0},
};
* know that they are sane. */
for (size_t i = 0; i < m->n_label; i++) {
char value[LABEL_VALUE_SIZE];
- snprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
- escape_label_value(value, sizeof(value), m->label[i]->value));
+ ssnprintf(labels[i], LABEL_BUFFER_SIZE, "%s=\"%s\"", m->label[i]->name,
+ escape_label_value(value, sizeof(value), m->label[i]->value));
}
strjoin(buffer, buffer_size, labels, m->n_label, ",");
while (c_avl_iterator_next(iter, (void *)&unused_name, (void *)&fam) == 0) {
char line[1024]; /* 4x DATA_MAX_NAME_LEN? */
- snprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
+ ssnprintf(line, sizeof(line), "# HELP %s %s\n", fam->name, fam->help);
buffer->append(buffer, strlen(line), (uint8_t *)line);
- snprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
- (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
- ? "gauge"
- : "counter");
+ ssnprintf(line, sizeof(line), "# TYPE %s %s\n", fam->name,
+ (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
+ ? "gauge"
+ : "counter");
buffer->append(buffer, strlen(line), (uint8_t *)line);
for (size_t i = 0; i < fam->n_metric; i++) {
char timestamp_ms[24] = "";
if (m->has_timestamp_ms)
- snprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
- m->timestamp_ms);
+ ssnprintf(timestamp_ms, sizeof(timestamp_ms), " %" PRIi64,
+ m->timestamp_ms);
if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__GAUGE)
- snprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
- format_labels(labels, sizeof(labels), m), m->gauge->value,
- timestamp_ms);
+ ssnprintf(line, sizeof(line), "%s{%s} " GAUGE_FORMAT "%s\n", fam->name,
+ format_labels(labels, sizeof(labels), m), m->gauge->value,
+ timestamp_ms);
else /* if (fam->type == IO__PROMETHEUS__CLIENT__METRIC_TYPE__COUNTER) */
- snprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
- format_labels(labels, sizeof(labels), m), m->counter->value,
- timestamp_ms);
+ ssnprintf(line, sizeof(line), "%s{%s} %.0f%s\n", fam->name,
+ format_labels(labels, sizeof(labels), m), m->counter->value,
+ timestamp_ms);
buffer->append(buffer, strlen(line), (uint8_t *)line);
}
c_avl_iterator_destroy(iter);
char server[1024];
- snprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
- PACKAGE_VERSION, hostname_g);
+ ssnprintf(server, sizeof(server), "\n# collectd/write_prometheus %s at %s\n",
+ PACKAGE_VERSION, hostname_g);
buffer->append(buffer, strlen(server), (uint8_t *)server);
pthread_mutex_unlock(&metrics_lock);
msg->name = name;
char help[1024];
- snprintf(
+ ssnprintf(
help, sizeof(help),
"write_prometheus plugin: '%s' Type: '%s', Dstype: '%s', Dsname: '%s'",
vl->plugin, vl->type, DS_TYPE_TO_STRING(ds->ds[ds_index].type),
int status = c_avl_insert(metrics, fam->name, fam);
if (status != 0) {
- ERROR("write_prometheus plugin: Adding \"%s\" failed.", name);
+ ERROR("write_prometheus plugin: Adding \"%s\" failed.", fam->name);
metric_family_destroy(fam);
return NULL;
}
static int prom_open_socket(int addrfamily) {
/* {{{ */
char service[NI_MAXSERV];
- snprintf(service, sizeof(service), "%hu", httpd_port);
+ ssnprintf(service, sizeof(service), "%hu", httpd_port);
struct addrinfo *res;
- int status = getaddrinfo(NULL, service,
+ int status = getaddrinfo(httpd_host, service,
&(struct addrinfo){
.ai_flags = AI_PASSIVE | AI_ADDRCONFIG,
.ai_family = addrfamily,
int fd = -1;
for (struct addrinfo *ai = res; ai != NULL; ai = ai->ai_next) {
- fd = socket(ai->ai_family, ai->ai_socktype | SOCK_CLOEXEC, 0);
+ int flags = ai->ai_socktype;
+#ifdef SOCK_CLOEXEC
+ flags |= SOCK_CLOEXEC;
+#endif
+
+ fd = socket(ai->ai_family, flags, 0);
if (fd == -1)
continue;
- int tmp = 1;
- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) != 0) {
- WARNING("write_prometheus: setsockopt(SO_REUSEADDR) failed: %s",
+ if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) != 0) {
+ WARNING("write_prometheus plugin: setsockopt(SO_REUSEADDR) failed: %s",
STRERRNO);
close(fd);
fd = -1;
continue;
}
+ char str_node[NI_MAXHOST];
+ char str_service[NI_MAXSERV];
+
+ getnameinfo(ai->ai_addr, ai->ai_addrlen, str_node, sizeof(str_node),
+ str_service, sizeof(str_service),
+ NI_NUMERICHOST | NI_NUMERICSERV);
+
+ INFO("write_prometheus plugin: Listening on [%s]:%s.", str_node,
+ str_service);
break;
}
if (fd == -1)
fd = prom_open_socket(PF_INET);
if (fd == -1) {
- ERROR("write_prometheus plugin: Opening a listening socket failed.");
+ ERROR("write_prometheus plugin: Opening a listening socket for [%s]:%hu "
+ "failed.",
+ (httpd_host != NULL) ? httpd_host : "::", httpd_port);
return NULL;
}
for (int i = 0; i < ci->children_num; i++) {
oconfig_item_t *child = ci->children + i;
- if (strcasecmp("Port", child->key) == 0) {
+ if (strcasecmp("Host", child->key) == 0) {
+#if MHD_VERSION >= 0x00090000
+ cf_util_get_string(child, &httpd_host);
+#else
+ ERROR("write_prometheus plugin: Option `Host' not supported. Please "
+ "upgrade libmicrohttpd to at least 0.9.0");
+ return -1;
+#endif
+ } else if (strcasecmp("Port", child->key) == 0) {
int status = cf_util_get_port_number(child);
if (status > 0)
httpd_port = (unsigned short)status;
if (httpd == NULL) {
httpd = prom_start_daemon();
if (httpd == NULL) {
- ERROR("write_prometheus plugin: MHD_start_daemon() failed.");
return -1;
}
DEBUG("write_prometheus plugin: Successfully started microhttpd %s",
}
pthread_mutex_unlock(&metrics_lock);
+ sfree(httpd_host);
+
return 0;
}