William,

My turn now :)

Here is an attempt to simplify the metrics matrices definition. Instead of having multiple arrays to define the metrics names and type, there is now only 2 arrays. One for the global metrics and another one for the frontend/backend/server metrics. And there is no longer a custom order.

For now, labels and descriptions are still defined apart. I guess, we will be able to simply the descriptions part using the ones from the stats module, overriding only some when necessary. For the labels, I guess we should think about it a bit to have something more flexible.

--
Christopher Faulet
>From 1b5e0dad1cdd9c1f2196a3ce55a84bd1aea0598f Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Wed, 20 Jan 2021 15:28:22 +0100
Subject: [PATCH 1/4] MINOR: contrib/prometheus-exporter: Don't needlessly set
 empty label for metrics

There is no reason to define empty labels for metrics. By default, all labels
are initialized to an empty ist.
---
 .../prometheus-exporter/service-prometheus.c  | 166 +-----------------
 1 file changed, 7 insertions(+), 159 deletions(-)

diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
index 92613e8a9..81f5ba0db 100644
--- a/contrib/prometheus-exporter/service-prometheus.c
+++ b/contrib/prometheus-exporter/service-prometheus.c
@@ -750,169 +750,17 @@ const struct ist promex_st_metric_desc[ST_F_TOTAL_FIELDS] = {
 
 /* Specific labels for all info fields. Empty by default. */
 const struct ist promex_inf_metric_labels[INF_TOTAL_FIELDS] = {
-	[INF_NAME]                           = IST(""),
-	[INF_VERSION]                        = IST(""),
-	[INF_RELEASE_DATE]                   = IST(""),
-	[INF_BUILD_INFO]                     = IST(PROMEX_BUILDINFO_LABEL),
-	[INF_NBTHREAD]                       = IST(""),
-	[INF_NBPROC]                         = IST(""),
-	[INF_PROCESS_NUM]                    = IST(""),
-	[INF_PID]                            = IST(""),
-	[INF_UPTIME]                         = IST(""),
-	[INF_UPTIME_SEC]                     = IST(""),
-	[INF_START_TIME_SEC]                 = IST(""),
-	[INF_MEMMAX_BYTES]                   = IST(""),
-	[INF_POOL_ALLOC_BYTES]               = IST(""),
-	[INF_POOL_USED_BYTES]                = IST(""),
-	[INF_POOL_FAILED]                    = IST(""),
-	[INF_ULIMIT_N]                       = IST(""),
-	[INF_MAXSOCK]                        = IST(""),
-	[INF_MAXCONN]                        = IST(""),
-	[INF_HARD_MAXCONN]                   = IST(""),
-	[INF_CURR_CONN]                      = IST(""),
-	[INF_CUM_CONN]                       = IST(""),
-	[INF_CUM_REQ]                        = IST(""),
-	[INF_MAX_SSL_CONNS]                  = IST(""),
-	[INF_CURR_SSL_CONNS]                 = IST(""),
-	[INF_CUM_SSL_CONNS]                  = IST(""),
-	[INF_MAXPIPES]                       = IST(""),
-	[INF_PIPES_USED]                     = IST(""),
-	[INF_PIPES_FREE]                     = IST(""),
-	[INF_CONN_RATE]                      = IST(""),
-	[INF_CONN_RATE_LIMIT]                = IST(""),
-	[INF_MAX_CONN_RATE]                  = IST(""),
-	[INF_SESS_RATE]                      = IST(""),
-	[INF_SESS_RATE_LIMIT]                = IST(""),
-	[INF_MAX_SESS_RATE]                  = IST(""),
-	[INF_SSL_RATE]                       = IST(""),
-	[INF_SSL_RATE_LIMIT]                 = IST(""),
-	[INF_MAX_SSL_RATE]                   = IST(""),
-	[INF_SSL_FRONTEND_KEY_RATE]          = IST(""),
-	[INF_SSL_FRONTEND_MAX_KEY_RATE]      = IST(""),
-	[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = IST(""),
-	[INF_SSL_BACKEND_KEY_RATE]           = IST(""),
-	[INF_SSL_BACKEND_MAX_KEY_RATE]       = IST(""),
-	[INF_SSL_CACHE_LOOKUPS]              = IST(""),
-	[INF_SSL_CACHE_MISSES]               = IST(""),
-	[INF_COMPRESS_BPS_IN]                = IST(""),
-	[INF_COMPRESS_BPS_OUT]               = IST(""),
-	[INF_COMPRESS_BPS_RATE_LIM]          = IST(""),
-	[INF_ZLIB_MEM_USAGE]                 = IST(""),
-	[INF_MAX_ZLIB_MEM_USAGE]             = IST(""),
-	[INF_TASKS]                          = IST(""),
-	[INF_RUN_QUEUE]                      = IST(""),
-	[INF_IDLE_PCT]                       = IST(""),
-	[INF_NODE]                           = IST(""),
-	[INF_DESCRIPTION]                    = IST(""),
-	[INF_STOPPING]                       = IST(""),
-	[INF_JOBS]                           = IST(""),
-	[INF_UNSTOPPABLE_JOBS]               = IST(""),
-	[INF_LISTENERS]                      = IST(""),
-	[INF_ACTIVE_PEERS]                   = IST(""),
-	[INF_CONNECTED_PEERS]                = IST(""),
-	[INF_DROPPED_LOGS]                   = IST(""),
-	[INF_BUSY_POLLING]                   = IST(""),
-	[INF_FAILED_RESOLUTIONS]             = IST(""),
-	[INF_TOTAL_BYTES_OUT]                = IST(""),
-	[INF_TOTAL_SPLICED_BYTES_OUT]        = IST(""),
-	[INF_BYTES_OUT_RATE]                 = IST(""),
-	[INF_DEBUG_COMMANDS_ISSUED]          = IST(""),
+	[INF_BUILD_INFO]  = IST(PROMEX_BUILDINFO_LABEL),
 };
 
 /* Specific labels for all stats fields. Empty by default. */
 const struct ist promex_st_metric_labels[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = IST(""),
-	[ST_F_SVNAME]         = IST(""),
-	[ST_F_QCUR]           = IST(""),
-	[ST_F_QMAX]           = IST(""),
-	[ST_F_SCUR]           = IST(""),
-	[ST_F_SMAX]           = IST(""),
-	[ST_F_SLIM]           = IST(""),
-	[ST_F_STOT]           = IST(""),
-	[ST_F_BIN]            = IST(""),
-	[ST_F_BOUT]           = IST(""),
-	[ST_F_DREQ]           = IST(""),
-	[ST_F_DRESP]          = IST(""),
-	[ST_F_EREQ]           = IST(""),
-	[ST_F_ECON]           = IST(""),
-	[ST_F_ERESP]          = IST(""),
-	[ST_F_WRETR]          = IST(""),
-	[ST_F_WREDIS]         = IST(""),
-	[ST_F_STATUS]         = IST(""),
-	[ST_F_WEIGHT]         = IST(""),
-	[ST_F_ACT]            = IST(""),
-	[ST_F_BCK]            = IST(""),
-	[ST_F_CHKFAIL]        = IST(""),
-	[ST_F_CHKDOWN]        = IST(""),
-	[ST_F_LASTCHG]        = IST(""),
-	[ST_F_DOWNTIME]       = IST(""),
-	[ST_F_QLIMIT]         = IST(""),
-	[ST_F_PID]            = IST(""),
-	[ST_F_IID]            = IST(""),
-	[ST_F_SID]            = IST(""),
-	[ST_F_THROTTLE]       = IST(""),
-	[ST_F_LBTOT]          = IST(""),
-	[ST_F_TRACKED]        = IST(""),
-	[ST_F_TYPE]           = IST(""),
-	[ST_F_RATE]           = IST(""),
-	[ST_F_RATE_LIM]       = IST(""),
-	[ST_F_RATE_MAX]       = IST(""),
-	[ST_F_CHECK_STATUS]   = IST(""),
-	[ST_F_CHECK_CODE]     = IST(""),
-	[ST_F_CHECK_DURATION] = IST(""),
-	[ST_F_HRSP_1XX]       = IST("code=\"1xx\""),
-	[ST_F_HRSP_2XX]       = IST("code=\"2xx\""),
-	[ST_F_HRSP_3XX]       = IST("code=\"3xx\""),
-	[ST_F_HRSP_4XX]       = IST("code=\"4xx\""),
-	[ST_F_HRSP_5XX]       = IST("code=\"5xx\""),
-	[ST_F_HRSP_OTHER]     = IST("code=\"other\""),
-	[ST_F_HANAFAIL]       = IST(""),
-	[ST_F_REQ_RATE]       = IST(""),
-	[ST_F_REQ_RATE_MAX]   = IST(""),
-	[ST_F_REQ_TOT]        = IST(""),
-	[ST_F_CLI_ABRT]       = IST(""),
-	[ST_F_SRV_ABRT]       = IST(""),
-	[ST_F_COMP_IN]        = IST(""),
-	[ST_F_COMP_OUT]       = IST(""),
-	[ST_F_COMP_BYP]       = IST(""),
-	[ST_F_COMP_RSP]       = IST(""),
-	[ST_F_LASTSESS]       = IST(""),
-	[ST_F_LAST_CHK]       = IST(""),
-	[ST_F_LAST_AGT]       = IST(""),
-	[ST_F_QTIME]          = IST(""),
-	[ST_F_CTIME]          = IST(""),
-	[ST_F_RTIME]          = IST(""),
-	[ST_F_TTIME]          = IST(""),
-	[ST_F_AGENT_STATUS]   = IST(""),
-	[ST_F_AGENT_CODE]     = IST(""),
-	[ST_F_AGENT_DURATION] = IST(""),
-	[ST_F_CHECK_DESC]     = IST(""),
-	[ST_F_AGENT_DESC]     = IST(""),
-	[ST_F_CHECK_RISE]     = IST(""),
-	[ST_F_CHECK_FALL]     = IST(""),
-	[ST_F_CHECK_HEALTH]   = IST(""),
-	[ST_F_AGENT_RISE]     = IST(""),
-	[ST_F_AGENT_FALL]     = IST(""),
-	[ST_F_AGENT_HEALTH]   = IST(""),
-	[ST_F_ADDR]           = IST(""),
-	[ST_F_COOKIE]         = IST(""),
-	[ST_F_MODE]           = IST(""),
-	[ST_F_ALGO]           = IST(""),
-	[ST_F_CONN_RATE]      = IST(""),
-	[ST_F_CONN_RATE_MAX]  = IST(""),
-	[ST_F_CONN_TOT]       = IST(""),
-	[ST_F_INTERCEPTED]    = IST(""),
-	[ST_F_DCON]           = IST(""),
-	[ST_F_DSES]           = IST(""),
-	[ST_F_WREW]           = IST(""),
-	[ST_F_CONNECT]        = IST(""),
-	[ST_F_REUSE]          = IST(""),
-	[ST_F_CACHE_LOOKUPS]  = IST(""),
-	[ST_F_CACHE_HITS]     = IST(""),
-	[ST_F_IDLE_CONN_CUR]  = IST(""),
-	[ST_F_SAFE_CONN_CUR]  = IST(""),
-	[ST_F_USED_CONN_CUR]  = IST(""),
-	[ST_F_NEED_CONN_EST]  = IST(""),
+	[ST_F_HRSP_1XX]   = IST("code=\"1xx\""),
+	[ST_F_HRSP_2XX]   = IST("code=\"2xx\""),
+	[ST_F_HRSP_3XX]   = IST("code=\"3xx\""),
+	[ST_F_HRSP_4XX]   = IST("code=\"4xx\""),
+	[ST_F_HRSP_5XX]   = IST("code=\"5xx\""),
+	[ST_F_HRSP_OTHER] = IST("code=\"other\""),
 };
 
 /* Type for all info fields. "untyped" is used for unsupported field. */
-- 
2.29.2

>From c53078675bab24fbefcbfa1f7ad8f8c95bd04d72 Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Wed, 20 Jan 2021 15:02:50 +0100
Subject: [PATCH 2/4] MINOR: contrib/prometheus-exporter: Split the
 PROMEX_FL_STATS_METRIC flag

PROMEX_FL_STATS_METRIC flag is splitted in 3 flags to easily identify the
processed entity type (frontend, backend or server). Thus, now we are using
PROMEX_FL_FRONT_METRIC, PROMEX_FL_BACK_METRIC or PROMEX_FL_SRV_METRIC. These
flags will be used to know if a metric is defined and must be exported for a
given entity type.
---
 .../prometheus-exporter/service-prometheus.c  | 24 +++++++++++--------
 1 file changed, 14 insertions(+), 10 deletions(-)

diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
index 81f5ba0db..bad4be8ea 100644
--- a/contrib/prometheus-exporter/service-prometheus.c
+++ b/contrib/prometheus-exporter/service-prometheus.c
@@ -63,12 +63,14 @@ enum {
 /* Prometheus exporter flags (appctx->ctx.stats.flags) */
 #define PROMEX_FL_METRIC_HDR    0x00000001
 #define PROMEX_FL_INFO_METRIC   0x00000002
-#define PROMEX_FL_STATS_METRIC  0x00000004
-#define PROMEX_FL_SCOPE_GLOBAL  0x00000008
-#define PROMEX_FL_SCOPE_FRONT   0x00000010
-#define PROMEX_FL_SCOPE_BACK    0x00000020
-#define PROMEX_FL_SCOPE_SERVER  0x00000040
-#define PROMEX_FL_NO_MAINT_SRV  0x00000080
+#define PROMEX_FL_FRONT_METRIC  0x00000004
+#define PROMEX_FL_BACK_METRIC   0x00000008
+#define PROMEX_FL_SRV_METRIC    0x00000010
+#define PROMEX_FL_SCOPE_GLOBAL  0x00000020
+#define PROMEX_FL_SCOPE_FRONT   0x00000040
+#define PROMEX_FL_SCOPE_BACK    0x00000080
+#define PROMEX_FL_SCOPE_SERVER  0x00000100
+#define PROMEX_FL_NO_MAINT_SRV  0x00000200
 
 #define PROMEX_FL_SCOPE_ALL (PROMEX_FL_SCOPE_GLOBAL|PROMEX_FL_SCOPE_FRONT|PROMEX_FL_SCOPE_BACK|PROMEX_FL_SCOPE_SERVER)
 
@@ -1762,7 +1764,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 			appctx->ctx.stats.obj1 = proxies_list;
 			appctx->ctx.stats.obj2 = NULL;
 			appctx->ctx.stats.flags &= ~PROMEX_FL_INFO_METRIC;
-			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_STATS_METRIC);
+			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_FRONT_METRIC);
 			appctx->st2 = promex_front_metrics[ST_F_PXNAME];
 			appctx->st1 = PROMEX_DUMPER_FRONT;
 			/* fall through */
@@ -1779,7 +1781,8 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 
 			appctx->ctx.stats.obj1 = proxies_list;
 			appctx->ctx.stats.obj2 = NULL;
-			appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
+			appctx->ctx.stats.flags &= ~PROMEX_FL_FRONT_METRIC;
+			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_BACK_METRIC);
 			appctx->st2 = promex_back_metrics[ST_F_PXNAME];
 			appctx->st1 = PROMEX_DUMPER_BACK;
 			/* fall through */
