]> git.ipfire.org Git - thirdparty/haproxy.git/commitdiff
MINOR: stats: Add JSON export from the stats page
authorChristopher Faulet <cfaulet@haproxy.com>
Mon, 9 Sep 2019 13:50:54 +0000 (15:50 +0200)
committerChristopher Faulet <cfaulet@haproxy.com>
Tue, 10 Sep 2019 08:29:54 +0000 (10:29 +0200)
It is now possible to export stats using the JSON format from the HTTP stats
page. Like for the CSV export, to export stats in JSON, you must add the option
";json" on the stats URL. It is also possible to dump the JSON schema with the
option ";json-schema". Corresponding Links have been added on the HTML page.

This patch fixes the issue #263.

include/types/stats.h
src/http_ana.c
src/stats.c

index 2a71ff64ef54b6ef3d88da4e4c1f68e96ebdcf1e..d99d51911543ec11234fd356d8a8ebde40465d24 100644 (file)
 #define STAT_NO_REFRESH 0x00000010     /* do not automatically refresh the stats page */
 #define STAT_ADMIN      0x00000020     /* indicate a stats admin level */
 #define STAT_CHUNKED    0x00000040      /* use chunked encoding (HTTP/1.1) */
+#define STAT_JSON_SCHM  0x00000080      /* dump the json schema */
 #define STAT_BOUND      0x00800000     /* bound statistics to selected proxies/types/services */
 #define STAT_STARTED    0x01000000     /* some output has occurred */
 
+#define STAT_FMT_MASK   0x00000007
+
 #define STATS_TYPE_FE  0
 #define STATS_TYPE_BE  1
 #define STATS_TYPE_SV  2
index eef0c09cacb7194a965c9f2c8f22cd8908c1921c..6fff39b30f625ff9466b37e54e4e1fa84cb26634 100644 (file)
@@ -4399,19 +4399,35 @@ static int http_handle_stats(struct stream *s, struct channel *req)
 
        for (h = lookup; h <= end - 4; h++) {
                if (memcmp(h, ";csv", 4) == 0) {
-                       appctx->ctx.stats.flags &= ~STAT_FMT_HTML;
+                       appctx->ctx.stats.flags &= ~(STAT_FMT_MASK|STAT_JSON_SCHM);
                        break;
                }
        }
 
        for (h = lookup; h <= end - 6; h++) {
                if (memcmp(h, ";typed", 6) == 0) {
-                       appctx->ctx.stats.flags &= ~STAT_FMT_HTML;
+                       appctx->ctx.stats.flags &= ~(STAT_FMT_MASK|STAT_JSON_SCHM);
                        appctx->ctx.stats.flags |= STAT_FMT_TYPED;
                        break;
                }
        }
 
+       for (h = lookup; h <= end - 5; h++) {
+               if (memcmp(h, ";json", 5) == 0) {
+                       appctx->ctx.stats.flags &= ~(STAT_FMT_MASK|STAT_JSON_SCHM);
+                       appctx->ctx.stats.flags |= STAT_FMT_JSON;
+                       break;
+               }
+       }
+
+       for (h = lookup; h <= end - 12; h++) {
+               if (memcmp(h, ";json-schema", 12) == 0) {
+                       appctx->ctx.stats.flags &= ~STAT_FMT_MASK;
+                       appctx->ctx.stats.flags |= STAT_JSON_SCHM;
+                       break;
+               }
+       }
+
        for (h = lookup; h <= end - 8; h++) {
                if (memcmp(h, ";st=", 4) == 0) {
                        int i;
index 34efbfbbb0e9411ef418a182330fa24610f4532a..e59ad10bb86bb5d216fa00fa7acf8511c5eb7696 100644 (file)
@@ -251,6 +251,7 @@ static THREAD_LOCAL struct field info[INF_TOTAL_FIELDS];
 /* one line of stats */
 static THREAD_LOCAL struct field stats[ST_F_TOTAL_FIELDS];
 
+static void stats_dump_json_schema(struct buffer *out);
 
 static int stats_putchk(struct channel *chn, struct htx *htx, struct buffer *chk)
 {
@@ -2526,6 +2527,12 @@ static void stats_dump_html_info(struct stream_interface *si, struct uri_auth *u
                      (uri->refresh > 0) ? ";norefresh" : "",
                      scope_txt);
 
+       chunk_appendf(&trash,
+                     "<li><a href=\"%s;json%s%s\">JSON export</a> (<a href=\"%s;json-schema\">schema</a>)<br>\n",
+                     uri->uri_prefix,
+                     (uri->refresh > 0) ? ";norefresh" : "",
+                     scope_txt, uri->uri_prefix);
+
        chunk_appendf(&trash,
                      "</ul></td>"
                      "<td align=\"left\" valign=\"top\" nowrap width=\"1%%\">"
@@ -2682,6 +2689,8 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct htx *ht
        case STAT_ST_HEAD:
                if (appctx->ctx.stats.flags & STAT_FMT_HTML)
                        stats_dump_html_head(uri);
+               else if (appctx->ctx.stats.flags & STAT_JSON_SCHM)
+                       stats_dump_json_schema(&trash);
                else if (appctx->ctx.stats.flags & STAT_FMT_JSON)
                        stats_dump_json_header();
                else if (!(appctx->ctx.stats.flags & STAT_FMT_TYPED))
@@ -2690,6 +2699,10 @@ static int stats_dump_stat_to_buffer(struct stream_interface *si, struct htx *ht
                if (!stats_putchk(rep, htx, &trash))
                        goto full;
 
+               if (appctx->ctx.stats.flags & STAT_JSON_SCHM) {
+                       appctx->st2 = STAT_ST_FIN;
+                       return 1;
+               }
                appctx->st2 = STAT_ST_INFO;
                /* fall through */
 
@@ -3124,6 +3137,10 @@ static int stats_send_http_headers(struct stream_interface *si, struct htx *htx)
                if (!htx_add_header(htx, ist("Content-Type"), ist("text/html")))
                        goto full;
        }
+       else if (appctx->ctx.stats.flags & (STAT_FMT_JSON|STAT_JSON_SCHM)) {
+               if (!htx_add_header(htx, ist("Content-Type"), ist("application/json")))
+                       goto full;
+       }
        else {
                if (!htx_add_header(htx, ist("Content-Type"), ist("text/plain")))
                        goto full;