Browse Source

xhttp_prom: new xhttp_prom_tags parameter

- allows custom tags to be added to prometheus metrics
- Addresses GH issue #4021
Christian Berger 9 tháng trước cách đây
mục cha
commit
f92de6d0e5

+ 25 - 0
src/modules/xhttp_prom/doc/xhttp_prom_admin.xml

@@ -251,6 +251,31 @@ modparam("xhttp_prom", "xhttp_prom_beginning", "my_metric_")
 
 # No string at the beginning.
 modparam("xhttp_prom", "xhttp_prom_beginning", "");
+...
+		</programlisting>
+	  </example>
+	</section>
+	<section id="xhttp_prom.p.xhttp_prom_tags">
+	  <title><varname>xhttp_prom_tags</varname> (str)</title>
+	  <para>
+		Specifies additional tags for the metrics. These can be useful for evaluating
+		  the metrics afterwards.
+	  </para>
+	  <para>
+		It defaults to an empty string which means that no metric tags will be added.
+	  </para>
+	  <para>
+		A comma separated list of key-value pairs connected by equal signs.
+	  </para>
+	  <example>
+		<title>Set <varname>xhttp_prom_tags</varname> parameter</title>
+		<programlisting format="linespecific">
+...
+# Add one tag to every metric
+modparam("xhttp_prom", "xhttp_prom_tags", "host_job=foo")
+
+# Add multiple tags to every metric
+modparam("xhttp_prom", "xhttp_prom_tags", "tag_bar=foo,host_job=wurst");
 ...
 		</programlisting>
 	  </example>

+ 16 - 14
src/modules/xhttp_prom/prom.c

@@ -191,8 +191,9 @@ static int metric_generate(
 			(uint64_t)ts);
 
 	/* Print metric name. */