@@ -1796,7 +1799,8 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 
 			appctx->ctx.stats.obj1 = proxies_list;
 			appctx->ctx.stats.obj2 = (appctx->ctx.stats.obj1 ? ((struct proxy *)appctx->ctx.stats.obj1)->srv : NULL);
-			appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
+			appctx->ctx.stats.flags &= ~PROMEX_FL_BACK_METRIC;
+			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_SRV_METRIC);
 			appctx->st2 = promex_srv_metrics[ST_F_PXNAME];
 			appctx->st1 = PROMEX_DUMPER_SRV;
 			/* fall through */
@@ -1813,7 +1817,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 
 			appctx->ctx.stats.obj1 = NULL;
 			appctx->ctx.stats.obj2 = NULL;
-			appctx->ctx.stats.flags &= ~(PROMEX_FL_METRIC_HDR|PROMEX_FL_INFO_METRIC|PROMEX_FL_STATS_METRIC);
+			appctx->ctx.stats.flags &= ~(PROMEX_FL_METRIC_HDR|PROMEX_FL_SRV_METRIC);
 			appctx->st2 = 0;
 			appctx->st1 = PROMEX_DUMPER_DONE;
 			/* fall through */
-- 
2.29.2

>From 26111899589f517a5656573260c99187fb14841f Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Wed, 20 Jan 2021 15:19:12 +0100
Subject: [PATCH 3/4] MINOR: contrib/prometheus-exporter: Add promex_metric
 struct defining a metric

This structure will be used to define a Prometheus metric, i.e its name, its
type (gauge or counter) and its flags. The flags will be used to know for
which entities the metric is defined (global, frontend, backend and/or server).
---
 contrib/prometheus-exporter/service-prometheus.c | 13 +++++++++++++
 1 file changed, 13 insertions(+)

diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
index bad4be8ea..2dcbb9d7e 100644
--- a/contrib/prometheus-exporter/service-prometheus.c
+++ b/contrib/prometheus-exporter/service-prometheus.c
@@ -74,6 +74,12 @@ enum {
 
 #define PROMEX_FL_SCOPE_ALL (PROMEX_FL_SCOPE_GLOBAL|PROMEX_FL_SCOPE_FRONT|PROMEX_FL_SCOPE_BACK|PROMEX_FL_SCOPE_SERVER)
 
+/* Promtheus metric type (gauge or counter) */
+enum promex_mt_type {
+	PROMEX_MT_GAUGE   = 1,
+	PROMEX_MT_COUNTER = 2,
+};
+
 /* The max length for metrics name. It is a hard limit but it should be
  * enough.
  */
@@ -89,6 +95,13 @@ enum {
 #define PROMEX_VERSION_LABEL "version=\"" HAPROXY_VERSION "\""
 #define PROMEX_BUILDINFO_LABEL PROMEX_VERSION_LABEL
 
+/* Describe a prometheus metric */
+struct promex_metric {
+	const struct ist    n;      /* The metric name */
+	enum promex_mt_type type;   /* The metric type (gauge or counter) */
+	unsigned int        flags;  /* PROMEX_FL_* flags */
+};
+
 /* Matrix used to dump global metrics. Each metric points to the next one to be
  * processed or 0 to stop the dump. */
 const int promex_global_metrics[INF_TOTAL_FIELDS] = {
-- 
2.29.2

>From db99dbd8ddeebadacaae58a7a21de628295fc36b Mon Sep 17 00:00:00 2001
From: Christopher Faulet <cfau...@haproxy.com>
Date: Wed, 20 Jan 2021 15:20:53 +0100
Subject: [PATCH 4/4] MEDIUM: contrib/prometheus-exporter: Rework matrices
 defining Promex metrics

The global and stats matrices are replaced by a simpler ones. Now we have
only 2 arrays of prometheus metrics. Their flags are used to match on the
entity type. This simplify a bit the metrics definition. For now, labels and
descriptions are still outside of these arrays, because the labels must be
reworked to be more dynamic and the descrptions must be replaced by stats
ones as far as possible.
---
 .../prometheus-exporter/service-prometheus.c  | 1225 +++++------------
 1 file changed, 333 insertions(+), 892 deletions(-)

diff --git a/contrib/prometheus-exporter/service-prometheus.c b/contrib/prometheus-exporter/service-prometheus.c
index 2dcbb9d7e..3d27814e7 100644
--- a/contrib/prometheus-exporter/service-prometheus.c
+++ b/contrib/prometheus-exporter/service-prometheus.c
@@ -102,562 +102,178 @@ struct promex_metric {
 	unsigned int        flags;  /* PROMEX_FL_* flags */
 };
 
-/* Matrix used to dump global metrics. Each metric points to the next one to be
- * processed or 0 to stop the dump. */
-const int promex_global_metrics[INF_TOTAL_FIELDS] = {
-	[INF_NAME]                           = INF_BUILD_INFO,
-	[INF_VERSION]                        = 0,
-	[INF_RELEASE_DATE]                   = 0,
-	[INF_BUILD_INFO]                     = INF_NBTHREAD,
-	[INF_NBTHREAD]                       = INF_NBPROC,
-	[INF_NBPROC]                         = INF_PROCESS_NUM,
-	[INF_PROCESS_NUM]                    = INF_UPTIME_SEC,
-	[INF_PID]                            = 0,
-	[INF_UPTIME]                         = 0,
-	[INF_UPTIME_SEC]                     = INF_START_TIME_SEC,
-	[INF_START_TIME_SEC]                 = INF_MEMMAX_BYTES,
-	[INF_MEMMAX_BYTES]                   = INF_POOL_ALLOC_BYTES,
-	[INF_POOL_ALLOC_BYTES]               = INF_POOL_USED_BYTES,
-	[INF_POOL_USED_BYTES]                = INF_POOL_FAILED,
-	[INF_POOL_FAILED]                    = INF_ULIMIT_N,
-	[INF_ULIMIT_N]                       = INF_MAXSOCK,
-	[INF_MAXSOCK]                        = INF_MAXCONN,
-	[INF_MAXCONN]                        = INF_HARD_MAXCONN,
-	[INF_HARD_MAXCONN]                   = INF_CURR_CONN,
-	[INF_CURR_CONN]                      = INF_CUM_CONN,
-	[INF_CUM_CONN]                       = INF_CUM_REQ,
-	[INF_CUM_REQ]                        = INF_MAX_SSL_CONNS,
-	[INF_MAX_SSL_CONNS]                  = INF_CURR_SSL_CONNS,
-	[INF_CURR_SSL_CONNS]                 = INF_CUM_SSL_CONNS,
-	[INF_CUM_SSL_CONNS]                  = INF_MAXPIPES,
-	[INF_MAXPIPES]                       = INF_PIPES_USED,
-	[INF_PIPES_USED]                     = INF_PIPES_FREE,
-	[INF_PIPES_FREE]                     = INF_CONN_RATE,
-	[INF_CONN_RATE]                      = INF_CONN_RATE_LIMIT,
-	[INF_CONN_RATE_LIMIT]                = INF_MAX_CONN_RATE,
-	[INF_MAX_CONN_RATE]                  = INF_SESS_RATE,
-	[INF_SESS_RATE]                      = INF_SESS_RATE_LIMIT,
-	[INF_SESS_RATE_LIMIT]                = INF_MAX_SESS_RATE,
-	[INF_MAX_SESS_RATE]                  = INF_SSL_RATE,
-	[INF_SSL_RATE]                       = INF_SSL_RATE_LIMIT,
-	[INF_SSL_RATE_LIMIT]                 = INF_MAX_SSL_RATE,
-	[INF_MAX_SSL_RATE]                   = INF_SSL_FRONTEND_KEY_RATE,
-	[INF_SSL_FRONTEND_KEY_RATE]          = INF_SSL_FRONTEND_MAX_KEY_RATE,
-	[INF_SSL_FRONTEND_MAX_KEY_RATE]      = INF_SSL_FRONTEND_SESSION_REUSE_PCT,
-	[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = INF_SSL_BACKEND_KEY_RATE,
-	[INF_SSL_BACKEND_KEY_RATE]           = INF_SSL_BACKEND_MAX_KEY_RATE,
-	[INF_SSL_BACKEND_MAX_KEY_RATE]       = INF_SSL_CACHE_LOOKUPS,
-	[INF_SSL_CACHE_LOOKUPS]              = INF_SSL_CACHE_MISSES,
-	[INF_SSL_CACHE_MISSES]               = INF_COMPRESS_BPS_IN,
-	[INF_COMPRESS_BPS_IN]                = INF_COMPRESS_BPS_OUT,
-	[INF_COMPRESS_BPS_OUT]               = INF_COMPRESS_BPS_RATE_LIM,
-	[INF_COMPRESS_BPS_RATE_LIM]          = INF_ZLIB_MEM_USAGE,
-	[INF_ZLIB_MEM_USAGE]                 = INF_MAX_ZLIB_MEM_USAGE,
-	[INF_MAX_ZLIB_MEM_USAGE]             = INF_TASKS,
-	[INF_TASKS]                          = INF_RUN_QUEUE,
-	[INF_RUN_QUEUE]                      = INF_IDLE_PCT,
-	[INF_IDLE_PCT]                       = INF_STOPPING,
-	[INF_NODE]                           = 0,
-	[INF_DESCRIPTION]                    = 0,
-	[INF_STOPPING]                       = INF_JOBS,
-	[INF_JOBS]                           = INF_UNSTOPPABLE_JOBS,
-	[INF_UNSTOPPABLE_JOBS]               = INF_LISTENERS,
-	[INF_LISTENERS]                      = INF_ACTIVE_PEERS,
-	[INF_ACTIVE_PEERS]                   = INF_CONNECTED_PEERS,
-	[INF_CONNECTED_PEERS]                = INF_DROPPED_LOGS,
-	[INF_DROPPED_LOGS]                   = INF_BUSY_POLLING,
-	[INF_BUSY_POLLING]                   = INF_FAILED_RESOLUTIONS,
-	[INF_FAILED_RESOLUTIONS]             = INF_TOTAL_BYTES_OUT,
-	[INF_TOTAL_BYTES_OUT]                = INF_TOTAL_SPLICED_BYTES_OUT,
-	[INF_TOTAL_SPLICED_BYTES_OUT]        = INF_BYTES_OUT_RATE,
-	[INF_BYTES_OUT_RATE]                 = 0,
-	[INF_DEBUG_COMMANDS_ISSUED]          = 0,
+/* Global metrics  */
+const struct promex_metric promex_global_metrics[INF_TOTAL_FIELDS] = {
+	//[INF_NAME]                           ignored
+	//[INF_VERSION],                       ignored
+	//[INF_RELEASE_DATE]                   ignored
+	[INF_BUILD_INFO]                     = { .n = IST("build_info"),                    .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_NBTHREAD]                       = { .n = IST("nbthread"),                      .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_NBPROC]                         = { .n = IST("nbproc"),                        .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_PROCESS_NUM]                    = { .n = IST("relative_process_id"),           .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	//[INF_PID]                            ignored
+	//[INF_UPTIME]                         ignored
+	[INF_UPTIME_SEC]                     = { .n = IST("uptime_seconds"),                .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_START_TIME_SEC]                 = { .n = IST("start_time_seconds"),            .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MEMMAX_BYTES]                   = { .n = IST("max_memory_bytes"),              .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_POOL_ALLOC_BYTES]               = { .n = IST("pool_allocated_bytes"),          .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_POOL_USED_BYTES]                = { .n = IST("pool_used_bytes"),               .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_POOL_FAILED]                    = { .n = IST("pool_failures_total"),           .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_ULIMIT_N]                       = { .n = IST("max_fds"),                       .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAXSOCK]                        = { .n = IST("max_sockets"),                   .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAXCONN]                        = { .n = IST("max_connections"),               .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_HARD_MAXCONN]                   = { .n = IST("hard_max_connections"),          .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CURR_CONN]                      = { .n = IST("current_connections"),           .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CUM_CONN]                       = { .n = IST("connections_total"),             .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CUM_REQ]                        = { .n = IST("requests_total"),                .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAX_SSL_CONNS]                  = { .n = IST("max_ssl_connections"),           .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CURR_SSL_CONNS]                 = { .n = IST("current_ssl_connections"),       .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CUM_SSL_CONNS]                  = { .n = IST("ssl_connections_total"),         .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAXPIPES]                       = { .n = IST("max_pipes"),                     .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_PIPES_USED]                     = { .n = IST("pipes_used_total"),              .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_PIPES_FREE]                     = { .n = IST("pipes_free_total"),              .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CONN_RATE]                      = { .n = IST("current_connection_rate"),       .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CONN_RATE_LIMIT]                = { .n = IST("limit_connection_rate"),         .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAX_CONN_RATE]                  = { .n = IST("max_connection_rate"),           .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SESS_RATE]                      = { .n = IST("current_session_rate"),          .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SESS_RATE_LIMIT]                = { .n = IST("limit_session_rate"),            .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAX_SESS_RATE]                  = { .n = IST("max_session_rate"),              .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_RATE]                       = { .n = IST("current_ssl_rate"),              .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_RATE_LIMIT]                 = { .n = IST("limit_ssl_rate"),                .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAX_SSL_RATE]                   = { .n = IST("max_ssl_rate"),                  .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_FRONTEND_KEY_RATE]          = { .n = IST("current_frontend_ssl_key_rate"), .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_FRONTEND_MAX_KEY_RATE]      = { .n = IST("max_frontend_ssl_key_rate"),     .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = { .n = IST("frontend_ssl_reuse"),            .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_BACKEND_KEY_RATE]           = { .n = IST("current_backend_ssl_key_rate"),  .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_BACKEND_MAX_KEY_RATE]       = { .n = IST("max_backend_ssl_key_rate"),      .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_CACHE_LOOKUPS]              = { .n = IST("ssl_cache_lookups_total"),       .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_SSL_CACHE_MISSES]               = { .n = IST("ssl_cache_misses_total"),        .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_COMPRESS_BPS_IN]                = { .n = IST("http_comp_bytes_in_total"),      .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_COMPRESS_BPS_OUT]               = { .n = IST("http_comp_bytes_out_total"),     .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_COMPRESS_BPS_RATE_LIM]          = { .n = IST("limit_http_comp"),               .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_ZLIB_MEM_USAGE]                 = { .n = IST("current_zlib_memory"),           .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_MAX_ZLIB_MEM_USAGE]             = { .n = IST("max_zlib_memory"),               .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_TASKS]                          = { .n = IST("current_tasks"),                 .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_RUN_QUEUE]                      = { .n = IST("current_run_queue"),             .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_IDLE_PCT]                       = { .n = IST("idle_time_percent"),             .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	//[INF_NODE]                           ignored
+	//[INF_DESCRIPTION]                    ignored
+	[INF_STOPPING]                       = { .n = IST("stopping"),                      .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_JOBS]                           = { .n = IST("jobs"),                          .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_UNSTOPPABLE_JOBS]               = { .n = IST("unstoppable_jobs"),              .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_LISTENERS]                      = { .n = IST("listeners"),                     .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_ACTIVE_PEERS]                   = { .n = IST("active_peers"),                  .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_CONNECTED_PEERS]                = { .n = IST("connected_peers"),               .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_DROPPED_LOGS]                   = { .n = IST("dropped_logs_total"),            .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_BUSY_POLLING]                   = { .n = IST("busy_polling_enabled"),          .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	[INF_FAILED_RESOLUTIONS]             = { .n = IST("failed_resolutions"),            .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_TOTAL_BYTES_OUT]                = { .n = IST("bytes_out_total"),               .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_TOTAL_SPLICED_BYTES_OUT]        = { .n = IST("spliced_bytes_out_total"),       .type = PROMEX_MT_COUNTER, .flags = PROMEX_FL_INFO_METRIC },
+	[INF_BYTES_OUT_RATE]                 = { .n = IST("bytes_out_rate"),                .type = PROMEX_MT_GAUGE,   .flags = PROMEX_FL_INFO_METRIC },
+	//[INF_DEBUG_COMMANDS_ISSUED]          ignored
 };
 
-/* Matrix used to dump frontend metrics. Each metric points to the next one to be
- * processed or 0 to stop the dump. */
-const int promex_front_metrics[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = ST_F_STATUS,
-	[ST_F_SVNAME]         = 0,
-	[ST_F_QCUR]           = 0,
-	[ST_F_QMAX]           = 0,
-	[ST_F_SCUR]           = ST_F_SMAX,
-	[ST_F_SMAX]           = ST_F_SLIM,
-	[ST_F_SLIM]           = ST_F_STOT,
-	[ST_F_STOT]           = ST_F_RATE_LIM,
-	[ST_F_BIN]            = ST_F_BOUT,
-	[ST_F_BOUT]           = ST_F_DREQ,
-	[ST_F_DREQ]           = ST_F_DRESP,
-	[ST_F_DRESP]          = ST_F_EREQ,
-	[ST_F_EREQ]           = ST_F_DCON,
-	[ST_F_ECON]           = 0,
-	[ST_F_ERESP]          = 0,
-	[ST_F_WRETR]          = 0,
-	[ST_F_WREDIS]         = 0,
-	[ST_F_STATUS]         = ST_F_SCUR,
-	[ST_F_WEIGHT]         = 0,
-	[ST_F_ACT]            = 0,
-	[ST_F_BCK]            = 0,
-	[ST_F_CHKFAIL]        = 0,
-	[ST_F_CHKDOWN]        = 0,
-	[ST_F_LASTCHG]        = 0,
-	[ST_F_DOWNTIME]       = 0,
-	[ST_F_QLIMIT]         = 0,
-	[ST_F_PID]            = 0,
-	[ST_F_IID]            = 0,
-	[ST_F_SID]            = 0,
-	[ST_F_THROTTLE]       = 0,
-	[ST_F_LBTOT]          = 0,
-	[ST_F_TRACKED]        = 0,
-	[ST_F_TYPE]           = 0,
-	[ST_F_RATE]           = 0,
-	[ST_F_RATE_LIM]       = ST_F_RATE_MAX,
-	[ST_F_RATE_MAX]       = ST_F_CONN_RATE_MAX,
-	[ST_F_CHECK_STATUS]   = 0,
-	[ST_F_CHECK_CODE]     = 0,
-	[ST_F_CHECK_DURATION] = 0,
-	[ST_F_HRSP_1XX]       = ST_F_HRSP_2XX,
-	[ST_F_HRSP_2XX]       = ST_F_HRSP_3XX,
-	[ST_F_HRSP_3XX]       = ST_F_HRSP_4XX,
-	[ST_F_HRSP_4XX]       = ST_F_HRSP_5XX,
-	[ST_F_HRSP_5XX]       = ST_F_HRSP_OTHER,
-	[ST_F_HRSP_OTHER]     = ST_F_INTERCEPTED,
-	[ST_F_HANAFAIL]       = 0,
-	[ST_F_REQ_RATE]       = 0,
-	[ST_F_REQ_RATE_MAX]   = ST_F_REQ_TOT,
-	[ST_F_REQ_TOT]        = ST_F_HRSP_1XX,
-	[ST_F_CLI_ABRT]       = 0,
-	[ST_F_SRV_ABRT]       = 0,
-	[ST_F_COMP_IN]        = ST_F_COMP_OUT,
-	[ST_F_COMP_OUT]       = ST_F_COMP_BYP,
-	[ST_F_COMP_BYP]       = ST_F_COMP_RSP,
-	[ST_F_COMP_RSP]       = 0,
-	[ST_F_LASTSESS]       = 0,
-	[ST_F_LAST_CHK]       = 0,
-	[ST_F_LAST_AGT]       = 0,
-	[ST_F_QTIME]          = 0,
-	[ST_F_CTIME]          = 0,
-	[ST_F_RTIME]          = 0,
-	[ST_F_TTIME]          = 0,
-	[ST_F_AGENT_STATUS]   = 0,
-	[ST_F_AGENT_CODE]     = 0,
-	[ST_F_AGENT_DURATION] = 0,
-	[ST_F_CHECK_DESC]     = 0,
-	[ST_F_AGENT_DESC]     = 0,
-	[ST_F_CHECK_RISE]     = 0,
-	[ST_F_CHECK_FALL]     = 0,
-	[ST_F_CHECK_HEALTH]   = 0,
-	[ST_F_AGENT_RISE]     = 0,
-	[ST_F_AGENT_FALL]     = 0,
-	[ST_F_AGENT_HEALTH]   = 0,
-	[ST_F_ADDR]           = 0,
-	[ST_F_COOKIE]         = 0,
-	[ST_F_MODE]           = 0,
-	[ST_F_ALGO]           = 0,
-	[ST_F_CONN_RATE]      = 0,
-	[ST_F_CONN_RATE_MAX]  = ST_F_CONN_TOT,
-	[ST_F_CONN_TOT]       = ST_F_BIN,
-	[ST_F_INTERCEPTED]    = ST_F_CACHE_LOOKUPS,
-	[ST_F_DCON]           = ST_F_DSES,
-	[ST_F_DSES]           = ST_F_WREW,
-	[ST_F_WREW]           = ST_F_EINT,
-	[ST_F_CONNECT]        = 0,
-	[ST_F_REUSE]          = 0,
-	[ST_F_CACHE_LOOKUPS]  = ST_F_CACHE_HITS,
-	[ST_F_CACHE_HITS]     = ST_F_COMP_IN,
-	[ST_F_SRV_ICUR]       = 0,
-	[ST_F_SRV_ILIM]       = 0,
-	[ST_F_QT_MAX]         = 0,
-	[ST_F_CT_MAX]         = 0,
-	[ST_F_RT_MAX]         = 0,
-	[ST_F_TT_MAX]         = 0,
-	[ST_F_EINT]           = ST_F_REQ_RATE_MAX,
-	[ST_F_IDLE_CONN_CUR]  = 0,
-	[ST_F_SAFE_CONN_CUR]  = 0,
-	[ST_F_USED_CONN_CUR]  = 0,
-	[ST_F_NEED_CONN_EST]  = 0,
-};
-
-/* Matrix used to dump backend metrics. Each metric points to the next one to be
- * processed or 0 to stop the dump. */
-const int promex_back_metrics[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = ST_F_STATUS,
-	[ST_F_SVNAME]         = 0,
-	[ST_F_QCUR]           = ST_F_QMAX,
-	[ST_F_QMAX]           = ST_F_CONNECT,
-	[ST_F_SCUR]           = ST_F_SMAX,
-	[ST_F_SMAX]           = ST_F_SLIM,
-	[ST_F_SLIM]           = ST_F_STOT,
-	[ST_F_STOT]           = ST_F_RATE_MAX,
-	[ST_F_BIN]            = ST_F_BOUT,
-	[ST_F_BOUT]           = ST_F_QTIME,
-	[ST_F_DREQ]           = ST_F_DRESP,
-	[ST_F_DRESP]          = ST_F_ECON,
-	[ST_F_EREQ]           = 0,
-	[ST_F_ECON]           = ST_F_ERESP,
-	[ST_F_ERESP]          = ST_F_WRETR,
-	[ST_F_WRETR]          = ST_F_WREDIS,
-	[ST_F_WREDIS]         = ST_F_WREW,
-	[ST_F_STATUS]         = ST_F_SCUR,
-	[ST_F_WEIGHT]         = ST_F_ACT,
-	[ST_F_ACT]            = ST_F_BCK,
-	[ST_F_BCK]            = ST_F_CHKDOWN,
-	[ST_F_CHKFAIL]        = 0,
-	[ST_F_CHKDOWN]        = ST_F_LASTCHG,
-	[ST_F_LASTCHG]        = ST_F_DOWNTIME,
-	[ST_F_DOWNTIME]       = ST_F_LBTOT,
-	[ST_F_QLIMIT]         = 0,
-	[ST_F_PID]            = 0,
-	[ST_F_IID]            = 0,
-	[ST_F_SID]            = 0,
-	[ST_F_THROTTLE]       = 0,
-	[ST_F_LBTOT]          = ST_F_REQ_TOT,
-	[ST_F_TRACKED]        = 9,
-	[ST_F_TYPE]           = 0,
-	[ST_F_RATE]           = 0,
-	[ST_F_RATE_LIM]       = 0,
-	[ST_F_RATE_MAX]       = ST_F_LASTSESS,
-	[ST_F_CHECK_STATUS]   = 0,
-	[ST_F_CHECK_CODE]     = 0,
-	[ST_F_CHECK_DURATION] = 0,
-	[ST_F_HRSP_1XX]       = ST_F_HRSP_2XX,
-	[ST_F_HRSP_2XX]       = ST_F_HRSP_3XX,
-	[ST_F_HRSP_3XX]       = ST_F_HRSP_4XX,
-	[ST_F_HRSP_4XX]       = ST_F_HRSP_5XX,
-	[ST_F_HRSP_5XX]       = ST_F_HRSP_OTHER,
-	[ST_F_HRSP_OTHER]     = ST_F_CACHE_LOOKUPS,
-	[ST_F_HANAFAIL]       = 0,
-	[ST_F_REQ_RATE]       = 0,
-	[ST_F_REQ_RATE_MAX]   = 0,
-	[ST_F_REQ_TOT]        = ST_F_HRSP_1XX,
-	[ST_F_CLI_ABRT]       = ST_F_SRV_ABRT,
-	[ST_F_SRV_ABRT]       = ST_F_WEIGHT,
-	[ST_F_COMP_IN]        = ST_F_COMP_OUT,
-	[ST_F_COMP_OUT]       = ST_F_COMP_BYP,
-	[ST_F_COMP_BYP]       = ST_F_COMP_RSP,
-	[ST_F_COMP_RSP]       = 0,
-	[ST_F_LASTSESS]       = ST_F_QCUR,
-	[ST_F_LAST_CHK]       = 0,
-	[ST_F_LAST_AGT]       = 0,
-	[ST_F_QTIME]          = ST_F_CTIME,
-	[ST_F_CTIME]          = ST_F_RTIME,
-	[ST_F_RTIME]          = ST_F_TTIME,
-	[ST_F_TTIME]          = ST_F_QT_MAX,
-	[ST_F_AGENT_STATUS]   = 0,
-	[ST_F_AGENT_CODE]     = 0,
-	[ST_F_AGENT_DURATION] = 0,
-	[ST_F_CHECK_DESC]     = 0,
-	[ST_F_AGENT_DESC]     = 0,
-	[ST_F_CHECK_RISE]     = 0,
-	[ST_F_CHECK_FALL]     = 0,
-	[ST_F_CHECK_HEALTH]   = 0,
-	[ST_F_AGENT_RISE]     = 0,
-	[ST_F_AGENT_FALL]     = 0,
-	[ST_F_AGENT_HEALTH]   = 0,
-	[ST_F_ADDR]           = 0,
-	[ST_F_COOKIE]         = 0,
-	[ST_F_MODE]           = 0,
-	[ST_F_ALGO]           = 0,
-	[ST_F_CONN_RATE]      = 0,
-	[ST_F_CONN_RATE_MAX]  = 0,
-	[ST_F_CONN_TOT]       = 0,
-	[ST_F_INTERCEPTED]    = 0,
-	[ST_F_DCON]           = 0,
-	[ST_F_DSES]           = 0,
-	[ST_F_WREW]           = ST_F_EINT,
-	[ST_F_CONNECT]        = ST_F_REUSE,
-	[ST_F_REUSE]          = ST_F_BIN,
-	[ST_F_CACHE_LOOKUPS]  = ST_F_CACHE_HITS,
-	[ST_F_CACHE_HITS]     = ST_F_COMP_IN,
-	[ST_F_SRV_ICUR]       = 0,
-	[ST_F_SRV_ILIM]       = 0,
-	[ST_F_QT_MAX]         = ST_F_CT_MAX,
-	[ST_F_CT_MAX]         = ST_F_RT_MAX,
-	[ST_F_RT_MAX]         = ST_F_TT_MAX,
-	[ST_F_TT_MAX]         = ST_F_DREQ,
-	[ST_F_EINT]           = ST_F_CLI_ABRT,
-	[ST_F_IDLE_CONN_CUR]  = 0,
-	[ST_F_SAFE_CONN_CUR]  = 0,
-	[ST_F_USED_CONN_CUR]  = 0,
-	[ST_F_NEED_CONN_EST]  = 0,
-};
-
-/* Matrix used to dump server metrics. Each metric points to the next one to be
- * processed or 0 to stop the dump. */
-const int promex_srv_metrics[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = ST_F_STATUS,
-	[ST_F_SVNAME]         = 0,
-	[ST_F_QCUR]           = ST_F_QMAX,
-	[ST_F_QMAX]           = ST_F_QLIMIT,
-	[ST_F_SCUR]           = ST_F_SMAX,
-	[ST_F_SMAX]           = ST_F_SLIM,
-	[ST_F_SLIM]           = ST_F_STOT,
-	[ST_F_STOT]           = ST_F_RATE_MAX,
-	[ST_F_BIN]            = ST_F_BOUT,
-	[ST_F_BOUT]           = ST_F_QTIME,
-	[ST_F_DREQ]           = 0,
-	[ST_F_DRESP]          = ST_F_ECON,
-	[ST_F_EREQ]           = 0,
-	[ST_F_ECON]           = ST_F_ERESP,
-	[ST_F_ERESP]          = ST_F_WRETR,
-	[ST_F_WRETR]          = ST_F_WREDIS,
-	[ST_F_WREDIS]         = ST_F_WREW,
-	[ST_F_STATUS]         = ST_F_SCUR,
-	[ST_F_WEIGHT]         = ST_F_CHECK_STATUS,
-	[ST_F_ACT]            = 0,
-	[ST_F_BCK]            = 0,
-	[ST_F_CHKFAIL]        = ST_F_CHKDOWN,
-	[ST_F_CHKDOWN]        = ST_F_DOWNTIME,
-	[ST_F_LASTCHG]        = ST_F_THROTTLE,
-	[ST_F_DOWNTIME]       = ST_F_LASTCHG,
-	[ST_F_QLIMIT]         = ST_F_BIN,
-	[ST_F_PID]            = 0,
-	[ST_F_IID]            = 0,
-	[ST_F_SID]            = 0,
-	[ST_F_THROTTLE]       = ST_F_LBTOT,
-	[ST_F_LBTOT]          = ST_F_HRSP_1XX,
-	[ST_F_TRACKED]        = 0,
-	[ST_F_TYPE]           = 0,
-	[ST_F_RATE]           = 0,
-	[ST_F_RATE_LIM]       = 0,
-	[ST_F_RATE_MAX]       = ST_F_LASTSESS,
-	[ST_F_CHECK_STATUS]   = ST_F_CHECK_CODE,
-	[ST_F_CHECK_CODE]     = ST_F_CHECK_DURATION,
-	[ST_F_CHECK_DURATION] = ST_F_CHKFAIL,
-	[ST_F_HRSP_1XX]       = ST_F_HRSP_2XX,
-	[ST_F_HRSP_2XX]       = ST_F_HRSP_3XX,
-	[ST_F_HRSP_3XX]       = ST_F_HRSP_4XX,
-	[ST_F_HRSP_4XX]       = ST_F_HRSP_5XX,
-	[ST_F_HRSP_5XX]       = ST_F_HRSP_OTHER,
-	[ST_F_HRSP_OTHER]     = ST_F_SRV_ICUR,
-	[ST_F_HANAFAIL]       = 0,
-	[ST_F_REQ_RATE]       = 0,
-	[ST_F_REQ_RATE_MAX]   = 0,
-	[ST_F_REQ_TOT]        = 0,
-	[ST_F_CLI_ABRT]       = ST_F_SRV_ABRT,
-	[ST_F_SRV_ABRT]       = ST_F_WEIGHT,
-	[ST_F_COMP_IN]        = 0,
-	[ST_F_COMP_OUT]       = 0,
-	[ST_F_COMP_BYP]       = 0,
-	[ST_F_COMP_RSP]       = 0,
-	[ST_F_LASTSESS]       = ST_F_QCUR,
-	[ST_F_LAST_CHK]       = 0,
-	[ST_F_LAST_AGT]       = 0,
-	[ST_F_QTIME]          = ST_F_CTIME,
-	[ST_F_CTIME]          = ST_F_RTIME,
-	[ST_F_RTIME]          = ST_F_TTIME,
-	[ST_F_TTIME]          = ST_F_QT_MAX,
-	[ST_F_AGENT_STATUS]   = 0,
-	[ST_F_AGENT_CODE]     = 0,
-	[ST_F_AGENT_DURATION] = 0,
-	[ST_F_CHECK_DESC]     = 0,
-	[ST_F_AGENT_DESC]     = 0,
-	[ST_F_CHECK_RISE]     = 0,
-	[ST_F_CHECK_FALL]     = 0,
-	[ST_F_CHECK_HEALTH]   = 0,
-	[ST_F_AGENT_RISE]     = 0,
-	[ST_F_AGENT_FALL]     = 0,
-	[ST_F_AGENT_HEALTH]   = 0,
-	[ST_F_ADDR]           = 0,
-	[ST_F_COOKIE]         = 0,
-	[ST_F_MODE]           = 0,
-	[ST_F_ALGO]           = 0,
-	[ST_F_CONN_RATE]      = 0,
-	[ST_F_CONN_RATE_MAX]  = 0,
-	[ST_F_CONN_TOT]       = 0,
-	[ST_F_INTERCEPTED]    = 0,
-	[ST_F_DCON]           = 0,
-	[ST_F_DSES]           = 0,
-	[ST_F_WREW]           = ST_F_EINT,
-	[ST_F_CONNECT]        = ST_F_REUSE,
-	[ST_F_REUSE]          = ST_F_DRESP,
-	[ST_F_CACHE_LOOKUPS]  = 0,
-	[ST_F_CACHE_HITS]     = 0,
-	[ST_F_SRV_ICUR]       = ST_F_SRV_ILIM,
-	[ST_F_SRV_ILIM]       = ST_F_IDLE_CONN_CUR,
-	[ST_F_QT_MAX]         = ST_F_CT_MAX,
-	[ST_F_CT_MAX]         = ST_F_RT_MAX,
-	[ST_F_RT_MAX]         = ST_F_TT_MAX,
-	[ST_F_TT_MAX]         = ST_F_CONNECT,
-	[ST_F_EINT]           = ST_F_CLI_ABRT,
-	[ST_F_IDLE_CONN_CUR]  = ST_F_SAFE_CONN_CUR,
-	[ST_F_SAFE_CONN_CUR]  = ST_F_USED_CONN_CUR,
-	[ST_F_USED_CONN_CUR]  = ST_F_NEED_CONN_EST,
-	[ST_F_NEED_CONN_EST]  = 0,
-};
-
-/* Name of all info fields */
-const struct ist promex_inf_metric_names[INF_TOTAL_FIELDS] = {
-	[INF_NAME]                           = IST("name"),
-	[INF_VERSION]                        = IST("version"),
-	[INF_RELEASE_DATE]                   = IST("release_date"),
-	[INF_BUILD_INFO]                     = IST("build_info"),
-	[INF_NBTHREAD]                       = IST("nbthread"),
-	[INF_NBPROC]                         = IST("nbproc"),
-	[INF_PROCESS_NUM]                    = IST("relative_process_id"),
-	[INF_PID]                            = IST("pid"),
-	[INF_UPTIME]                         = IST("uptime"),
-	[INF_UPTIME_SEC]                     = IST("uptime_seconds"),
-	[INF_START_TIME_SEC]                 = IST("start_time_seconds"),
-	[INF_MEMMAX_BYTES]                   = IST("max_memory_bytes"),
-	[INF_POOL_ALLOC_BYTES]               = IST("pool_allocated_bytes"),
-	[INF_POOL_USED_BYTES]                = IST("pool_used_bytes"),
-	[INF_POOL_FAILED]                    = IST("pool_failures_total"),
-	[INF_ULIMIT_N]                       = IST("max_fds"),
-	[INF_MAXSOCK]                        = IST("max_sockets"),
-	[INF_MAXCONN]                        = IST("max_connections"),
-	[INF_HARD_MAXCONN]                   = IST("hard_max_connections"),
-	[INF_CURR_CONN]                      = IST("current_connections"),
-	[INF_CUM_CONN]                       = IST("connections_total"),
-	[INF_CUM_REQ]                        = IST("requests_total"),
-	[INF_MAX_SSL_CONNS]                  = IST("max_ssl_connections"),
-	[INF_CURR_SSL_CONNS]                 = IST("current_ssl_connections"),
-	[INF_CUM_SSL_CONNS]                  = IST("ssl_connections_total"),
-	[INF_MAXPIPES]                       = IST("max_pipes"),
-	[INF_PIPES_USED]                     = IST("pipes_used_total"),
-	[INF_PIPES_FREE]                     = IST("pipes_free_total"),
-	[INF_CONN_RATE]                      = IST("current_connection_rate"),
-	[INF_CONN_RATE_LIMIT]                = IST("limit_connection_rate"),
-	[INF_MAX_CONN_RATE]                  = IST("max_connection_rate"),
-	[INF_SESS_RATE]                      = IST("current_session_rate"),
-	[INF_SESS_RATE_LIMIT]                = IST("limit_session_rate"),
-	[INF_MAX_SESS_RATE]                  = IST("max_session_rate"),
-	[INF_SSL_RATE]                       = IST("current_ssl_rate"),
-	[INF_SSL_RATE_LIMIT]                 = IST("limit_ssl_rate"),
-	[INF_MAX_SSL_RATE]                   = IST("max_ssl_rate"),
-	[INF_SSL_FRONTEND_KEY_RATE]          = IST("current_frontend_ssl_key_rate"),
-	[INF_SSL_FRONTEND_MAX_KEY_RATE]      = IST("max_frontend_ssl_key_rate"),
-	[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = IST("frontend_ssl_reuse"),
-	[INF_SSL_BACKEND_KEY_RATE]           = IST("current_backend_ssl_key_rate"),
-	[INF_SSL_BACKEND_MAX_KEY_RATE]       = IST("max_backend_ssl_key_rate"),
-	[INF_SSL_CACHE_LOOKUPS]              = IST("ssl_cache_lookups_total"),
-	[INF_SSL_CACHE_MISSES]               = IST("ssl_cache_misses_total"),
-	[INF_COMPRESS_BPS_IN]                = IST("http_comp_bytes_in_total"),
-	[INF_COMPRESS_BPS_OUT]               = IST("http_comp_bytes_out_total"),
-	[INF_COMPRESS_BPS_RATE_LIM]          = IST("limit_http_comp"),
-	[INF_ZLIB_MEM_USAGE]                 = IST("current_zlib_memory"),
-	[INF_MAX_ZLIB_MEM_USAGE]             = IST("max_zlib_memory"),
-	[INF_TASKS]                          = IST("current_tasks"),
-	[INF_RUN_QUEUE]                      = IST("current_run_queue"),
-	[INF_IDLE_PCT]                       = IST("idle_time_percent"),
-	[INF_NODE]                           = IST("node"),
-	[INF_DESCRIPTION]                    = IST("description"),
-	[INF_STOPPING]                       = IST("stopping"),
-	[INF_JOBS]                           = IST("jobs"),
-	[INF_UNSTOPPABLE_JOBS]               = IST("unstoppable_jobs"),
-	[INF_LISTENERS]                      = IST("listeners"),
-	[INF_ACTIVE_PEERS]                   = IST("active_peers"),
-	[INF_CONNECTED_PEERS]                = IST("connected_peers"),
-	[INF_DROPPED_LOGS]                   = IST("dropped_logs_total"),
-	[INF_BUSY_POLLING]                   = IST("busy_polling_enabled"),
-	[INF_FAILED_RESOLUTIONS]             = IST("failed_resolutions"),
-	[INF_TOTAL_BYTES_OUT]                = IST("bytes_out_total"),
-	[INF_TOTAL_SPLICED_BYTES_OUT]        = IST("spliced_bytes_out_total"),
-	[INF_BYTES_OUT_RATE]                 = IST("bytes_out_rate"),
-	[INF_DEBUG_COMMANDS_ISSUED]          = IST("debug_commands_issued"),
-};
-
-/* Name of all stats fields */
-const struct ist promex_st_metric_names[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = IST("proxy_name"),
-	[ST_F_SVNAME]         = IST("service_name"),
-	[ST_F_QCUR]           = IST("current_queue"),
-	[ST_F_QMAX]           = IST("max_queue"),
-	[ST_F_SCUR]           = IST("current_sessions"),
-	[ST_F_SMAX]           = IST("max_sessions"),
-	[ST_F_SLIM]           = IST("limit_sessions"),
-	[ST_F_STOT]           = IST("sessions_total"),
-	[ST_F_BIN]            = IST("bytes_in_total"),
-	[ST_F_BOUT]           = IST("bytes_out_total"),
-	[ST_F_DREQ]           = IST("requests_denied_total"),
-	[ST_F_DRESP]          = IST("responses_denied_total"),
-	[ST_F_EREQ]           = IST("request_errors_total"),
-	[ST_F_ECON]           = IST("connection_errors_total"),
-	[ST_F_ERESP]          = IST("response_errors_total"),
-	[ST_F_WRETR]          = IST("retry_warnings_total"),
-	[ST_F_WREDIS]         = IST("redispatch_warnings_total"),
-	[ST_F_STATUS]         = IST("status"),
-	[ST_F_WEIGHT]         = IST("weight"),
-	[ST_F_ACT]            = IST("active_servers"),
-	[ST_F_BCK]            = IST("backup_servers"),
-	[ST_F_CHKFAIL]        = IST("check_failures_total"),
-	[ST_F_CHKDOWN]        = IST("check_up_down_total"),
-	[ST_F_LASTCHG]        = IST("check_last_change_seconds"),
-	[ST_F_DOWNTIME]       = IST("downtime_seconds_total"),
-	[ST_F_QLIMIT]         = IST("queue_limit"),
-	[ST_F_PID]            = IST("pid"),
-	[ST_F_IID]            = IST("proxy_id"),
-	[ST_F_SID]            = IST("server_id"),
-	[ST_F_THROTTLE]       = IST("current_throttle"),
-	[ST_F_LBTOT]          = IST("loadbalanced_total"),
-	[ST_F_TRACKED]        = IST("tracked"),
-	[ST_F_TYPE]           = IST("type"),
-	[ST_F_RATE]           = IST("current_session_rate"),
-	[ST_F_RATE_LIM]       = IST("limit_session_rate"),
-	[ST_F_RATE_MAX]       = IST("max_session_rate"),
-	[ST_F_CHECK_STATUS]   = IST("check_status"),
-	[ST_F_CHECK_CODE]     = IST("check_code"),
-	[ST_F_CHECK_DURATION] = IST("check_duration_seconds"),
-	[ST_F_HRSP_1XX]       = IST("http_responses_total"),
-	[ST_F_HRSP_2XX]       = IST("http_responses_total"),
-	[ST_F_HRSP_3XX]       = IST("http_responses_total"),
-	[ST_F_HRSP_4XX]       = IST("http_responses_total"),
-	[ST_F_HRSP_5XX]       = IST("http_responses_total"),
-	[ST_F_HRSP_OTHER]     = IST("http_responses_total"),
-	[ST_F_HANAFAIL]       = IST("check_analyses_failures_total"),
-	[ST_F_REQ_RATE]       = IST("http_requests_rate_current"),
-	[ST_F_REQ_RATE_MAX]   = IST("http_requests_rate_max"),
-	[ST_F_REQ_TOT]        = IST("http_requests_total"),
-	[ST_F_CLI_ABRT]       = IST("client_aborts_total"),
-	[ST_F_SRV_ABRT]       = IST("server_aborts_total"),
-	[ST_F_COMP_IN]        = IST("http_comp_bytes_in_total"),
-	[ST_F_COMP_OUT]       = IST("http_comp_bytes_out_total"),
-	[ST_F_COMP_BYP]       = IST("http_comp_bytes_bypassed_total"),
-	[ST_F_COMP_RSP]       = IST("http_comp_responses_total"),
-	[ST_F_LASTSESS]       = IST("last_session_seconds"),
-	[ST_F_LAST_CHK]       = IST("check_last_content"),
-	[ST_F_LAST_AGT]       = IST("agentcheck_last_content"),
-	[ST_F_QTIME]          = IST("queue_time_average_seconds"),
-	[ST_F_CTIME]          = IST("connect_time_average_seconds"),
-	[ST_F_RTIME]          = IST("response_time_average_seconds"),
-	[ST_F_TTIME]          = IST("total_time_average_seconds"),
-	[ST_F_AGENT_STATUS]   = IST("agentcheck_status"),
-	[ST_F_AGENT_CODE]     = IST("agentcheck_code"),
-	[ST_F_AGENT_DURATION] = IST("agentcheck_duration_milliseconds"),
-	[ST_F_CHECK_DESC]     = IST("check_description"),
-	[ST_F_AGENT_DESC]     = IST("agentcheck_description"),
-	[ST_F_CHECK_RISE]     = IST("check_rise"),
-	[ST_F_CHECK_FALL]     = IST("check_fall"),
-	[ST_F_CHECK_HEALTH]   = IST("check_value"),
-	[ST_F_AGENT_RISE]     = IST("agentcheck_rise"),
-	[ST_F_AGENT_FALL]     = IST("agentcheck_fall"),
-	[ST_F_AGENT_HEALTH]   = IST("agentcheck_value"),
-	[ST_F_ADDR]           = IST("address"),
-	[ST_F_COOKIE]         = IST("cookie"),
-	[ST_F_MODE]           = IST("mode"),
-	[ST_F_ALGO]           = IST("loadbalance_algorithm"),
-	[ST_F_CONN_RATE]      = IST("connections_rate_current"),
-	[ST_F_CONN_RATE_MAX]  = IST("connections_rate_max"),
-	[ST_F_CONN_TOT]       = IST("connections_total"),
-	[ST_F_INTERCEPTED]    = IST("intercepted_requests_total"),
-	[ST_F_DCON]           = IST("denied_connections_total"),
-	[ST_F_DSES]           = IST("denied_sessions_total"),
-	[ST_F_WREW]           = IST("failed_header_rewriting_total"),
-	[ST_F_CONNECT]        = IST("connection_attempts_total"),
-	[ST_F_REUSE]          = IST("connection_reuses_total"),
-	[ST_F_CACHE_LOOKUPS]  = IST("http_cache_lookups_total"),
-	[ST_F_CACHE_HITS]     = IST("http_cache_hits_total"),
-	[ST_F_SRV_ICUR]       = IST("idle_connections_current"),
-	[ST_F_SRV_ILIM]       = IST("idle_connections_limit"),
-	[ST_F_QT_MAX]         = IST("max_queue_time_seconds"),
-	[ST_F_CT_MAX]         = IST("max_connect_time_seconds"),
-	[ST_F_RT_MAX]         = IST("max_response_time_seconds"),
-	[ST_F_TT_MAX]         = IST("max_total_time_seconds"),
-	[ST_F_EINT]           = IST("internal_errors_total"),
-	[ST_F_IDLE_CONN_CUR]  = IST("unsafe_idle_connections_current"),
-	[ST_F_SAFE_CONN_CUR]  = IST("safe_idle_connections_current"),
-	[ST_F_USED_CONN_CUR]  = IST("used_connections_current"),
-	[ST_F_NEED_CONN_EST]  = IST("need_connections_current"),
+/* frontend/backend/server fields */
+const struct promex_metric promex_st_metrics[ST_F_TOTAL_FIELDS] = {
+	//[ST_F_PXNAME]         ignored
+	//[ST_F_SVNAME]         ignored
+	[ST_F_QCUR]           = { .n = IST("current_queue"),                    .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_QMAX]           = { .n = IST("max_queue"),                        .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_SCUR]           = { .n = IST("current_sessions"),                 .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_SMAX]           = { .n = IST("max_sessions"),                     .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_SLIM]           = { .n = IST("limit_sessions"),                   .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_STOT]           = { .n = IST("sessions_total"),                   .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_BIN]            = { .n = IST("bytes_in_total"),                   .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_BOUT]           = { .n = IST("bytes_out_total"),                  .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_DREQ]           = { .n = IST("requests_denied_total"),            .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_DRESP]          = { .n = IST("responses_denied_total"),           .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_EREQ]           = { .n = IST("request_errors_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_ECON]           = { .n = IST("connection_errors_total"),          .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_ERESP]          = { .n = IST("response_errors_total"),            .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_WRETR]          = { .n = IST("retry_warnings_total"),             .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_WREDIS]         = { .n = IST("redispatch_warnings_total"),        .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_STATUS]         = { .n = IST("status"),                           .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_WEIGHT]         = { .n = IST("weight"),                           .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_ACT]            = { .n = IST("active_servers"),                   .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_BCK]            = { .n = IST("backup_servers"),                   .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_CHKFAIL]        = { .n = IST("check_failures_total"),             .type = PROMEX_MT_COUNTER,  .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_CHKDOWN]        = { .n = IST("check_up_down_total"),              .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_LASTCHG]        = { .n = IST("check_last_change_seconds"),        .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_DOWNTIME]       = { .n = IST("downtime_seconds_total"),           .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_QLIMIT]         = { .n = IST("queue_limit"),                      .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	//[ST_F_PID]            ignored
+	//[ST_F_IID]            ignored
+	//[ST_F_SID]            ignored
+	[ST_F_THROTTLE]       = { .n = IST("current_throttle"),                 .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_LBTOT]          = { .n = IST("loadbalanced_total"),               .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	//[ST_F_TRACKED]        ignored
+	//[ST_F_TYPE]           ignored
+	//[ST_F_RATE]           ignored
+	[ST_F_RATE_LIM]       = { .n = IST("limit_session_rate"),               .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_RATE_MAX]       = { .n = IST("max_session_rate"),                 .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_CHECK_STATUS]   = { .n = IST("check_status"),                     .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_CHECK_CODE]     = { .n = IST("check_code"),                       .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_CHECK_DURATION] = { .n = IST("check_duration_seconds"),           .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_1XX]       = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_2XX]       = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_3XX]       = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_4XX]       = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_5XX]       = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_HRSP_OTHER]     = { .n = IST("http_responses_total"),             .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	//[ST_F_HANAFAIL]       ignored
+	//[ST_F_REQ_RATE]       ignored
+	[ST_F_REQ_RATE_MAX]   = { .n = IST("http_requests_rate_max"),           .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_REQ_TOT]        = { .n = IST("http_requests_total"),              .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_CLI_ABRT]       = { .n = IST("client_aborts_total"),              .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_SRV_ABRT]       = { .n = IST("server_aborts_total"),              .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_COMP_IN]        = { .n = IST("http_comp_bytes_in_total"),         .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_COMP_OUT]       = { .n = IST("http_comp_bytes_out_total"),        .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_COMP_BYP]       = { .n = IST("http_comp_bytes_bypassed_total"),   .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_COMP_RSP]       = { .n = IST("http_comp_responses_total"),        .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_LASTSESS]       = { .n = IST("last_session_seconds"),             .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	//[ST_F_LAST_CHK]       ignroed
+	//[ST_F_LAST_AGT]       ignored
+	[ST_F_QTIME]          = { .n = IST("queue_time_average_seconds"),       .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_CTIME]          = { .n = IST("connect_time_average_seconds"),     .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_RTIME]          = { .n = IST("response_time_average_seconds"),    .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_TTIME]          = { .n = IST("total_time_average_seconds"),       .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	//[ST_F_AGENT_STATUS]   ignored
+	//[ST_F_AGENT_CODE]     ignored
+	//[ST_F_AGENT_DURATION] ignored
+	//[ST_F_CHECK_DESC]     ignored
+	//[ST_F_AGENT_DESC]     ignored
+	//[ST_F_CHECK_RISE]     ignored
+	//[ST_F_CHECK_FALL]     ignored
+	//[ST_F_CHECK_HEALTH]   ignored
+	//[ST_F_AGENT_RISE]     ignored
+	//[ST_F_AGENT_FALL]     ignored
+	//[ST_F_AGENT_HEALTH]   ignored
+	//[ST_F_ADDR]           ignored
+	//[ST_F_COOKIE]         ignored
+	//[ST_F_MODE]           ignored
+	//[ST_F_ALGO]           ignored
+	//[ST_F_CONN_RATE]      ignored
+	[ST_F_CONN_RATE_MAX]  = { .n = IST("connections_rate_max"),             .type = PROMEX_MT_GAUGE,    .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_CONN_TOT]       = { .n = IST("connections_total"),                .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_INTERCEPTED]    = { .n = IST("intercepted_requests_total"),       .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_DCON]           = { .n = IST("denied_connections_total"),         .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_DSES]           = { .n = IST("denied_sessions_total"),            .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC                                               ) },
+	[ST_F_WREW]           = { .n = IST("failed_header_rewriting_total"),    .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_CONNECT]        = { .n = IST("connection_attempts_total"),        .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_REUSE]          = { .n = IST("connection_reuses_total"),          .type = PROMEX_MT_COUNTER,  .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_CACHE_LOOKUPS]  = { .n = IST("http_cache_lookups_total"),         .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_CACHE_HITS]     = { .n = IST("http_cache_hits_total"),            .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC                       ) },
+	[ST_F_SRV_ICUR]       = { .n = IST("idle_connections_current"),         .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_SRV_ILIM]       = { .n = IST("idle_connections_limit"),           .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_QT_MAX]         = { .n = IST("max_queue_time_seconds"),           .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_CT_MAX]         = { .n = IST("max_connect_time_seconds"),         .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_RT_MAX]         = { .n = IST("max_response_time_seconds"),        .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_TT_MAX]         = { .n = IST("max_total_time_seconds"),           .type = PROMEX_MT_GAUGE,    .flags = (                         PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_EINT]           = { .n = IST("internal_errors_total"),            .type = PROMEX_MT_COUNTER,  .flags = (PROMEX_FL_FRONT_METRIC | PROMEX_FL_BACK_METRIC | PROMEX_FL_SRV_METRIC) },
+	[ST_F_IDLE_CONN_CUR]  = { .n = IST("unsafe_idle_connections_current"),  .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_SAFE_CONN_CUR]=   { .n = IST("safe_idle_connections_current"),    .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_USED_CONN_CUR]  = { .n = IST("used_connections_current"),         .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
+	[ST_F_NEED_CONN_EST]  = { .n = IST("need_connections_current"),         .type = PROMEX_MT_GAUGE,    .flags = (                                                 PROMEX_FL_SRV_METRIC) },
 };
 
 /* Description of all stats fields */
@@ -778,180 +394,6 @@ const struct ist promex_st_metric_labels[ST_F_TOTAL_FIELDS] = {
 	[ST_F_HRSP_OTHER] = IST("code=\"other\""),
 };
 
-/* Type for all info fields. "untyped" is used for unsupported field. */
-const struct ist promex_inf_metric_types[INF_TOTAL_FIELDS] = {
-	[INF_NAME]                           = IST("untyped"),
-	[INF_VERSION]                        = IST("untyped"),
-	[INF_RELEASE_DATE]                   = IST("untyped"),
-	[INF_BUILD_INFO]                     = IST("gauge"),
-	[INF_NBTHREAD]                       = IST("gauge"),
-	[INF_NBPROC]                         = IST("gauge"),
-	[INF_PROCESS_NUM]                    = IST("gauge"),
-	[INF_PID]                            = IST("untyped"),
-	[INF_UPTIME]                         = IST("untyped"),
-	[INF_UPTIME_SEC]                     = IST("gauge"),
-	[INF_START_TIME_SEC]                 = IST("gauge"),
-	[INF_MEMMAX_BYTES]                   = IST("gauge"),
-	[INF_POOL_ALLOC_BYTES]               = IST("gauge"),
-	[INF_POOL_USED_BYTES]                = IST("gauge"),
-	[INF_POOL_FAILED]                    = IST("counter"),
-	[INF_ULIMIT_N]                       = IST("gauge"),
-	[INF_MAXSOCK]                        = IST("gauge"),
-	[INF_MAXCONN]                        = IST("gauge"),
-	[INF_HARD_MAXCONN]                   = IST("gauge"),
-	[INF_CURR_CONN]                      = IST("gauge"),
-	[INF_CUM_CONN]                       = IST("counter"),
-	[INF_CUM_REQ]                        = IST("counter"),
-	[INF_MAX_SSL_CONNS]                  = IST("gauge"),
-	[INF_CURR_SSL_CONNS]                 = IST("gauge"),
-	[INF_CUM_SSL_CONNS]                  = IST("counter"),
-	[INF_MAXPIPES]                       = IST("gauge"),
-	[INF_PIPES_USED]                     = IST("counter"),
-	[INF_PIPES_FREE]                     = IST("counter"),
-	[INF_CONN_RATE]                      = IST("gauge"),
-	[INF_CONN_RATE_LIMIT]                = IST("gauge"),
-	[INF_MAX_CONN_RATE]                  = IST("gauge"),
-	[INF_SESS_RATE]                      = IST("gauge"),
-	[INF_SESS_RATE_LIMIT]                = IST("gauge"),
-	[INF_MAX_SESS_RATE]                  = IST("gauge"),
-	[INF_SSL_RATE]                       = IST("gauge"),
-	[INF_SSL_RATE_LIMIT]                 = IST("gauge"),
-	[INF_MAX_SSL_RATE]                   = IST("gauge"),
-	[INF_SSL_FRONTEND_KEY_RATE]          = IST("gauge"),
-	[INF_SSL_FRONTEND_MAX_KEY_RATE]      = IST("gauge"),
-	[INF_SSL_FRONTEND_SESSION_REUSE_PCT] = IST("gauge"),
-	[INF_SSL_BACKEND_KEY_RATE]           = IST("gauge"),
-	[INF_SSL_BACKEND_MAX_KEY_RATE]       = IST("gauge"),
-	[INF_SSL_CACHE_LOOKUPS]              = IST("counter"),
-	[INF_SSL_CACHE_MISSES]               = IST("counter"),
-	[INF_COMPRESS_BPS_IN]                = IST("counter"),
-	[INF_COMPRESS_BPS_OUT]               = IST("counter"),
-	[INF_COMPRESS_BPS_RATE_LIM]          = IST("gauge"),
-	[INF_ZLIB_MEM_USAGE]                 = IST("gauge"),
-	[INF_MAX_ZLIB_MEM_USAGE]             = IST("gauge"),
-	[INF_TASKS]                          = IST("gauge"),
-	[INF_RUN_QUEUE]                      = IST("gauge"),
-	[INF_IDLE_PCT]                       = IST("gauge"),
-	[INF_NODE]                           = IST("untyped"),
-	[INF_DESCRIPTION]                    = IST("untyped"),
-	[INF_STOPPING]                       = IST("gauge"),
-	[INF_JOBS]                           = IST("gauge"),
-	[INF_UNSTOPPABLE_JOBS]               = IST("gauge"),
-	[INF_LISTENERS]                      = IST("gauge"),
-	[INF_ACTIVE_PEERS]                   = IST("gauge"),
-	[INF_CONNECTED_PEERS]                = IST("gauge"),
-	[INF_DROPPED_LOGS]                   = IST("counter"),
-	[INF_BUSY_POLLING]                   = IST("gauge"),
-	[INF_FAILED_RESOLUTIONS]             = IST("counter"),
-	[INF_TOTAL_BYTES_OUT]                = IST("counter"),
-	[INF_TOTAL_SPLICED_BYTES_OUT]        = IST("counter"),
-	[INF_BYTES_OUT_RATE]                 = IST("gauge"),
-	[INF_DEBUG_COMMANDS_ISSUED]          = IST(""),
-};
-
-/* Type for all stats fields. "untyped" is used for unsupported field. */
-const struct ist promex_st_metric_types[ST_F_TOTAL_FIELDS] = {
-	[ST_F_PXNAME]         = IST("untyped"),
-	[ST_F_SVNAME]         = IST("untyped"),
-	[ST_F_QCUR]           = IST("gauge"),
-	[ST_F_QMAX]           = IST("gauge"),
-	[ST_F_SCUR]           = IST("gauge"),
-	[ST_F_SMAX]           = IST("gauge"),
-	[ST_F_SLIM]           = IST("gauge"),
-	[ST_F_STOT]           = IST("counter"),
-	[ST_F_BIN]            = IST("counter"),
-	[ST_F_BOUT]           = IST("counter"),
-	[ST_F_DREQ]           = IST("counter"),
-	[ST_F_DRESP]          = IST("counter"),
-	[ST_F_EREQ]           = IST("counter"),
-	[ST_F_ECON]           = IST("counter"),
-	[ST_F_ERESP]          = IST("counter"),
-	[ST_F_WRETR]          = IST("counter"),
-	[ST_F_WREDIS]         = IST("counter"),
-	[ST_F_STATUS]         = IST("gauge"),
-	[ST_F_WEIGHT]         = IST("gauge"),
-	[ST_F_ACT]            = IST("gauge"),
-	[ST_F_BCK]            = IST("gauge"),
-	[ST_F_CHKFAIL]        = IST("counter"),
-	[ST_F_CHKDOWN]        = IST("counter"),
-	[ST_F_LASTCHG]        = IST("gauge"),
-	[ST_F_DOWNTIME]       = IST("counter"),
-	[ST_F_QLIMIT]         = IST("gauge"),
-	[ST_F_PID]            = IST("untyped"),
-	[ST_F_IID]            = IST("untyped"),
-	[ST_F_SID]            = IST("untyped"),
-	[ST_F_THROTTLE]       = IST("gauge"),
-	[ST_F_LBTOT]          = IST("counter"),
-	[ST_F_TRACKED]        = IST("untyped"),
-	[ST_F_TYPE]           = IST("untyped"),
-	[ST_F_RATE]           = IST("untyped"),
-	[ST_F_RATE_LIM]       = IST("gauge"),
-	[ST_F_RATE_MAX]       = IST("gauge"),
-	[ST_F_CHECK_STATUS]   = IST("gauge"),
-	[ST_F_CHECK_CODE]     = IST("gauge"),
-	[ST_F_CHECK_DURATION] = IST("gauge"),
-	[ST_F_HRSP_1XX]       = IST("counter"),
-	[ST_F_HRSP_2XX]       = IST("counter"),
-	[ST_F_HRSP_3XX]       = IST("counter"),
-	[ST_F_HRSP_4XX]       = IST("counter"),
-	[ST_F_HRSP_5XX]       = IST("counter"),
-	[ST_F_HRSP_OTHER]     = IST("counter"),
-	[ST_F_HANAFAIL]       = IST("counter"),
-	[ST_F_REQ_RATE]       = IST("untyped"),
-	[ST_F_REQ_RATE_MAX]   = IST("gauge"),
-	[ST_F_REQ_TOT]        = IST("counter"),
-	[ST_F_CLI_ABRT]       = IST("counter"),
-	[ST_F_SRV_ABRT]       = IST("counter"),
-	[ST_F_COMP_IN]        = IST("counter"),
-	[ST_F_COMP_OUT]       = IST("counter"),
-	[ST_F_COMP_BYP]       = IST("counter"),
-	[ST_F_COMP_RSP]       = IST("counter"),
-	[ST_F_LASTSESS]       = IST("gauge"),
-	[ST_F_LAST_CHK]       = IST("untyped"),
-	[ST_F_LAST_AGT]       = IST("untyped"),
-	[ST_F_QTIME]          = IST("gauge"),
-	[ST_F_CTIME]          = IST("gauge"),
-	[ST_F_RTIME]          = IST("gauge"),
-	[ST_F_TTIME]          = IST("gauge"),
-	[ST_F_AGENT_STATUS]   = IST("untyped"),
-	[ST_F_AGENT_CODE]     = IST("untyped"),
-	[ST_F_AGENT_DURATION] = IST("gauge"),
-	[ST_F_CHECK_DESC]     = IST("untyped"),
-	[ST_F_AGENT_DESC]     = IST("untyped"),
-	[ST_F_CHECK_RISE]     = IST("gauge"),
-	[ST_F_CHECK_FALL]     = IST("gauge"),
-	[ST_F_CHECK_HEALTH]   = IST("gauge"),
-	[ST_F_AGENT_RISE]     = IST("gauge"),
-	[ST_F_AGENT_FALL]     = IST("gauge"),
-	[ST_F_AGENT_HEALTH]   = IST("gauge"),
-	[ST_F_ADDR]           = IST("untyped"),
-	[ST_F_COOKIE]         = IST("untyped"),
-	[ST_F_MODE]           = IST("untyped"),
-	[ST_F_ALGO]           = IST("untyped"),
-	[ST_F_CONN_RATE]      = IST("untyped"),
-	[ST_F_CONN_RATE_MAX]  = IST("gauge"),
-	[ST_F_CONN_TOT]       = IST("counter"),
-	[ST_F_INTERCEPTED]    = IST("counter"),
-	[ST_F_DCON]           = IST("counter"),
-	[ST_F_DSES]           = IST("counter"),
-	[ST_F_WREW]           = IST("counter"),
-	[ST_F_CONNECT]        = IST("counter"),
-	[ST_F_REUSE]          = IST("counter"),
-	[ST_F_CACHE_LOOKUPS]  = IST("counter"),
-	[ST_F_CACHE_HITS]     = IST("counter"),
-	[ST_F_SRV_ICUR]       = IST("gauge"),
-	[ST_F_SRV_ILIM]       = IST("gauge"),
-	[ST_F_QT_MAX]         = IST("gauge"),
-	[ST_F_CT_MAX]         = IST("gauge"),
-	[ST_F_RT_MAX]         = IST("gauge"),
-	[ST_F_TT_MAX]         = IST("gauge"),
-	[ST_F_EINT]           = IST("counter"),
-	[ST_F_IDLE_CONN_CUR]  = IST("gauge"),
-	[ST_F_SAFE_CONN_CUR]  = IST("gauge"),
-	[ST_F_USED_CONN_CUR]  = IST("gauge"),
-	[ST_F_NEED_CONN_EST]  = IST("gauge"),
-};
-
 /* Return the server status: 0=DOWN, 1=UP, 2=MAINT, 3=DRAIN, 4=NOLB. */
 static int promex_srv_status(struct server *sv)
 {
@@ -996,55 +438,42 @@ static int promex_metric_to_str(struct buffer *out, struct field *f, size_t max)
 	return 1;
 }
 
-/* Concatenate the <prefix> with the field name using the array
- * <promex_st_metric_names> and store it in <name>. The field type is in
- * <appctx->st2>. This function never fails but relies on
- * <PROMEX_MAX_NAME_LEN>. So by sure the result is small enough to be copied in
- * <name>
- */
-static void promex_metric_name(struct appctx *appctx, struct ist *name, const struct ist prefix)
-{
-	const struct ist *names;
-
-	names = ((appctx->ctx.stats.flags & PROMEX_FL_INFO_METRIC)
-		 ? promex_inf_metric_names
-		 : promex_st_metric_names);
-
-	istcat(name, prefix, PROMEX_MAX_NAME_LEN);
-	istcat(name, names[appctx->st2],  PROMEX_MAX_NAME_LEN);
-}
-
 /* Dump the header lines for <metric>. It is its #HELP and #TYPE strings. It
  * returns 1 on success. Otherwise, if <out> length exceeds <max>, it returns 0.
  */
 static int promex_dump_metric_header(struct appctx *appctx, struct htx *htx,
-				     const struct ist name, struct ist *out, size_t max)
+				     const struct promex_metric *metric, const struct ist name,
+				     struct ist *out, size_t max)
 {
-	const struct ist *desc, *types;
+	struct ist type;
+
+	switch (metric->type) {
+		case PROMEX_MT_GAUGE:
+			type = ist("gauge");
+			break;
+		case PROMEX_MT_COUNTER:
+			type = ist("counter");
+			break;
+	}
 
 	if (istcat(out, ist("# HELP "), max) == -1 ||
 	    istcat(out, name, max) == -1 ||
 	    istcat(out, ist(" "), max) == -1)
 		goto full;
 
-	if (appctx->ctx.stats.flags & PROMEX_FL_INFO_METRIC) {
-		types = promex_inf_metric_types;
-
+	if (metric->flags & PROMEX_FL_INFO_METRIC) {
 		if (istcat(out, ist(info_fields[appctx->st2].desc), max) == -1)
 			goto full;
 	}
 	else {
-		desc  = promex_st_metric_desc;
-		types = promex_st_metric_types;
-
-		if (istcat(out, desc[appctx->st2], max) == -1)
+		if (istcat(out, promex_st_metric_desc[appctx->st2], max) == -1)
 			goto full;
 	}
 
 	if (istcat(out, ist("\n# TYPE "), max) == -1 ||
 	    istcat(out, name, max) == -1 ||
 	    istcat(out, ist(" "), max) == -1 ||
-	    istcat(out, types[appctx->st2], max) == -1 ||
+	    istcat(out, type, max) == -1 ||
 	    istcat(out, ist("\n"), max) == -1)
 		goto full;
 
@@ -1059,8 +488,8 @@ static int promex_dump_metric_header(struct appctx *appctx, struct htx *htx,
  * not already done, the header lines are dumped first. It returns 1 on
  * success. Otherwise if <out> length exceeds <max>, it returns 0.
  */
-static int promex_dump_metric(struct appctx *appctx, struct htx *htx,
-			      const struct ist prefix, struct field *metric,
+static int promex_dump_metric(struct appctx *appctx, struct htx *htx, struct ist prefix,
+			     const  struct promex_metric *metric, struct field *val,
 			      struct ist *out, size_t max)
 {
 	struct ist name = { .ptr = (char[PROMEX_MAX_NAME_LEN]){ 0 }, .len = 0 };
@@ -1069,9 +498,13 @@ static int promex_dump_metric(struct appctx *appctx, struct htx *htx,
 	if (out->len + PROMEX_MAX_METRIC_LENGTH > max)
 		return 0;
 
-	promex_metric_name(appctx, &name, prefix);
+	/* Fill the metric name */
+	istcat(&name, prefix, PROMEX_MAX_NAME_LEN);
+	istcat(&name, metric->n, PROMEX_MAX_NAME_LEN);
+
+
 	if ((appctx->ctx.stats.flags & PROMEX_FL_METRIC_HDR) &&
-	    !promex_dump_metric_header(appctx, htx, name, out, max))
+	    !promex_dump_metric_header(appctx, htx, metric, name, out, max))
 		goto full;
 
 	if (appctx->ctx.stats.flags & PROMEX_FL_INFO_METRIC) {
@@ -1103,7 +536,7 @@ static int promex_dump_metric(struct appctx *appctx, struct htx *htx,
 	}
 
 	trash.data = out->len;
-	if (!promex_metric_to_str(&trash, metric, max))
+	if (!promex_metric_to_str(&trash, val, max))
 		goto full;
 	out->len = trash.data;
 
@@ -1122,7 +555,7 @@ static int promex_dump_metric(struct appctx *appctx, struct htx *htx,
 static int promex_dump_global_metrics(struct appctx *appctx, struct htx *htx)
 {
 	static struct ist prefix = IST("haproxy_process_");
-	struct field metric;
+	struct field val;
 	struct channel *chn = si_ic(appctx->owner);
 	struct ist out = ist2(trash.area, 0);
 	size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
@@ -1131,21 +564,23 @@ static int promex_dump_global_metrics(struct appctx *appctx, struct htx *htx)
 	if (!stats_fill_info(info, INF_TOTAL_FIELDS))
 		return -1;
 
-	while (appctx->st2 && appctx->st2 < INF_TOTAL_FIELDS) {
+	for (; appctx->st2 < INF_TOTAL_FIELDS; appctx->st2++) {
+		if (!(promex_global_metrics[appctx->st2].flags & appctx->ctx.stats.flags))
+			continue;
+
 		switch (appctx->st2) {
 			case INF_BUILD_INFO:
-				metric = mkf_u32(FN_GAUGE, 1);
+				val = mkf_u32(FN_GAUGE, 1);
 				break;
 
 			default:
-				metric = info[appctx->st2];
+				val = info[appctx->st2];
 		}
 
-		if (!promex_dump_metric(appctx, htx, prefix, &metric, &out, max))
+		if (!promex_dump_metric(appctx, htx, prefix, &promex_global_metrics[appctx->st2], &val, &out, max))
 			goto full;
 
 		appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
-		appctx->st2 = promex_global_metrics[appctx->st2];
 	}
 
   end:
@@ -1166,14 +601,17 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
 {
 	static struct ist prefix = IST("haproxy_frontend_");
 	struct proxy *px;
-	struct field metric;
+	struct field val;
 	struct channel *chn = si_ic(appctx->owner);
 	struct ist out = ist2(trash.area, 0);
 	size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
 	struct field *stats = stat_l[STATS_DOMAIN_PROXY];
 	int ret = 1;
 
-	while (appctx->st2 && appctx->st2 < ST_F_TOTAL_FIELDS) {
+	for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) {
+		if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags))
+			continue;
+
 		while (appctx->ctx.stats.obj1) {
 			px = appctx->ctx.stats.obj1;
 
@@ -1186,7 +624,7 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
 
 			switch (appctx->st2) {
 				case ST_F_STATUS:
-					metric = mkf_u32(FO_STATUS, !px->disabled);
+					val = mkf_u32(FO_STATUS, !px->disabled);
 					break;
 				case ST_F_REQ_RATE_MAX:
 				case ST_F_REQ_TOT:
@@ -1200,7 +638,7 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
 				case ST_F_COMP_RSP:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = stats[appctx->st2];
+					val = stats[appctx->st2];
 					break;
 				case ST_F_HRSP_2XX:
 				case ST_F_HRSP_3XX:
@@ -1209,22 +647,21 @@ static int promex_dump_front_metrics(struct appctx *appctx, struct htx *htx)
 				case ST_F_HRSP_OTHER:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = stats[appctx->st2];
+					val = stats[appctx->st2];
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
 					break;
 
 				default:
-					metric = stats[appctx->st2];
+					val = stats[appctx->st2];
 			}
 
-			if (!promex_dump_metric(appctx, htx, prefix, &metric, &out, max))
+			if (!promex_dump_metric(appctx, htx, prefix, &promex_st_metrics[appctx->st2], &val, &out, max))
 				goto full;
 		  next_px:
 			appctx->ctx.stats.obj1 = px->next;
 		}
 		appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
 		appctx->ctx.stats.obj1 = proxies_list;
-		appctx->st2 = promex_front_metrics[appctx->st2];
 	}
 
   end:
@@ -1245,7 +682,7 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
 {
 	static struct ist prefix = IST("haproxy_backend_");
 	struct proxy *px;
-	struct field metric;
+	struct field val;
 	struct channel *chn = si_ic(appctx->owner);
 	struct ist out = ist2(trash.area, 0);
 	size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
@@ -1253,7 +690,10 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
 	uint32_t weight;
 	double secs;
 
-	while (appctx->st2 && appctx->st2 < ST_F_TOTAL_FIELDS) {
+	for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) {
+		if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags))
+			continue;
+
 		while (appctx->ctx.stats.obj1) {
 			px = appctx->ctx.stats.obj1;
 
@@ -1263,204 +703,204 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
 
 			switch (appctx->st2) {
 				case ST_F_STATUS:
-					metric = mkf_u32(FO_STATUS, (px->lbprm.tot_weight > 0 || !px->srv) ? 1 : 0);
+					val = mkf_u32(FO_STATUS, (px->lbprm.tot_weight > 0 || !px->srv) ? 1 : 0);
 					break;
 				case ST_F_SCUR:
-					metric = mkf_u32(0, px->beconn);
+					val = mkf_u32(0, px->beconn);
 					break;
 				case ST_F_SMAX:
-					metric = mkf_u32(FN_MAX, px->be_counters.conn_max);
+					val = mkf_u32(FN_MAX, px->be_counters.conn_max);
 					break;
 				case ST_F_SLIM:
-					metric = mkf_u32(FO_CONFIG|FN_LIMIT, px->fullconn);
+					val = mkf_u32(FO_CONFIG|FN_LIMIT, px->fullconn);
 					break;
 				case ST_F_STOT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.cum_conn);
+					val = mkf_u64(FN_COUNTER, px->be_counters.cum_conn);
 					break;
 				case ST_F_RATE_MAX:
-					metric = mkf_u32(0, px->be_counters.sps_max);
+					val = mkf_u32(0, px->be_counters.sps_max);
 					break;
 				case ST_F_LASTSESS:
-					metric = mkf_s32(FN_AGE, be_lastsession(px));
+					val = mkf_s32(FN_AGE, be_lastsession(px));
 					break;
 				case ST_F_QCUR:
-					metric = mkf_u32(0, px->nbpend);
+					val = mkf_u32(0, px->nbpend);
 					break;
 				case ST_F_QMAX:
-					metric = mkf_u32(FN_MAX, px->be_counters.nbpend_max);
+					val = mkf_u32(FN_MAX, px->be_counters.nbpend_max);
 					break;
 				case ST_F_CONNECT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.connect);
+					val = mkf_u64(FN_COUNTER, px->be_counters.connect);
 					break;
 				case ST_F_REUSE:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.reuse);
+					val = mkf_u64(FN_COUNTER, px->be_counters.reuse);
 					break;
 				case ST_F_BIN:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.bytes_in);
+					val = mkf_u64(FN_COUNTER, px->be_counters.bytes_in);
 					break;
 				case ST_F_BOUT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.bytes_out);
+					val = mkf_u64(FN_COUNTER, px->be_counters.bytes_out);
 					break;
 				case ST_F_QTIME:
 					secs = (double)swrate_avg(px->be_counters.q_time, TIME_STATS_SAMPLES) / 1000.0;
-					metric = mkf_flt(FN_AVG, secs);
+					val = mkf_flt(FN_AVG, secs);
 					break;
 				case ST_F_CTIME:
 					secs = (double)swrate_avg(px->be_counters.c_time, TIME_STATS_SAMPLES) / 1000.0;
-					metric = mkf_flt(FN_AVG, secs);
+					val = mkf_flt(FN_AVG, secs);
 					break;
 				case ST_F_RTIME:
 					secs = (double)swrate_avg(px->be_counters.d_time, TIME_STATS_SAMPLES) / 1000.0;
-					metric = mkf_flt(FN_AVG, secs);
+					val = mkf_flt(FN_AVG, secs);
 					break;
 				case ST_F_TTIME:
 					secs = (double)swrate_avg(px->be_counters.t_time, TIME_STATS_SAMPLES) / 1000.0;
-					metric = mkf_flt(FN_AVG, secs);
+					val = mkf_flt(FN_AVG, secs);
 					break;
 				case ST_F_QT_MAX:
 					secs = (double)px->be_counters.qtime_max / 1000.0;
-					metric = mkf_flt(FN_MAX, secs);
+					val = mkf_flt(FN_MAX, secs);
 					break;
 				case ST_F_CT_MAX:
 					secs = (double)px->be_counters.ctime_max / 1000.0;
-					metric = mkf_flt(FN_MAX, secs);
+					val = mkf_flt(FN_MAX, secs);
 					break;
 				case ST_F_RT_MAX:
 					secs = (double)px->be_counters.dtime_max / 1000.0;
-					metric = mkf_flt(FN_MAX, secs);
+					val = mkf_flt(FN_MAX, secs);
 					break;
 				case ST_F_TT_MAX:
 					secs = (double)px->be_counters.ttime_max / 1000.0;
-					metric = mkf_flt(FN_MAX, secs);
+					val = mkf_flt(FN_MAX, secs);
 					break;
 				case ST_F_DREQ:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.denied_req);
+					val = mkf_u64(FN_COUNTER, px->be_counters.denied_req);
 					break;
 				case ST_F_DRESP:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.denied_resp);
+					val = mkf_u64(FN_COUNTER, px->be_counters.denied_resp);
 					break;
 				case ST_F_ECON:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.failed_conns);
+					val = mkf_u64(FN_COUNTER, px->be_counters.failed_conns);
 					break;
 				case ST_F_ERESP:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.failed_resp);
+					val = mkf_u64(FN_COUNTER, px->be_counters.failed_resp);
 					break;
 				case ST_F_WRETR:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.retries);
+					val = mkf_u64(FN_COUNTER, px->be_counters.retries);
 					break;
 				case ST_F_WREDIS:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.redispatches);
+					val = mkf_u64(FN_COUNTER, px->be_counters.redispatches);
 					break;
 				case ST_F_WREW:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.failed_rewrites);
+					val = mkf_u64(FN_COUNTER, px->be_counters.failed_rewrites);
 					break;
 				case ST_F_EINT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.internal_errors);
+					val = mkf_u64(FN_COUNTER, px->be_counters.internal_errors);
 					break;
 				case ST_F_CLI_ABRT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.cli_aborts);
+					val = mkf_u64(FN_COUNTER, px->be_counters.cli_aborts);
 					break;
 				case ST_F_SRV_ABRT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.srv_aborts);
+					val = mkf_u64(FN_COUNTER, px->be_counters.srv_aborts);
 					break;
 				case ST_F_WEIGHT:
 					weight = (px->lbprm.tot_weight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv;
-					metric = mkf_u32(FN_AVG, weight);
+					val = mkf_u32(FN_AVG, weight);
 					break;
 				case ST_F_ACT:
-					metric = mkf_u32(0, px->srv_act);
+					val = mkf_u32(0, px->srv_act);
 					break;
 				case ST_F_BCK:
-					metric = mkf_u32(0, px->srv_bck);
+					val = mkf_u32(0, px->srv_bck);
 					break;
 				case ST_F_CHKDOWN:
-					metric = mkf_u64(FN_COUNTER, px->down_trans);
+					val = mkf_u64(FN_COUNTER, px->down_trans);
 					break;
 				case ST_F_LASTCHG:
-					metric = mkf_u32(FN_AGE, now.tv_sec - px->last_change);
+					val = mkf_u32(FN_AGE, now.tv_sec - px->last_change);
 					break;
 				case ST_F_DOWNTIME:
-					metric = mkf_u32(FN_COUNTER, be_downtime(px));
+					val = mkf_u32(FN_COUNTER, be_downtime(px));
 					break;
 				case ST_F_LBTOT:
-					metric = mkf_u64(FN_COUNTER, px->be_counters.cum_lbconn);
+					val = mkf_u64(FN_COUNTER, px->be_counters.cum_lbconn);
 					break;
 				case ST_F_REQ_TOT:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.cum_req);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.cum_req);
 					break;
 				case ST_F_HRSP_1XX:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[1]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[1]);
 					break;
 				case ST_F_HRSP_2XX:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[2]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[2]);
 					break;
 				case ST_F_HRSP_3XX:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[3]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[3]);
 					break;
 				case ST_F_HRSP_4XX:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[4]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[4]);
 					break;
 				case ST_F_HRSP_5XX:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[5]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[5]);
 					break;
 				case ST_F_HRSP_OTHER:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
 					appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[0]);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.rsp[0]);
 					break;
 				case ST_F_CACHE_LOOKUPS:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.cache_lookups);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.cache_lookups);
 					break;
 				case ST_F_CACHE_HITS:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.cache_hits);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.cache_hits);
 					break;
 				case ST_F_COMP_IN:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.comp_in);
