There is a relationship between the state and colour of a server in
stats, however, it is not a one-to-one relationship and the current
implementation has proved fragile.

This patch attempts to address that problem by clearly separating
state and colour.

A follow-up patch will further distinguish between DRAIN states
and DRAINING colours.

Signed-off-by: Simon Horman <ho...@verge.net.au>

---
v2
* First post
---
 src/dumpstats.c | 134 +++++++++++++++++++++++++++++++++++---------------------
 1 file changed, 83 insertions(+), 51 deletions(-)

diff --git a/src/dumpstats.c b/src/dumpstats.c
index 402fb0ae98ad..b505d4e2e172 100644
--- a/src/dumpstats.c
+++ b/src/dumpstats.c
@@ -2934,13 +2934,35 @@ enum srv_stats_state {
        SRV_STATS_STATE_COUNT, /* Must be last */
 };
 
+enum srv_stats_colour {
+       SRV_STATS_COLOUR_DOWN = 0,
+       SRV_STATS_COLOUR_GOING_UP,
+       SRV_STATS_COLOUR_GOING_DOWN,
+       SRV_STATS_COLOUR_UP,
+       SRV_STATS_COLOUR_NOLB,
+       SRV_STATS_COLOUR_DRAINING,
+       SRV_STATS_COLOUR_NO_CHECK,
+
+       SRV_STATS_COLOUR_COUNT, /* Must be last */
+};
+
+static const char *srv_stats_colour_st[SRV_STATS_COLOUR_COUNT] = {
+       [SRV_STATS_COLOUR_DOWN]         = "down",
+       [SRV_STATS_COLOUR_GOING_UP]     = "going_up",
+       [SRV_STATS_COLOUR_GOING_DOWN]   = "going_down",
+       [SRV_STATS_COLOUR_UP]           = "up",
+       [SRV_STATS_COLOUR_NOLB]         = "nolb",
+       [SRV_STATS_COLOUR_DRAINING]     = "draining",
+       [SRV_STATS_COLOUR_NO_CHECK]     = "no_check",
+};
+
 /* Dumps a line for server <sv> and proxy <px> to the trash and uses the state
  * from stream interface <si>, stats flags <flags>, and server state <state>.
  * The caller is responsible for clearing the trash if needed. Returns non-zero
  * if it emits anything, zero otherwise.
  */
 static int stats_dump_sv_stats(struct stream_interface *si, struct proxy *px, 
int flags, struct server *sv,
-                              enum srv_stats_state state)
+                              enum srv_stats_state state, enum 
srv_stats_colour colour)
 {
        struct appctx *appctx = __objt_appctx(si->end);
        struct server *via, *ref;
@@ -2974,8 +2996,8 @@ static int stats_dump_sv_stats(struct stream_interface 
*si, struct proxy *px, in
                        chunk_appendf(&trash, "<tr class=\"maintain\">");
                else
                        chunk_appendf(&trash,
-                                     "<tr class=\"%s%d\">",
-                                     (sv->flags & SRV_F_BACKUP) ? "backup" : 
"active", state);
+                                     "<tr class=\"%s_%s\">",
+                                     (sv->flags & SRV_F_BACKUP) ? "backup" : 
"active", srv_stats_colour_st[colour]);
 
                if ((px->cap & PR_CAP_BE) && px->srv && 
(appctx->ctx.stats.flags & STAT_ADMIN))
                        chunk_appendf(&trash,
@@ -3853,6 +3875,7 @@ static int stats_dump_proxy_to_buffer(struct 
stream_interface *si, struct proxy
                /* stats.sv has been initialized above */
                for (; appctx->ctx.stats.sv != NULL; appctx->ctx.stats.sv = 
sv->next) {
                        enum srv_stats_state sv_state;
+                       enum srv_stats_colour sv_colour;
 
                        if (buffer_almost_full(rep->buf)) {
                                si->flags |= SI_FL_WAIT_ROOM;
@@ -3875,37 +3898,52 @@ static int stats_dump_proxy_to_buffer(struct 
stream_interface *si, struct proxy
 
                        if (sv->state == SRV_ST_RUNNING || sv->state == 
SRV_ST_STARTING) {
                                if ((svs->check.state & CHK_ST_ENABLED) &&
-                                   (svs->check.health < svs->check.rise + 
svs->check.fall - 1))
+                                   (svs->check.health < svs->check.rise + 
svs->check.fall - 1)) {
                                        sv_state = 
SRV_STATS_STATE_UP_GOING_DOWN;
-                               else
+                                       sv_colour = SRV_STATS_COLOUR_GOING_DOWN;
+                               } else {
                                        sv_state = SRV_STATS_STATE_UP;
+                                       sv_colour = SRV_STATS_COLOUR_UP;
+                               }
 
                                if (server_is_draining(sv)) {
-                                       if (sv_state == 
SRV_STATS_STATE_UP_GOING_DOWN)
+                                       if (sv_state == 
SRV_STATS_STATE_UP_GOING_DOWN) {
                                                sv_state = 
SRV_STATS_STATE_DRAIN_GOING_DOWN;
-                                       else
+                                       } else {
                                                sv_state = 
SRV_STATS_STATE_DRAIN;
+                                               sv_colour = 
SRV_STATS_COLOUR_DRAINING;
+                                       }
                                }
 
-                               if (sv_state == SRV_STATS_STATE_UP && 
!(svs->check.state & CHK_ST_ENABLED))
+                               if (sv_state == SRV_STATS_STATE_UP && 
!(svs->check.state & CHK_ST_ENABLED)) {
                                        sv_state = SRV_STATS_STATE_NO_CHECK;
+                                       sv_colour = SRV_STATS_COLOUR_NO_CHECK;
+                               }
                        }
                        else if (sv->state == SRV_ST_STOPPING) {
                                if ((!(sv->check.state & CHK_ST_ENABLED) && 
!sv->track) ||
-                                   (svs->check.health == svs->check.rise + 
svs->check.fall - 1))
+                                   (svs->check.health == svs->check.rise + 
svs->check.fall - 1)) {
                                        sv_state = SRV_STATS_STATE_NOLB;
-                               else
+                                       sv_colour = SRV_STATS_COLOUR_NOLB;
+                               } else {
                                        sv_state = 
SRV_STATS_STATE_NOLB_GOING_DOWN;
+                                       sv_colour = SRV_STATS_COLOUR_GOING_DOWN;
+                               }
                        }
                        else {  /* stopped */
-                               if ((svs->agent.state & CHK_ST_ENABLED) && 
!svs->agent.health)
+                               if ((svs->agent.state & CHK_ST_ENABLED) && 
!svs->agent.health) {
                                        sv_state = SRV_STATS_STATE_DOWN_AGENT;
-                               else if ((svs->check.state & CHK_ST_ENABLED) && 
!svs->check.health)
+                                       sv_colour = SRV_STATS_COLOUR_DOWN;
+                               } else if ((svs->check.state & CHK_ST_ENABLED) 
&& !svs->check.health) {
                                        sv_state = SRV_STATS_STATE_DOWN; /* 
DOWN */
-                               else if ((svs->agent.state & CHK_ST_ENABLED) || 
(svs->check.state & CHK_ST_ENABLED))
+                                       sv_colour = SRV_STATS_COLOUR_DOWN;
+                               } else if ((svs->agent.state & CHK_ST_ENABLED) 
|| (svs->check.state & CHK_ST_ENABLED)) {
                                        sv_state = SRV_STATS_STATE_GOING_UP;
-                               else
+                                       sv_colour = SRV_STATS_COLOUR_GOING_UP;
+                               } else {
                                        sv_state = SRV_STATS_STATE_DOWN; /* 
DOWN, unchecked */
+                                       sv_colour = SRV_STATS_COLOUR_DOWN;
+                               }
                        }
 
                        if (((sv_state <= 1) || (sv->admin & SRV_ADMF_MAINT)) 
&& (appctx->ctx.stats.flags & STAT_HIDE_DOWN)) {
@@ -3914,7 +3952,7 @@ static int stats_dump_proxy_to_buffer(struct 
stream_interface *si, struct proxy
                                continue;
                        }
 
-                       if (stats_dump_sv_stats(si, px, uri ? uri->flags : 0, 
sv, sv_state)) {
+                       if (stats_dump_sv_stats(si, px, uri ? uri->flags : 0, 
sv, sv_state, sv_colour)) {
                                if (bi_putchk(rep, &trash) == -1) {
                                        si->flags |= SI_FL_WAIT_ROOM;
                                        return 0;
@@ -4015,26 +4053,20 @@ static void stats_dump_html_head(struct uri_auth *uri)
                      ".frontend        {background: #e8e8d0;}\n"
                      ".socket  {background: #d0d0d0;}\n"
                      ".backend {background: #e8e8d0;}\n"
-                     ".active0 {background: #ff9090;}\n"
-                     ".active1 {background: #ff9090;}\n"
-                     ".active2 {background: #ffd020;}\n"
-                     ".active3 {background: #ffffa0;}\n"
-                     ".active4 {background: #c0ffc0;}\n"
-                     ".active5 {background: #ffffa0;}\n"  /* NOLB state shows 
same as going down */
-                     ".active6 {background: #20a0ff;}\n"  /* NOLB state shows 
different to be detected */
-                     ".active7 {background: #ffffa0;}\n"  /* DRAIN going down 
= same as going down */
-                     ".active8 {background: #20a0FF;}\n"  /* DRAIN must be 
detected (weight=0) */
-                     ".active9 {background: #e0e0e0;}\n"
-                     ".backup0 {background: #ff9090;}\n"
-                     ".backup1 {background: #ff9090;}\n"
-                     ".backup2 {background: #ff80ff;}\n"
-                     ".backup3 {background: #c060ff;}\n"
-                     ".backup4 {background: #b0d0ff;}\n"
-                     ".backup5 {background: #c060ff;}\n"  /* NOLB state shows 
same as going down */
-                     ".backup6 {background: #90b0e0;}\n"  /* NOLB state shows 
same as going down */
-                     ".backup7 {background: #c060ff;}\n"
-                     ".backup8 {background: #cc9900;}\n"
-                     ".backup9 {background: #e0e0e0;}\n"
+                     ".active_down             {background: #ff9090;}\n"
+                     ".active_going_up         {background: #ffd020;}\n"
+                     ".active_going_down       {background: #ffffa0;}\n"
+                     ".active_up               {background: #c0ffc0;}\n"
+                     ".active_nolb             {background: #20a0ff;}\n"
+                     ".active_draining         {background: #20a0FF;}\n"
+                     ".active_no_check         {background: #e0e0e0;}\n"
+                     ".backup_down             {background: #ff9090;}\n"
+                     ".backup_going_up         {background: #ff80ff;}\n"
+                     ".backup_going_down       {background: #c060ff;}\n"
+                     ".backup_up               {background: #b0d0ff;}\n"
+                     ".backup_nolb             {background: #90b0e0;}\n"
+                     ".backup_draining         {background: #cc9900;}\n"
+                     ".backup_no_check         {background: #e0e0e0;}\n"
                      ".maintain        {background: #c07820;}\n"
                      ".rls      {letter-spacing: 0.2em; margin-right: 1px;}\n" 
/* right letter spacing (used for grouping digits) */
                      "\n"
@@ -4110,21 +4142,21 @@ static void stats_dump_html_info(struct 
stream_interface *si, struct uri_auth *u
                      "Running tasks: %d/%d; idle = %d %%<br>\n"
                      "</td><td align=\"center\" nowrap>\n"
                      "<table class=\"lgd\"><tr>\n"
-                     "<td class=\"active4\">&nbsp;</td><td 
class=\"noborder\">active UP </td>"
-                     "<td class=\"backup4\">&nbsp;</td><td 
class=\"noborder\">backup UP </td>"
+                     "<td class=\"active_up\">&nbsp;</td><td 
class=\"noborder\">active UP </td>"
+                     "<td class=\"backup_up\">&nbsp;</td><td 
class=\"noborder\">backup UP </td>"
                      "</tr><tr>\n"
-                     "<td class=\"active3\"></td><td class=\"noborder\">active 
UP, going down </td>"
-                     "<td class=\"backup3\"></td><td class=\"noborder\">backup 
UP, going down </td>"
+                     "<td class=\"active_going_down\"></td><td 
class=\"noborder\">active UP, going down </td>"
+                     "<td class=\"backup_going_down\"></td><td 
class=\"noborder\">backup UP, going down </td>"
                      "</tr><tr>\n"
-                     "<td class=\"active2\"></td><td class=\"noborder\">active 
DOWN, going up </td>"
-                     "<td class=\"backup2\"></td><td class=\"noborder\">backup 
DOWN, going up </td>"
+                     "<td class=\"active_going_up\"></td><td 
class=\"noborder\">active DOWN, going up </td>"
+                     "<td class=\"backup_going_up\"></td><td 
class=\"noborder\">backup DOWN, going up </td>"
                      "</tr><tr>\n"
-                     "<td class=\"active0\"></td><td class=\"noborder\">active 
or backup DOWN &nbsp;</td>"
-                     "<td class=\"active9\"></td><td class=\"noborder\">not 
checked </td>"
+                     "<td class=\"active_down\"></td><td 
class=\"noborder\">active or backup DOWN &nbsp;</td>"
+                     "<td class=\"active_no_check\"></td><td 
class=\"noborder\">not checked </td>"
                      "</tr><tr>\n"
                      "<td class=\"maintain\"></td><td class=\"noborder\" 
colspan=\"3\">active or backup DOWN for maintenance (MAINT) &nbsp;</td>"
                      "</tr><tr>\n"
-                     "<td class=\"active8\"></td><td class=\"noborder\" 
colspan=\"3\">active or backup SOFT STOPPED for maintenance &nbsp;</td>"
+                     "<td class=\"active_draining\"></td><td 
class=\"noborder\" colspan=\"3\">active or backup SOFT STOPPED for maintenance 
&nbsp;</td>"
                      "</tr></table>\n"
                      "Note: \"NOLB\"/\"DRAIN\" = UP with load-balancing 
disabled."
                      "</td>"
@@ -4226,7 +4258,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                switch (appctx->ctx.stats.st_code) {
                case STAT_STATUS_DONE:
                        chunk_appendf(&trash,
-                                     "<p><div class=active4>"
+                                     "<p><div class=active_up>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "Action processed successfully."
                                      "</div>\n", uri->uri_prefix,
@@ -4236,7 +4268,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                case STAT_STATUS_NONE:
                        chunk_appendf(&trash,
-                                     "<p><div class=active3>"
+                                     "<p><div class=active_going_down>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "Nothing has changed."
                                      "</div>\n", uri->uri_prefix,
@@ -4246,7 +4278,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                case STAT_STATUS_PART:
                        chunk_appendf(&trash,
-                                     "<p><div class=active3>"
+                                     "<p><div class=active_going_down>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "Action partially processed.<br>"
                                      "Some server names are probably unknown 
or ambiguous (duplicated names in the backend)."
@@ -4257,7 +4289,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                case STAT_STATUS_ERRP:
                        chunk_appendf(&trash,
-                                     "<p><div class=active0>"
+                                     "<p><div class=active_down>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "Action not processed because of invalid 
parameters."
                                      "<ul>"
@@ -4272,7 +4304,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                case STAT_STATUS_EXCD:
                        chunk_appendf(&trash,
-                                     "<p><div class=active0>"
+                                     "<p><div class=active_down>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "<b>Action not processed : the buffer 
couldn't store all the data.<br>"
                                      "You should retry with less servers at a 
time.</b>"
@@ -4283,7 +4315,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                case STAT_STATUS_DENY:
                        chunk_appendf(&trash,
-                                     "<p><div class=active0>"
+                                     "<p><div class=active_down>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "<b>Action denied.</b>"
                                      "</div>\n", uri->uri_prefix,
@@ -4293,7 +4325,7 @@ static void stats_dump_html_info(struct stream_interface 
*si, struct uri_auth *u
                        break;
                default:
                        chunk_appendf(&trash,
-                                     "<p><div class=active9>"
+                                     "<p><div class=active_no_check>"
                                      "<a class=lfsb href=\"%s%s%s%s\" 
title=\"Remove this message\">[X]</a> "
                                      "Unexpected result."
                                      "</div>\n", uri->uri_prefix,
-- 
2.1.4


Reply via email to