-	if(prom_body_name_printf(ctx, "%.*s%.*s_%.*s", xhttp_prom_beginning.len,
-			   xhttp_prom_beginning.s, group->len, group->s, name->len, name->s)
+	if(prom_body_name_printf(ctx, "%.*s%.*s_%.*s%s", xhttp_prom_beginning.len,
+			   xhttp_prom_beginning.s, group->len, group->s, name->len, name->s,
+			   xhttp_prom_tags_braces)
 			== -1) {
 		LM_ERR("Fail to print\n");
 		return -1;
@@ -225,8 +226,9 @@ static int prom_metric_uptime_print(prom_ctx_t *ctx)
 
 	time(&now);
 	uptime = (int)(now - up_since);
-	if(prom_body_printf(ctx, "%.*suptime %d %" PRIu64 "\n",
-			   xhttp_prom_beginning.len, xhttp_prom_beginning.s, uptime, ts)
+	if(prom_body_printf(ctx, "%.*suptime%s %d %" PRIu64 "\n",
+			   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
+			   xhttp_prom_tags_braces, uptime, ts)
 			== -1) {
 		LM_ERR("Fail to print\n");
 		goto error;
@@ -254,51 +256,51 @@ static int prom_metric_pkgmem_print(prom_ctx_t *ctx)
 
 	for(; i < pkg_proc_stats_no; i++) {
 		if(prom_body_printf(ctx,
-				   "%.*spkgmem_used{pid=\"%u\", rank=\"%d\", desc=\"%s\"} "
+				   "%.*spkgmem_used{pid=\"%u\", rank=\"%d\", desc=\"%s\"%s} "
 				   "%lu %" PRIu64 "\n",
 				   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
 				   pkg_proc_stats[i].pid, pkg_proc_stats[i].rank, pt[i].desc,
-				   pkg_proc_stats[i].used, ts)
+				   xhttp_prom_tags_comma, pkg_proc_stats[i].used, ts)
 				== -1) {
 			LM_ERR("Fail to print\n");
 			goto error;
 		}
 		if(prom_body_printf(ctx,
 				   "%.*spkgmem_available{pid=\"%u\", rank=\"%d\", "
-				   "desc=\"%s\"} %lu %" PRIu64 "\n",
+				   "desc=\"%s\"%s} %lu %" PRIu64 "\n",
 				   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
 				   pkg_proc_stats[i].pid, pkg_proc_stats[i].rank, pt[i].desc,
-				   pkg_proc_stats[i].available, ts)
+				   xhttp_prom_tags_comma, pkg_proc_stats[i].available, ts)
 				== -1) {
 			LM_ERR("Fail to print\n");
 			goto error;
 		}
 		if(prom_body_printf(ctx,
 				   "%.*spkgmem_real_used{pid=\"%u\", rank=\"%d\", "
-				   "desc=\"%s\"} %lu %" PRIu64 "\n",
+				   "desc=\"%s\"%s} %lu %" PRIu64 "\n",
 				   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
 				   pkg_proc_stats[i].pid, pkg_proc_stats[i].rank, pt[i].desc,
-				   pkg_proc_stats[i].real_used, ts)
+				   xhttp_prom_tags_comma, pkg_proc_stats[i].real_used, ts)
 				== -1) {
 			LM_ERR("Fail to print\n");
 			goto error;
 		}
 		if(prom_body_printf(ctx,
 				   "%.*spkgmem_total_frags{pid=\"%u\", rank=\"%d\", "
-				   "desc=\"%s\"} %lu %" PRIu64 "\n",
+				   "desc=\"%s\"%s} %lu %" PRIu64 "\n",
 				   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
 				   pkg_proc_stats[i].pid, pkg_proc_stats[i].rank, pt[i].desc,
-				   pkg_proc_stats[i].total_frags, ts)
+				   xhttp_prom_tags_comma, pkg_proc_stats[i].total_frags, ts)
 				== -1) {
 			LM_ERR("Fail to print\n");
 			goto error;
 		}
 		if(prom_body_printf(ctx,
 				   "%.*spkgmem_total_size{pid=\"%u\", rank=\"%d\" "
-				   "desc=\"%s\"} %lu %" PRIu64 "\n",
+				   "desc=\"%s\"%s} %lu %" PRIu64 "\n",
 				   xhttp_prom_beginning.len, xhttp_prom_beginning.s,
 				   pkg_proc_stats[i].pid, pkg_proc_stats[i].rank, pt[i].desc,
-				   pkg_proc_stats[i].total_size, ts)
+				   xhttp_prom_tags_comma, pkg_proc_stats[i].total_size, ts)
 				== -1) {
 			LM_ERR("Fail to print\n");
 			goto error;

+ 50 - 0
src/modules/xhttp_prom/xhttp_prom.c

@@ -153,6 +153,21 @@ str xhttp_prom_stats = str_init("");
  */
 str xhttp_prom_beginning = str_init("kamailio_");
 
+/**
+ * @brief string for metrics tags.
+ */
+str xhttp_prom_tags = str_init("");
+
+/**
+ * @brief helper string for metrics tags. Used for appending tag lists
+ */
+char *xhttp_prom_tags_comma = "";
+
+/**
+ * @brief helper string for metrics tags. Used for appending to metric
+ */
+char *xhttp_prom_tags_braces = "";
+
 int buf_size = 0; /**< size of buffer that contains the reply. */
 
 int timeout_minutes = 60; /**< timeout in minutes to delete old metrics. */
@@ -195,6 +210,7 @@ static param_export_t params[] = {
 	{"xhttp_prom_buf_size", PARAM_INT, &buf_size},
 	{"xhttp_prom_stats", PARAM_STR, &xhttp_prom_stats},
 	{"xhttp_prom_beginning", PARAM_STR, &xhttp_prom_beginning},
+	{"xhttp_prom_tags", PARAM_STR, &xhttp_prom_tags},
 	{"prom_counter", PARAM_STRING | PARAM_USE_FUNC, (void *)prom_counter_param},
 	{"prom_gauge", PARAM_STRING | PARAM_USE_FUNC, (void *)prom_gauge_param},
 	{"prom_histogram", PARAM_STRING | PARAM_USE_FUNC, (void *)prom_histogram_param},
@@ -282,6 +298,32 @@ static int mod_init(void)
 		return -1;
 	}
 
+	/* Write helper variables used to make handling additional metrics easier*/
+	if(xhttp_prom_tags.len > 0) {
+		/* 4 characters more for comma, space and terminating null */
+		size_t len_comma = xhttp_prom_tags.len + 4;
+		xhttp_prom_tags_comma = shm_malloc(len_comma);
+		if(xhttp_prom_tags_comma == NULL) {
+			LM_ERR("cannot allocate memory for helper variable\n");
+			return -1;
+		}
+		memset(xhttp_prom_tags_comma, 0, len_comma);
+		snprintf(xhttp_prom_tags_comma, len_comma - 1, ", %.*s",
+				xhttp_prom_tags.len, xhttp_prom_tags.s);
+		/* 4 characters more for curly braces and  terminating null */
+		size_t len_braces = xhttp_prom_tags.len + 4;
+		xhttp_prom_tags_braces = shm_malloc(len_braces);
+		if(xhttp_prom_tags_braces == NULL) {
+			LM_ERR("cannot allocate memory for helper variable\n");
+			return -1;
+		}
+		memset(xhttp_prom_tags_braces, 0, len_braces);
+		snprintf(xhttp_prom_tags_braces, len_braces - 1, "{%.*s}",
+				xhttp_prom_tags.len, xhttp_prom_tags.s);
+		LM_DBG("mod_init initalized helper variables to '%s' and '%s'\n",
+				xhttp_prom_tags_comma, xhttp_prom_tags_braces);
+	}
+
 	return 0;
 }
 
@@ -298,6 +340,14 @@ static void mod_destroy(void)
 {
 	LM_DBG("cleaning up\n");
 
+	/* Remove helper variables for tags */
+	if(xhttp_prom_tags.len > 0) {
+		if(xhttp_prom_tags_comma != NULL)
+			shm_free(xhttp_prom_tags_comma);
+		if(xhttp_prom_tags_braces != NULL)
+			shm_free(xhttp_prom_tags_braces);
+	}
+
 	prom_metric_close();
 }
 

+ 15 - 0
src/modules/xhttp_prom/xhttp_prom.h

@@ -81,6 +81,21 @@ typedef struct prom_ctx
  */
 extern str xhttp_prom_beginning;
 
+/**
+ * @brief string for metrics tags.
+ */
+extern str xhttp_prom_tags;
+
+/**
+ * @brief helper string for metrics tags. Used for appending tag lists
+ */
+extern char *xhttp_prom_tags_comma;
+
+/**
+ * @brief helper string for metrics tags. Used for appending to metric
+ */
+extern char *xhttp_prom_tags_braces;
+
 /**
  * @brief timeout in minutes to delete old metrics.
  */