+					val = mkf_u64(FN_COUNTER, px->be_counters.comp_in);
 					break;
 				case ST_F_COMP_OUT:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.comp_out);
+					val = mkf_u64(FN_COUNTER, px->be_counters.comp_out);
 					break;
 				case ST_F_COMP_BYP:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.comp_byp);
+					val = mkf_u64(FN_COUNTER, px->be_counters.comp_byp);
 					break;
 				case ST_F_COMP_RSP:
 					if (px->mode != PR_MODE_HTTP)
 						goto next_px;
-					metric = mkf_u64(FN_COUNTER, px->be_counters.p.http.comp_rsp);
+					val = mkf_u64(FN_COUNTER, px->be_counters.p.http.comp_rsp);
 					break;
 
 				default:
 					goto next_metric;
 			}
 
-			if (!promex_dump_metric(appctx, htx, prefix, &metric, &out, max))
+			if (!promex_dump_metric(appctx, htx, prefix, &promex_st_metrics[appctx->st2], &val, &out, max))
 				goto full;
 		  next_px:
 			appctx->ctx.stats.obj1 = px->next;
@@ -1468,7 +908,6 @@ static int promex_dump_back_metrics(struct appctx *appctx, struct htx *htx)
 	  next_metric:
 		appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
 		appctx->ctx.stats.obj1 = proxies_list;
