diff --git a/src/ngx_http_vhost_traffic_status_display_json.c b/src/ngx_http_vhost_traffic_status_display_json.c index f06f378..ae25f13 100644 --- a/src/ngx_http_vhost_traffic_status_display_json.c +++ b/src/ngx_http_vhost_traffic_status_display_json.c @@ -15,6 +15,17 @@ #endif +#if (nginx_version > 1027003) && defined(NGX_HTTP_UPSTREAM_MODIFY) && !defined(NGX_HTTP_UPSTREAM_CHECK) +static u_char * +ngx_http_vhost_traffic_status_display_ug_host( + ngx_http_request_t *r, + ngx_str_t host, + ngx_rbtree_node_t *node, + ngx_rbtree_node_t *sentinel, + ngx_http_upstream_rr_peers_t *peers, + u_char *buf); +#endif + u_char * ngx_http_vhost_traffic_status_display_set_main(ngx_http_request_t *r, u_char *buf) @@ -633,6 +644,50 @@ ngx_http_vhost_traffic_status_display_set_upstream_group(ngx_http_request_t *r, zone = 1; +#if (nginx_version > 1027003) && defined(NGX_HTTP_UPSTREAM_MODIFY) && !defined(NGX_HTTP_UPSTREAM_CHECK) + if (uscf->flags & NGX_HTTP_UPSTREAM_MODIFY) { + peers = uscf->peer.data; + buf = ngx_http_vhost_traffic_status_display_ug_host(r, uscf->host, ctx->rbtree->root, ctx->rbtree->sentinel, peers, buf); + } else { + for (peers = uscf->peer.data; peers; peers = peers->next) { + ngx_http_upstream_rr_peers_rlock(peers); + for (peer = peers->peer; peer; peer = peer->next) { + p = ngx_cpymem(p, uscf->host.data, uscf->host.len); + *p++ = NGX_HTTP_VHOST_TRAFFIC_STATUS_KEY_SEPARATOR; + p = ngx_cpymem(p, peer->name.data, peer->name.len); + + dst.len = uscf->host.len + sizeof("@") - 1 + peer->name.len; + + rc = ngx_http_vhost_traffic_status_node_generate_key(r->pool, &key, &dst, type); + if (rc != NGX_OK) { + ngx_http_upstream_rr_peers_unlock(peers); + return buf; + } + + hash = ngx_crc32_short(key.data, key.len); + node = ngx_http_vhost_traffic_status_node_lookup(ctx->rbtree, &key, hash); + + usn.weight = peer->weight; + usn.max_fails = peer->max_fails; + usn.fail_timeout = peer->fail_timeout; + usn.backup = 0; + usn.down = (peer->fails >= peer->max_fails || peer->down); + usn.name = peer->name; + + if (node != NULL) { + vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; + buf = ngx_http_vhost_traffic_status_display_set_upstream_node(r, buf, &usn, vtsn); + } else { + buf = ngx_http_vhost_traffic_status_display_set_upstream_node(r, buf, &usn, NULL); + } + p = dst.data; + } + ngx_http_upstream_rr_peers_unlock(peers); + } + } + goto last; +#endif + peers = uscf->peer.data; ngx_http_upstream_rr_peers_rlock(peers); @@ -744,6 +799,9 @@ ngx_http_vhost_traffic_status_display_set_upstream_group(ngx_http_request_t *r, } } +#if (nginx_version > 1027003) && defined(NGX_HTTP_UPSTREAM_MODIFY) && !defined(NGX_HTTP_UPSTREAM_CHECK) +last: +#endif if (s == buf) { buf = o; @@ -970,4 +1028,59 @@ ngx_http_vhost_traffic_status_display_set(ngx_http_request_t *r, return buf; } +#if (nginx_version > 1027003) && defined(NGX_HTTP_UPSTREAM_MODIFY) && !defined(NGX_HTTP_UPSTREAM_CHECK) +static u_char * +ngx_http_vhost_traffic_status_display_ug_host( + ngx_http_request_t *r, + ngx_str_t host, + ngx_rbtree_node_t *node, + ngx_rbtree_node_t *sentinel, + ngx_http_upstream_rr_peers_t *peers, + u_char *buf) +{ + ngx_int_t rc; + ngx_http_upstream_server_t usn; + ngx_http_upstream_rr_peer_t *peer; + ngx_http_upstream_rr_peers_t *base_peers; + ngx_http_vhost_traffic_status_node_t *vtsn; + + base_peers = peers; + if (node != sentinel) { + vtsn = (ngx_http_vhost_traffic_status_node_t *) &node->color; + if (vtsn->stat_upstream.type == NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_UG) { + if (vtsn->len >= NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_KEY_LEN + host.len) { + rc = ngx_memn2cmp(host.data, vtsn->data + NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_PREFIX_LEN, host.len, (size_t) host.len); + if (rc == 0) { + usn.name.data = vtsn->data + NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_PREFIX_LEN + host.len + 1; + usn.name.len = vtsn->len - host.len - NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_KEY_LEN; + usn.weight = 0; + usn.max_fails = 0; + usn.fail_timeout = 0; + usn.backup = 0; + usn.down = 0; + while (peers != NULL) { + ngx_http_upstream_rr_peers_rlock(peers); + for (peer = peers->peer; peer; peer = peer->next) { + rc = ngx_memn2cmp(peer->name.data, usn.name.data, peer->name.len, (size_t) usn.name.len); + if (rc == 0) { + usn.weight = peer->weight; + usn.max_fails = peer->max_fails; + usn.fail_timeout = peer->fail_timeout; + usn.backup = 0; + usn.down = (peer->fails >= peer->max_fails || peer->down); + } + } + ngx_http_upstream_rr_peers_unlock(peers); + peers = peers->next; + } + buf = ngx_http_vhost_traffic_status_display_set_upstream_node(r, buf, &usn, vtsn); + } + } + } + buf = ngx_http_vhost_traffic_status_display_ug_host(r, host, node->left, sentinel, base_peers, buf); + buf = ngx_http_vhost_traffic_status_display_ug_host(r, host, node->right, sentinel, base_peers, buf); + } + return buf; +} +#endif /* vi:set ft=c ts=4 sw=4 et fdm=marker: */ diff --git a/src/ngx_http_vhost_traffic_status_display_json.h b/src/ngx_http_vhost_traffic_status_display_json.h index 990ea3d..7816d87 100644 --- a/src/ngx_http_vhost_traffic_status_display_json.h +++ b/src/ngx_http_vhost_traffic_status_display_json.h @@ -180,6 +180,9 @@ "}," #if (NGX_HTTP_CACHE) +#define NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_PREFIX_LEN 3 +#define NGX_HTTP_VHOST_TRAFFIC_STATUS_UPSTREAM_KEY_LEN 4 + #define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CACHE_S "\"cacheZones\":{" #define NGX_HTTP_VHOST_TRAFFIC_STATUS_JSON_FMT_CACHE "\"%V\":{" \ "\"maxSize\":%uA," \