write_prometheus: Added 'Host' option.
authorPavel Rochnyack <pavel2000@ngs.ru>
Wed, 24 Oct 2018 08:08:14 +0000 (15:08 +0700)
committerPavel Rochnyack <pavel2000@ngs.ru>
Wed, 24 Oct 2018 08:08:14 +0000 (15:08 +0700)
This allows to set specific address to listen on.

Closes: #2173
Closes: #2288

src/collectd.conf.pod
src/write_prometheus.c

index 6f5ee7f..bb2aace 100644 (file)
@@ -9673,6 +9673,13 @@ B<Options:>
 
 =over 4
 
+=item B<Host> I<Host>
+
+Bind to the hostname / address I<Host>. By default, the plugin will bind to the
+"any" address, i.e. accept packets sent to any of the hosts addresses.
+
+This option is supported only for libmicrohttpd newer than 0.9.0.
+
 =item B<Port> I<Port>
 
 Port the embedded webserver should listen on. Defaults to B<9103>.
index 7137558..53a0709 100644 (file)
@@ -54,6 +54,7 @@
 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;
 
@@ -746,7 +747,7 @@ static int prom_open_socket(int addrfamily) {
   snprintf(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,
@@ -764,7 +765,7 @@ static int prom_open_socket(int addrfamily) {
       continue;
 
     if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &(int){1}, sizeof(int)) != 0) {
-      WARNING("write_prometheus: setsockopt(SO_REUSEADDR) failed: %s",
+      WARNING("write_prometheus plugin: setsockopt(SO_REUSEADDR) failed: %s",
               STRERRNO);
       close(fd);
       fd = -1;
@@ -783,6 +784,15 @@ static int prom_open_socket(int addrfamily) {
       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;
   }
 
@@ -797,7 +807,9 @@ static struct MHD_Daemon *prom_start_daemon() {
   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;
   }
 
@@ -844,7 +856,15 @@ static int prom_config(oconfig_item_t *ci) {
   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;
@@ -872,7 +892,6 @@ static int prom_init() {
   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",
@@ -965,6 +984,8 @@ static int prom_shutdown() {
   }
   pthread_mutex_unlock(&metrics_lock);
 
+  sfree(httpd_host);
+
   return 0;
 }