-		appctx->st2 = promex_back_metrics[appctx->st2];
 	}
 
   end:
@@ -1490,7 +929,7 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
 	static struct ist prefix = IST("haproxy_server_");
 	struct proxy *px;
 	struct server *sv;
-	struct field metric;
+	struct field val;
 	struct channel *chn = si_ic(appctx->owner);
 	struct ist out = ist2(trash.area, 0);
 	size_t max = htx_get_max_blksz(htx, channel_htx_recv_max(chn, htx));
@@ -1498,7 +937,10 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
 	uint32_t weight;
 	double secs;
 
-	while (appctx->st2 && appctx->st2 < ST_F_TOTAL_FIELDS) {
+	for (;appctx->st2 < ST_F_TOTAL_FIELDS; appctx->st2++) {
+		if (!(promex_st_metrics[appctx->st2].flags & appctx->ctx.stats.flags))
+			continue;
+
 		while (appctx->ctx.stats.obj1) {
 			px = appctx->ctx.stats.obj1;
 
@@ -1514,208 +956,208 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
 
 				switch (appctx->st2) {
 					case ST_F_STATUS:
-						metric = mkf_u32(FO_STATUS, promex_srv_status(sv));
+						val = mkf_u32(FO_STATUS, promex_srv_status(sv));
 						break;
 					case ST_F_SCUR:
-						metric = mkf_u32(0, sv->cur_sess);
+						val = mkf_u32(0, sv->cur_sess);
 						break;
 					case ST_F_SMAX:
-						metric = mkf_u32(FN_MAX, sv->counters.cur_sess_max);
+						val = mkf_u32(FN_MAX, sv->counters.cur_sess_max);
 						break;
 					case ST_F_SLIM:
-						metric = mkf_u32(FO_CONFIG|FN_LIMIT, sv->maxconn);
+						val = mkf_u32(FO_CONFIG|FN_LIMIT, sv->maxconn);
 						break;
 					case ST_F_STOT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.cum_sess);
+						val = mkf_u64(FN_COUNTER, sv->counters.cum_sess);
 						break;
 					case ST_F_RATE_MAX:
-						metric = mkf_u32(FN_MAX, sv->counters.sps_max);
+						val = mkf_u32(FN_MAX, sv->counters.sps_max);
 						break;
 					case ST_F_LASTSESS:
-						metric = mkf_s32(FN_AGE, srv_lastsession(sv));
+						val = mkf_s32(FN_AGE, srv_lastsession(sv));
 						break;
 					case ST_F_QCUR:
-						metric = mkf_u32(0, sv->nbpend);
+						val = mkf_u32(0, sv->nbpend);
 						break;
 					case ST_F_QMAX:
-						metric = mkf_u32(FN_MAX, sv->counters.nbpend_max);
+						val = mkf_u32(FN_MAX, sv->counters.nbpend_max);
 						break;
 					case ST_F_QLIMIT:
-						metric = mkf_u32(FO_CONFIG|FS_SERVICE, sv->maxqueue);
+						val = mkf_u32(FO_CONFIG|FS_SERVICE, sv->maxqueue);
 						break;
 					case ST_F_BIN:
-						metric = mkf_u64(FN_COUNTER, sv->counters.bytes_in);
+						val = mkf_u64(FN_COUNTER, sv->counters.bytes_in);
 						break;
 					case ST_F_BOUT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.bytes_out);
+						val = mkf_u64(FN_COUNTER, sv->counters.bytes_out);
 						break;
 					case ST_F_QTIME:
 						secs = (double)swrate_avg(sv->counters.q_time, TIME_STATS_SAMPLES) / 1000.0;
-						metric = mkf_flt(FN_AVG, secs);
+						val = mkf_flt(FN_AVG, secs);
 						break;
 					case ST_F_CTIME:
 						secs = (double)swrate_avg(sv->counters.c_time, TIME_STATS_SAMPLES) / 1000.0;
-						metric = mkf_flt(FN_AVG, secs);
+						val = mkf_flt(FN_AVG, secs);
 						break;
 					case ST_F_RTIME:
 						secs = (double)swrate_avg(sv->counters.d_time, TIME_STATS_SAMPLES) / 1000.0;
-						metric = mkf_flt(FN_AVG, secs);
+						val = mkf_flt(FN_AVG, secs);
 						break;
 					case ST_F_TTIME:
 						secs = (double)swrate_avg(sv->counters.t_time, TIME_STATS_SAMPLES) / 1000.0;
-						metric = mkf_flt(FN_AVG, secs);
+						val = mkf_flt(FN_AVG, secs);
 						break;
 					case ST_F_QT_MAX:
 						secs = (double)sv->counters.qtime_max / 1000.0;
-						metric = mkf_flt(FN_MAX, secs);
+						val = mkf_flt(FN_MAX, secs);
 						break;
 					case ST_F_CT_MAX:
 						secs = (double)sv->counters.ctime_max / 1000.0;
-						metric = mkf_flt(FN_MAX, secs);
+						val = mkf_flt(FN_MAX, secs);
 						break;
 					case ST_F_RT_MAX:
 						secs = (double)sv->counters.dtime_max / 1000.0;
-						metric = mkf_flt(FN_MAX, secs);
+						val = mkf_flt(FN_MAX, secs);
 						break;
 					case ST_F_TT_MAX:
 						secs = (double)sv->counters.ttime_max / 1000.0;
-						metric = mkf_flt(FN_MAX, secs);
+						val = mkf_flt(FN_MAX, secs);
 						break;
 					case ST_F_CONNECT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.connect);
+						val = mkf_u64(FN_COUNTER, sv->counters.connect);
 						break;
 					case ST_F_REUSE:
-						metric = mkf_u64(FN_COUNTER, sv->counters.reuse);
+						val = mkf_u64(FN_COUNTER, sv->counters.reuse);
 						break;
 					case ST_F_DRESP:
-						metric = mkf_u64(FN_COUNTER, sv->counters.denied_resp);
+						val = mkf_u64(FN_COUNTER, sv->counters.denied_resp);
 						break;
 					case ST_F_ECON:
-						metric = mkf_u64(FN_COUNTER, sv->counters.failed_conns);
+						val = mkf_u64(FN_COUNTER, sv->counters.failed_conns);
 						break;
 					case ST_F_ERESP:
-						metric = mkf_u64(FN_COUNTER, sv->counters.failed_resp);
+						val = mkf_u64(FN_COUNTER, sv->counters.failed_resp);
 						break;
 					case ST_F_WRETR:
-						metric = mkf_u64(FN_COUNTER, sv->counters.retries);
+						val = mkf_u64(FN_COUNTER, sv->counters.retries);
 						break;
 					case ST_F_WREDIS:
-						metric = mkf_u64(FN_COUNTER, sv->counters.redispatches);
+						val = mkf_u64(FN_COUNTER, sv->counters.redispatches);
 						break;
 					case ST_F_WREW:
-						metric = mkf_u64(FN_COUNTER, sv->counters.failed_rewrites);
+						val = mkf_u64(FN_COUNTER, sv->counters.failed_rewrites);
 						break;
 					case ST_F_EINT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.internal_errors);
+						val = mkf_u64(FN_COUNTER, sv->counters.internal_errors);
 						break;
 					case ST_F_CLI_ABRT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.cli_aborts);
+						val = mkf_u64(FN_COUNTER, sv->counters.cli_aborts);
 						break;
 					case ST_F_SRV_ABRT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.srv_aborts);
+						val = mkf_u64(FN_COUNTER, sv->counters.srv_aborts);
 						break;
 					case ST_F_WEIGHT:
 						weight = (sv->cur_eweight * px->lbprm.wmult + px->lbprm.wdiv - 1) / px->lbprm.wdiv;
-						metric = mkf_u32(FN_AVG, weight);
+						val = mkf_u32(FN_AVG, weight);
 						break;
 					case ST_F_CHECK_STATUS:
 						if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) != CHK_ST_ENABLED)
 							goto next_sv;
-						metric = mkf_u32(FN_OUTPUT, sv->check.status);
+						val = mkf_u32(FN_OUTPUT, sv->check.status);
 						break;
 					case ST_F_CHECK_CODE:
 						if ((sv->check.state & (CHK_ST_ENABLED|CHK_ST_PAUSED)) != CHK_ST_ENABLED)
 							goto next_sv;
-						metric = mkf_u32(FN_OUTPUT, (sv->check.status < HCHK_STATUS_L57DATA) ? 0 : sv->check.code);
+						val = mkf_u32(FN_OUTPUT, (sv->check.status < HCHK_STATUS_L57DATA) ? 0 : sv->check.code);
 						break;
 					case ST_F_CHECK_DURATION:
 						if (sv->check.status < HCHK_STATUS_CHECKED)
 						    goto next_sv;
 						secs = (double)sv->check.duration / 1000.0;
-						metric = mkf_flt(FN_DURATION, secs);
+						val = mkf_flt(FN_DURATION, secs);
 						break;
 					case ST_F_CHKFAIL:
-						metric = mkf_u64(FN_COUNTER, sv->counters.failed_checks);
+						val = mkf_u64(FN_COUNTER, sv->counters.failed_checks);
 						break;
 					case ST_F_CHKDOWN:
-						metric = mkf_u64(FN_COUNTER, sv->counters.down_trans);
+						val = mkf_u64(FN_COUNTER, sv->counters.down_trans);
 						break;
 					case ST_F_DOWNTIME:
-						metric = mkf_u32(FN_COUNTER, srv_downtime(sv));
+						val = mkf_u32(FN_COUNTER, srv_downtime(sv));
 						break;
 					case ST_F_LASTCHG:
-						metric = mkf_u32(FN_AGE, now.tv_sec - sv->last_change);
+						val = mkf_u32(FN_AGE, now.tv_sec - sv->last_change);
 						break;
 					case ST_F_THROTTLE:
-						metric = mkf_u32(FN_AVG, server_throttle_rate(sv));
+						val = mkf_u32(FN_AVG, server_throttle_rate(sv));
 						break;
 					case ST_F_LBTOT:
-						metric = mkf_u64(FN_COUNTER, sv->counters.cum_lbconn);
+						val = mkf_u64(FN_COUNTER, sv->counters.cum_lbconn);
 						break;
 					case ST_F_REQ_TOT:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.cum_req);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.cum_req);
 						break;
 					case ST_F_HRSP_1XX:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[1]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[1]);
 						break;
 					case ST_F_HRSP_2XX:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
 						appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[2]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[2]);
 						break;
 					case ST_F_HRSP_3XX:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
 						appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[3]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[3]);
 						break;
 					case ST_F_HRSP_4XX:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
 						appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[4]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[4]);
 						break;
 					case ST_F_HRSP_5XX:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
 						appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[5]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[5]);
 						break;
 					case ST_F_HRSP_OTHER:
 						if (px->mode != PR_MODE_HTTP)
 							goto next_px;
 						appctx->ctx.stats.flags &= ~PROMEX_FL_METRIC_HDR;
-						metric = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[0]);
+						val = mkf_u64(FN_COUNTER, sv->counters.p.http.rsp[0]);
 						break;
 					case ST_F_SRV_ICUR:
-						metric = mkf_u32(0, sv->curr_idle_conns);
+						val = mkf_u32(0, sv->curr_idle_conns);
 						break;
 					case ST_F_SRV_ILIM:
-						metric = mkf_u32(FO_CONFIG|FN_LIMIT, (sv->max_idle_conns == -1) ? 0 : sv->max_idle_conns);
+						val = mkf_u32(FO_CONFIG|FN_LIMIT, (sv->max_idle_conns == -1) ? 0 : sv->max_idle_conns);
 						break;
 					case ST_F_IDLE_CONN_CUR:
-						metric = mkf_u32(0, sv->curr_idle_nb);
+						val = mkf_u32(0, sv->curr_idle_nb);
 						break;
 					case ST_F_SAFE_CONN_CUR:
-						metric = mkf_u32(0, sv->curr_safe_nb);
+						val = mkf_u32(0, sv->curr_safe_nb);
 						break;
 					case ST_F_USED_CONN_CUR:
-						metric = mkf_u32(0, sv->curr_used_conns);
+						val = mkf_u32(0, sv->curr_used_conns);
 						break;
 					case ST_F_NEED_CONN_EST:
-						metric = mkf_u32(0, sv->est_need_conns);
+						val = mkf_u32(0, sv->est_need_conns);
 						break;
 
 					default:
 						goto next_metric;
 				}
 
-				if (!promex_dump_metric(appctx, htx, prefix, &metric, &out, max))
+				if (!promex_dump_metric(appctx, htx, prefix, &promex_st_metrics[appctx->st2], &val, &out, max))
 					goto full;
 
 			  next_sv:
@@ -1730,7 +1172,6 @@ static int promex_dump_srv_metrics(struct appctx *appctx, struct htx *htx)
 		appctx->ctx.stats.flags |= PROMEX_FL_METRIC_HDR;
 		appctx->ctx.stats.obj1 = proxies_list;
 		appctx->ctx.stats.obj2 = (appctx->ctx.stats.obj1 ? ((struct proxy *)appctx->ctx.stats.obj1)->srv : NULL);
-		appctx->st2 = promex_srv_metrics[appctx->st2];
 	}
 
 
@@ -1760,7 +1201,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 			appctx->ctx.stats.obj1 = NULL;
 			appctx->ctx.stats.obj2 = NULL;
 			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_INFO_METRIC);
-			appctx->st2 = promex_global_metrics[INF_NAME];
+			appctx->st2 = INF_NAME;
 			appctx->st1 = PROMEX_DUMPER_GLOBAL;
 			/* fall through */
 
@@ -1778,7 +1219,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 			appctx->ctx.stats.obj2 = NULL;
 			appctx->ctx.stats.flags &= ~PROMEX_FL_INFO_METRIC;
 			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_FRONT_METRIC);
-			appctx->st2 = promex_front_metrics[ST_F_PXNAME];
+			appctx->st2 = ST_F_PXNAME;
 			appctx->st1 = PROMEX_DUMPER_FRONT;
 			/* fall through */
 
@@ -1796,7 +1237,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 			appctx->ctx.stats.obj2 = NULL;
 			appctx->ctx.stats.flags &= ~PROMEX_FL_FRONT_METRIC;
 			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_BACK_METRIC);
-			appctx->st2 = promex_back_metrics[ST_F_PXNAME];
+			appctx->st2 = ST_F_PXNAME;
 			appctx->st1 = PROMEX_DUMPER_BACK;
 			/* fall through */
 
@@ -1814,7 +1255,7 @@ static int promex_dump_metrics(struct appctx *appctx, struct stream_interface *s
 			appctx->ctx.stats.obj2 = (appctx->ctx.stats.obj1 ? ((struct proxy *)appctx->ctx.stats.obj1)->srv : NULL);
 			appctx->ctx.stats.flags &= ~PROMEX_FL_BACK_METRIC;
 			appctx->ctx.stats.flags |= (PROMEX_FL_METRIC_HDR|PROMEX_FL_SRV_METRIC);
-			appctx->st2 = promex_srv_metrics[ST_F_PXNAME];
+			appctx->st2 = ST_F_PXNAME;
 			appctx->st1 = PROMEX_DUMPER_SRV;
 			/* fall through */
 
-- 
2.29.2

Reply via email to