mirror of
https://github.com/SKUDONET/zproxy.git
synced 2025-10-26 11:27:35 +00:00
state: remove unordered_map usage
Replacing unordered_map usage with list_head. This also includes the switch from shared_ptr to a raw C pointer. Yes, I moved around a lot of the functions, particularly in the header file, but it was a mess and I was having difficulty keeping track of function declarations. Please pardon the noise. The refcnt variable was removed from zproxy_backend_state and zproxy_service_state, since they should only ever be used directly in state.cpp. Signed-off-by: Nicolás A. Ortega Froysa <nicolas.ortega@zevenet.com>
This commit is contained in:
parent
60afe68f7b
commit
81351bb97c
185
include/state.h
185
include/state.h
@ -18,19 +18,20 @@
|
||||
#ifndef _ZPROXY_STATE_H_
|
||||
#define _ZPROXY_STATE_H_
|
||||
|
||||
#include "config.h"
|
||||
#include "list.h"
|
||||
#include "session.h"
|
||||
#include "zcu_log.h"
|
||||
#include <sys/time.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <memory>
|
||||
#include <ev.h>
|
||||
#include <atomic>
|
||||
|
||||
#define TIMEOUT_SESSIONS 1
|
||||
#define COUNTER_SESSIONS 10000
|
||||
|
||||
struct zproxy_backend_state;
|
||||
struct zproxy_service_state;
|
||||
|
||||
struct zproxy_stats {
|
||||
std::atomic<int32_t> http_2xx_hits {0}; ///< Total number of 2xx responses since initialization.
|
||||
std::atomic<int32_t> http_3xx_hits {0}; ///< Total number of 3xx responses since initialization.
|
||||
@ -41,24 +42,13 @@ struct zproxy_stats {
|
||||
std::atomic<int32_t> conn_pending {0}; ///< Number of connections pending at the moment.
|
||||
};
|
||||
|
||||
struct zproxy_backend_state {
|
||||
zproxy_stats backend_stats;
|
||||
uint32_t refcnt{1};
|
||||
};
|
||||
|
||||
struct zproxy_service_state {
|
||||
std::unordered_map<std::string, std::shared_ptr<zproxy_backend_state>> backends;
|
||||
struct zproxy_sessions *sessions;
|
||||
uint32_t refcnt{1};
|
||||
};
|
||||
|
||||
struct zproxy_http_state {
|
||||
list_head list;
|
||||
uint32_t proxy_id{UINT32_MAX};
|
||||
uint32_t refcnt{1};
|
||||
struct list_head list;
|
||||
uint32_t proxy_id;
|
||||
uint32_t refcnt;
|
||||
struct ev_timer timer;
|
||||
zproxy_stats listener_stats;
|
||||
std::unordered_map<std::string, std::shared_ptr<zproxy_service_state>> services;
|
||||
struct zproxy_stats listener_stats;
|
||||
struct list_head services;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -85,9 +75,64 @@ inline void zproxy_stats_dump(const struct zproxy_stats *stats)
|
||||
stats->conn_pending.load());
|
||||
}
|
||||
|
||||
zproxy_stats *zproxy_stats_backend_get(
|
||||
const struct zproxy_http_state *state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
struct zproxy_stats *
|
||||
zproxy_stats_backend_get(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
int zproxy_state_backend_add(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend);
|
||||
/**
|
||||
* Increment the backend stat for a given HTTP code.
|
||||
*
|
||||
* @param http_state HTTP state object that contains the backend stats.
|
||||
* @param backend_cfg Configuration for the backend.
|
||||
* @param code The HTTP code to increment.
|
||||
*
|
||||
* @return If the HTTP code is valid it will return 1. Return is -1 the HTTP
|
||||
* code is invalid.
|
||||
*/
|
||||
int zproxy_stats_backend_inc_code(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg,
|
||||
const int code);
|
||||
/**
|
||||
* Increment the connections established statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
void zproxy_stats_backend_inc_conn_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
/**
|
||||
* Decrement the connections established statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
void zproxy_stats_backend_dec_conn_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
/**
|
||||
* Increment the connections pending statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
int zproxy_stats_backend_inc_conn_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
/**
|
||||
* Decrement the connections pending statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
int zproxy_stats_backend_dec_conn_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
int zproxy_stats_backend_get_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
int zproxy_stats_backend_get_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
struct zproxy_sessions *
|
||||
zproxy_state_get_service_sessions(const char *service,
|
||||
const struct list_head *service_list);
|
||||
|
||||
/**
|
||||
* Increment the listener stat for a given HTTP code.
|
||||
@ -98,7 +143,8 @@ zproxy_stats *zproxy_stats_backend_get(
|
||||
* @return If the HTTP code is valid it will return 1. Return is -1 the HTTP
|
||||
* code is invalid.
|
||||
*/
|
||||
inline int zproxy_stats_listener_inc_code(struct zproxy_http_state *http_state, const int code)
|
||||
inline int zproxy_stats_listener_inc_code(struct zproxy_http_state *http_state,
|
||||
const int code)
|
||||
{
|
||||
if(code >= 500)
|
||||
http_state->listener_stats.http_5xx_hits++;
|
||||
@ -112,7 +158,6 @@ inline int zproxy_stats_listener_inc_code(struct zproxy_http_state *http_state,
|
||||
return -1;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the listener stat for WAF hits.
|
||||
*
|
||||
@ -122,99 +167,25 @@ inline void zproxy_stats_listener_inc_waf(struct zproxy_http_state *http_state)
|
||||
{
|
||||
http_state->listener_stats.http_waf_hits++;
|
||||
}
|
||||
|
||||
inline void zproxy_stats_listener_inc_conn_established(
|
||||
struct zproxy_http_state *http_state)
|
||||
inline void zproxy_stats_listener_inc_conn_established(struct zproxy_http_state *http_state)
|
||||
{
|
||||
http_state->listener_stats.conn_established++;
|
||||
}
|
||||
|
||||
inline void zproxy_stats_listener_dec_conn_established(
|
||||
struct zproxy_http_state *http_state)
|
||||
inline void zproxy_stats_listener_dec_conn_established(struct zproxy_http_state *http_state)
|
||||
{
|
||||
http_state->listener_stats.conn_established--;
|
||||
}
|
||||
|
||||
inline void zproxy_stats_listener_inc_conn_pending(
|
||||
struct zproxy_http_state *http_state)
|
||||
inline void zproxy_stats_listener_inc_conn_pending(struct zproxy_http_state *http_state)
|
||||
{
|
||||
http_state->listener_stats.conn_pending++;
|
||||
}
|
||||
|
||||
inline void zproxy_stats_listener_dec_conn_pending(
|
||||
struct zproxy_http_state *http_state)
|
||||
inline void zproxy_stats_listener_dec_conn_pending(struct zproxy_http_state *http_state)
|
||||
{
|
||||
http_state->listener_stats.conn_pending--;
|
||||
}
|
||||
|
||||
/**
|
||||
* Increment the backend stat for a given HTTP code.
|
||||
*
|
||||
* @param http_state HTTP state object that contains the backend stats.
|
||||
* @param backend_cfg Configuration for the backend.
|
||||
* @param code The HTTP code to increment.
|
||||
*
|
||||
* @return If the HTTP code is valid it will return 1. Return is -1 the HTTP
|
||||
* code is invalid.
|
||||
*/
|
||||
int zproxy_stats_backend_inc_code(struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg,
|
||||
int code);
|
||||
|
||||
/**
|
||||
* Increment the connections established statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
void zproxy_stats_backend_inc_conn_established(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
/**
|
||||
* Decrement the connections established statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
void zproxy_stats_backend_dec_conn_established(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
/**
|
||||
* Increment the connections pending statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
int zproxy_stats_backend_inc_conn_pending(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
/**
|
||||
* Decrement the connections pending statistics for a given backend.
|
||||
*
|
||||
* @param http_state State object for the target listener.
|
||||
* @param backend_cfg Configuration of the the backend to increment for.
|
||||
*/
|
||||
int zproxy_stats_backend_dec_conn_pending(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
int zproxy_stats_backend_get_pending(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
int zproxy_stats_backend_get_established(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
struct zproxy_stats *zproxy_stats_backend_get(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg);
|
||||
|
||||
void zproxy_state_purge(struct zproxy_proxy_cfg *proxy);
|
||||
struct zproxy_http_state *zproxy_state_init(const struct zproxy_proxy_cfg *proxy);
|
||||
struct zproxy_http_state *
|
||||
zproxy_state_init(const struct zproxy_proxy_cfg *proxy);
|
||||
void zproxy_state_purge(const struct zproxy_proxy_cfg *proxy);
|
||||
/**
|
||||
* @brief Looks up the corresponding zproxy_http_state for a given proxy ID.
|
||||
*
|
||||
@ -234,9 +205,5 @@ struct zproxy_http_state *zproxy_state_lookup(uint32_t proxy_id);
|
||||
*/
|
||||
void zproxy_state_release(struct zproxy_http_state **http_state);
|
||||
void zproxy_state_cfg_update(struct zproxy_cfg *cfg);
|
||||
void zproxy_state_backend_add(struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend);
|
||||
struct zproxy_sessions *zproxy_state_get_session(const std::string &service,
|
||||
std::unordered_map<std::string, std::shared_ptr<struct zproxy_service_state>> *service_map);
|
||||
|
||||
#endif
|
||||
|
||||
@ -255,7 +255,8 @@ static enum ws_responses handle_get(const std::string &req_path,
|
||||
return WS_HTTP_404;
|
||||
}
|
||||
zproxy_sessions *sessions =
|
||||
zproxy_state_get_session(service_id, &state->services);
|
||||
zproxy_state_get_service_sessions(service_id.c_str(),
|
||||
&state->services);
|
||||
if (!sessions) {
|
||||
*resp_buf = zproxy_json_return_err("Couldn't find sessions for service %s in listener %d",
|
||||
service_id.c_str(),
|
||||
@ -325,7 +326,8 @@ static enum ws_responses handle_patch(const std::string &req_path,
|
||||
return WS_HTTP_404;
|
||||
}
|
||||
zproxy_sessions *sessions =
|
||||
zproxy_state_get_session(service_id, &state->services);
|
||||
zproxy_state_get_service_sessions(service_id.c_str(),
|
||||
&state->services);
|
||||
if (!sessions) {
|
||||
zproxy_state_release(&state);
|
||||
*resp_buf = zproxy_json_return_err("Service %s not found.",
|
||||
@ -413,7 +415,8 @@ static enum ws_responses handle_patch(const std::string &req_path,
|
||||
return WS_HTTP_404;
|
||||
}
|
||||
zproxy_sessions *sessions =
|
||||
zproxy_state_get_session(service_id, &state->services);
|
||||
zproxy_state_get_service_sessions(service_id.c_str(),
|
||||
&state->services);
|
||||
if (!sessions) {
|
||||
zproxy_state_release(&state);
|
||||
*resp_buf = zproxy_json_return_err("Service %s not found.",
|
||||
@ -452,7 +455,7 @@ static enum ws_responses handle_patch(const std::string &req_path,
|
||||
}
|
||||
for (auto &j : i.services) {
|
||||
struct zproxy_sessions *sessions;
|
||||
sessions = zproxy_state_get_session(j.name, &state->services);
|
||||
sessions = zproxy_state_get_service_sessions(j.name, &state->services);
|
||||
if (!sessions) {
|
||||
*resp_buf = zproxy_json_return_err("Service %s doesn't exist.",
|
||||
j.name);
|
||||
@ -511,7 +514,8 @@ static enum ws_responses handle_delete(const std::string &req_path,
|
||||
return WS_HTTP_404;
|
||||
}
|
||||
zproxy_sessions *sessions =
|
||||
zproxy_state_get_session(service_id, &state->services);
|
||||
zproxy_state_get_service_sessions(service_id.c_str(),
|
||||
&state->services);
|
||||
if (!sessions) {
|
||||
zproxy_state_release(&state);
|
||||
*resp_buf = zproxy_json_return_err("Service %s not found.",
|
||||
@ -622,7 +626,8 @@ static enum ws_responses handle_put(const std::string &req_path,
|
||||
return WS_HTTP_404;
|
||||
}
|
||||
zproxy_sessions *sessions =
|
||||
zproxy_state_get_session(service_id, &state->services);
|
||||
zproxy_state_get_service_sessions(service_id.c_str(),
|
||||
&state->services);
|
||||
if (!sessions) {
|
||||
zproxy_state_release(&state);
|
||||
*resp_buf = zproxy_json_return_err("Service %s not found.",
|
||||
|
||||
@ -175,7 +175,9 @@ static int zproxy_http_request_head_rcv(struct zproxy_http_ctx *ctx)
|
||||
list_for_each_entry(service, &cfg->service_list, list) {
|
||||
if (zproxy_service_select(&stream->request, service)) {
|
||||
stream->service_config = service;
|
||||
stream->session = zproxy_state_get_session(service->name, &state->services);
|
||||
stream->session =
|
||||
zproxy_state_get_service_sessions(service->name,
|
||||
&state->services);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
26
src/json.cpp
26
src/json.cpp
@ -151,11 +151,12 @@ static json_t *serialize_service_sessions(const struct zproxy_service_cfg *servi
|
||||
static json_t *serialize_service(const struct zproxy_service_cfg *service_cfg,
|
||||
const struct zproxy_http_state *state)
|
||||
{
|
||||
struct zproxy_monitor_service_state *service_state;
|
||||
const struct zproxy_monitor_service_state *service_monitor;
|
||||
struct zproxy_sessions *service_sessions;
|
||||
json_t *service;
|
||||
|
||||
service_state = zproxy_monitor_service_state_lookup(service_cfg->name);
|
||||
if (!service_state)
|
||||
service_monitor = zproxy_monitor_service_state_lookup(service_cfg->name);
|
||||
if (!service_monitor)
|
||||
return NULL;
|
||||
|
||||
service = json_object();
|
||||
@ -163,9 +164,15 @@ static json_t *serialize_service(const struct zproxy_service_cfg *service_cfg,
|
||||
serialize_service_backends(service_cfg, state));
|
||||
|
||||
json_object_set_new(service, "name", json_string(service_cfg->name));
|
||||
json_object_set_new(service, "priority", json_integer(service_state->priority));
|
||||
json_object_set_new(service, "priority", json_integer(service_monitor->priority));
|
||||
service_sessions =
|
||||
zproxy_state_get_service_sessions(service_cfg->name,
|
||||
&state->services);
|
||||
if (!service_sessions)
|
||||
return NULL;
|
||||
json_object_set_new(service, "sessions",
|
||||
serialize_service_sessions(service_cfg, state->services.at(service_cfg->name)->sessions));
|
||||
serialize_service_sessions(service_cfg,
|
||||
service_sessions));
|
||||
|
||||
return service;
|
||||
}
|
||||
@ -313,6 +320,7 @@ char *zproxy_json_encode_glob_sessions(const struct zproxy_cfg *cfg)
|
||||
char *buf;
|
||||
const struct zproxy_proxy_cfg *proxy = NULL;
|
||||
const struct zproxy_service_cfg *service = NULL;
|
||||
struct zproxy_sessions *service_sessions;
|
||||
struct zproxy_http_state *state = NULL;
|
||||
json_t *json_obj = json_array();
|
||||
|
||||
@ -334,9 +342,15 @@ char *zproxy_json_encode_glob_sessions(const struct zproxy_cfg *cfg)
|
||||
json_object_set_new(serv_obj, "name",
|
||||
json_string(service->name));
|
||||
|
||||
service_sessions =
|
||||
zproxy_state_get_service_sessions(service->name,
|
||||
&state->services);
|
||||
if (!service_sessions)
|
||||
return NULL;
|
||||
|
||||
json_t *sess_arr =
|
||||
serialize_service_sessions(service,
|
||||
state->services.at(service->name)->sessions);
|
||||
service_sessions);
|
||||
json_object_set_new(serv_obj, "sessions", sess_arr);
|
||||
json_array_append_new(serv_arr, serv_obj);
|
||||
}
|
||||
|
||||
517
src/state.cpp
517
src/state.cpp
@ -15,10 +15,17 @@
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ev.h>
|
||||
#include <assert.h>
|
||||
#include <pthread.h>
|
||||
#include <sys/syslog.h>
|
||||
|
||||
#include "config.h"
|
||||
#include "zcu_log.h"
|
||||
#include "zproxy.h"
|
||||
#include "state.h"
|
||||
#include "list.h"
|
||||
@ -26,13 +33,88 @@
|
||||
#include "session.h"
|
||||
#include "proxy.h"
|
||||
|
||||
struct zproxy_backend_state {
|
||||
struct list_head list;
|
||||
char id[CONFIG_IDENT_MAX];
|
||||
struct zproxy_stats backend_stats;
|
||||
};
|
||||
|
||||
struct zproxy_service_state {
|
||||
struct list_head list;
|
||||
char name[CONFIG_IDENT_MAX];
|
||||
struct list_head backends;
|
||||
struct zproxy_sessions *sessions;
|
||||
};
|
||||
|
||||
static LIST_HEAD(state_list);
|
||||
static pthread_mutex_t list_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP;
|
||||
|
||||
static void zproxy_state_maintenance_cb(struct ev_loop *loop, ev_timer *timer, int events)
|
||||
static struct zproxy_backend_state *
|
||||
zproxy_state_backend_lookup(const struct list_head *backend_list,
|
||||
const char *backend_id)
|
||||
{
|
||||
struct zproxy_backend_state *backend_state;
|
||||
|
||||
list_for_each_entry(backend_state, backend_list, list) {
|
||||
if (strcmp(backend_state->id, backend_id) == 0)
|
||||
return backend_state;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct zproxy_service_state *
|
||||
zproxy_state_service_lookup(const struct list_head *service_list,
|
||||
const char *name)
|
||||
{
|
||||
struct zproxy_service_state *service_state;
|
||||
|
||||
list_for_each_entry(service_state, service_list, list) {
|
||||
if (strcmp(name, service_state->name) == 0)
|
||||
return service_state;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct zproxy_http_state *_zproxy_state_lookup(uint32_t proxy_id)
|
||||
{
|
||||
struct zproxy_http_state *state;
|
||||
|
||||
list_for_each_entry(state, &state_list, list) {
|
||||
if(state->proxy_id == proxy_id) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct zproxy_http_state *zproxy_state_lookup(uint32_t proxy_id)
|
||||
{
|
||||
struct zproxy_http_state *state;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
state = _zproxy_state_lookup(proxy_id);
|
||||
state->refcnt++;
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
void zproxy_state_release(struct zproxy_http_state **http_state)
|
||||
{
|
||||
(*http_state)->refcnt--;
|
||||
*http_state = NULL;
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
}
|
||||
|
||||
static void zproxy_state_maintenance_cb(struct ev_loop *loop, ev_timer *timer,
|
||||
int events)
|
||||
{
|
||||
unsigned long counter = COUNTER_SESSIONS; // avoid CPU abuse of garbage recollector
|
||||
struct zproxy_http_state *state;
|
||||
struct zproxy_service_state *service_state;
|
||||
|
||||
Time::updateTime();
|
||||
ev_timer_stop(loop, timer);
|
||||
@ -40,9 +122,9 @@ static void zproxy_state_maintenance_cb(struct ev_loop *loop, ev_timer *timer, i
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
state = container_of(timer, struct zproxy_http_state, timer);
|
||||
|
||||
for (auto & service : state->services) {
|
||||
counter -= service.second->sessions->size;
|
||||
zproxy_sessions_remove_expired(service.second->sessions);
|
||||
list_for_each_entry(service_state, &state->services, list) {
|
||||
counter -= service_state->sessions->size;
|
||||
zproxy_sessions_remove_expired(service_state->sessions);
|
||||
if (counter<=0)
|
||||
break;
|
||||
}
|
||||
@ -51,49 +133,60 @@ static void zproxy_state_maintenance_cb(struct ev_loop *loop, ev_timer *timer, i
|
||||
ev_timer_again(loop, timer);
|
||||
}
|
||||
|
||||
struct zproxy_stats *zproxy_stats_backend_get(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
struct zproxy_stats *
|
||||
zproxy_stats_backend_get(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return &http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats;
|
||||
const struct zproxy_service_state *service_state =
|
||||
zproxy_state_service_lookup(&http_state->services, backend_cfg->service->name);
|
||||
if (!service_state)
|
||||
return NULL;
|
||||
struct zproxy_backend_state *backend_state =
|
||||
zproxy_state_backend_lookup(&service_state->backends, backend_cfg->runtime.id);
|
||||
if (!backend_state)
|
||||
return NULL;
|
||||
|
||||
return &backend_state->backend_stats;
|
||||
}
|
||||
|
||||
static int __zproxy_stats_backend_get_pending(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
static int __zproxy_stats_backend_get_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_pending;
|
||||
const struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return -1;
|
||||
|
||||
return backend_stats->conn_pending;
|
||||
}
|
||||
|
||||
static int __zproxy_stats_backend_get_established(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
static int __zproxy_stats_backend_get_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_established;
|
||||
const struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return -1;
|
||||
|
||||
return backend_stats->conn_established;
|
||||
}
|
||||
|
||||
int zproxy_stats_backend_get_established(
|
||||
const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
int zproxy_stats_backend_get_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return __zproxy_stats_backend_get_pending(http_state, backend_cfg) +
|
||||
__zproxy_stats_backend_get_established(http_state, backend_cfg);
|
||||
}
|
||||
|
||||
int zproxy_stats_backend_inc_code(struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg,
|
||||
int code)
|
||||
int zproxy_stats_backend_inc_code(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg,
|
||||
const int code)
|
||||
{
|
||||
struct zproxy_stats *backend_stats =
|
||||
&http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats;
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return -1;
|
||||
|
||||
if(code >= 500)
|
||||
backend_stats->http_5xx_hits++;
|
||||
else if(code >= 400)
|
||||
@ -104,79 +197,83 @@ int zproxy_stats_backend_inc_code(struct zproxy_http_state *http_state,
|
||||
backend_stats->http_2xx_hits++;
|
||||
else
|
||||
return -1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zproxy_stats_backend_inc_conn_established(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
void zproxy_stats_backend_inc_conn_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_established++;
|
||||
struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return;
|
||||
|
||||
backend_stats->conn_established++;
|
||||
}
|
||||
|
||||
void zproxy_stats_backend_dec_conn_established(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
void zproxy_stats_backend_dec_conn_established(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_established--;
|
||||
struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return;
|
||||
|
||||
backend_stats->conn_established--;
|
||||
}
|
||||
|
||||
int zproxy_stats_backend_inc_conn_pending(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
int zproxy_stats_backend_inc_conn_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return ++http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_pending;
|
||||
struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return -1;
|
||||
|
||||
return ++backend_stats->conn_pending;
|
||||
}
|
||||
|
||||
int zproxy_stats_backend_dec_conn_pending(
|
||||
struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
int zproxy_stats_backend_dec_conn_pending(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend_cfg)
|
||||
{
|
||||
return --http_state->services.at(backend_cfg->service->name)
|
||||
->backends.at(backend_cfg->runtime.id)
|
||||
->backend_stats.conn_pending;
|
||||
struct zproxy_stats *backend_stats =
|
||||
zproxy_stats_backend_get(http_state, backend_cfg);
|
||||
if (!backend_stats)
|
||||
return -1;
|
||||
|
||||
return --backend_stats->conn_pending;
|
||||
}
|
||||
|
||||
struct zproxy_backend_state *zproxy_state_get_backend(
|
||||
const std::unordered_map<std::string, std::shared_ptr<struct zproxy_backend_state>> *backend_state_map,
|
||||
const struct zproxy_backend_cfg *backend)
|
||||
{
|
||||
const std::string id = std::string(backend->runtime.id);
|
||||
|
||||
auto backend_pair = backend_state_map->find(id);
|
||||
if (backend_pair == backend_state_map->end())
|
||||
return nullptr;
|
||||
|
||||
return backend_pair->second.get();
|
||||
}
|
||||
|
||||
void zproxy_state_backend_init(const struct zproxy_service_cfg *service_cfg,
|
||||
std::unordered_map<std::string, std::shared_ptr<zproxy_backend_state>> *backend_state_list)
|
||||
static int zproxy_state_backend_init(const struct zproxy_service_cfg *service_cfg,
|
||||
struct list_head *backend_list)
|
||||
{
|
||||
struct zproxy_backend_cfg *backend;
|
||||
struct zproxy_backend_state *backend_state;
|
||||
|
||||
list_for_each_entry(backend, &service_cfg->backend_list, list) {
|
||||
auto backend_state = zproxy_state_get_backend(backend_state_list, backend);
|
||||
if (backend_state != nullptr) {
|
||||
backend_state->refcnt++;
|
||||
backend_state = zproxy_state_backend_lookup(backend_list,
|
||||
backend->runtime.id);
|
||||
if (backend_state)
|
||||
continue;
|
||||
|
||||
backend_state = (struct zproxy_backend_state*)
|
||||
calloc(1, sizeof(struct zproxy_backend_state));
|
||||
if (!backend_state) {
|
||||
zcu_log_print(LOG_ERR,
|
||||
"Couldn't create backend state (OOM)");
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string backend_id = std::string(backend->runtime.id);
|
||||
|
||||
auto new_backend_state = std::make_shared<zproxy_backend_state>();
|
||||
auto it = make_pair(backend_id, std::move(new_backend_state));
|
||||
backend_state_list->emplace(std::move(it));
|
||||
snprintf(backend_state->id, CONFIG_IDENT_MAX, "%s",
|
||||
backend->runtime.id);
|
||||
list_add_tail(&backend_state->list, backend_list);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void zproxy_state_backend_add(struct zproxy_http_state *http_state,
|
||||
int zproxy_state_backend_add(const struct zproxy_http_state *http_state,
|
||||
const struct zproxy_backend_cfg *backend)
|
||||
{
|
||||
struct zproxy_service_state *service_state;
|
||||
@ -184,49 +281,61 @@ void zproxy_state_backend_add(struct zproxy_http_state *http_state,
|
||||
struct zproxy_backend_state *backend_state;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
service_state = http_state->services.at(service_name).get();
|
||||
|
||||
backend_state = zproxy_state_get_backend(&service_state->backends, backend);
|
||||
if (backend_state != nullptr) {
|
||||
backend_state->refcnt++;
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
return;
|
||||
service_state = zproxy_state_service_lookup(&http_state->services,
|
||||
service_name);
|
||||
if (!service_state) {
|
||||
zcu_log_print(LOG_ERR, "Couldn't find service state %s.",
|
||||
service_name);
|
||||
return -1;
|
||||
}
|
||||
|
||||
const std::string backend_id = std::string(backend->runtime.id);
|
||||
backend_state = zproxy_state_backend_lookup(&service_state->backends,
|
||||
backend->runtime.id);
|
||||
if (backend_state) {
|
||||
zcu_log_print(LOG_INFO, "Backend %s already exists.",
|
||||
backend->runtime.id);
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
return 1;
|
||||
}
|
||||
|
||||
auto new_backend_state = std::make_shared<zproxy_backend_state>();
|
||||
auto it = make_pair(backend_id, std::move(new_backend_state));
|
||||
service_state->backends.emplace(std::move(it));
|
||||
backend_state = (struct zproxy_backend_state*)
|
||||
calloc(1, sizeof(struct zproxy_backend_state));
|
||||
if (!backend_state) {
|
||||
zcu_log_print(LOG_ERR, "Couldn't create backend (OOM).");
|
||||
return -1;
|
||||
}
|
||||
|
||||
snprintf(backend_state->id, CONFIG_IDENT_MAX, "%s",
|
||||
backend->runtime.id);
|
||||
list_add_tail(&backend_state->list, &service_state->backends);
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
struct zproxy_http_state *zproxy_state_init(const struct zproxy_proxy_cfg *proxy)
|
||||
struct zproxy_http_state *
|
||||
zproxy_state_init(const struct zproxy_proxy_cfg *proxy)
|
||||
{
|
||||
struct zproxy_http_state *state = nullptr;
|
||||
struct zproxy_http_state *state_ptr;
|
||||
struct std::shared_ptr<zproxy_service_state> service_state;
|
||||
struct zproxy_service_state *service_state;
|
||||
struct zproxy_service_cfg *service_cfg;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
list_for_each_entry(state_ptr, &state_list, list) {
|
||||
if (proxy->id == state_ptr->proxy_id) {
|
||||
state_ptr->refcnt++;
|
||||
state = state_ptr;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!state) {
|
||||
state = new zproxy_http_state;
|
||||
state = _zproxy_state_lookup(proxy->id);
|
||||
if (state) {
|
||||
state->refcnt++;
|
||||
} else {
|
||||
state = (struct zproxy_http_state*)
|
||||
calloc(1, sizeof(struct zproxy_http_state));
|
||||
if (!state) {
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
state->proxy_id = proxy->id;
|
||||
INIT_LIST_HEAD(&state->services);
|
||||
|
||||
// Garbage recolector for expired sessions
|
||||
// Garbage collector for expired sessions
|
||||
ev_init(&state->timer, zproxy_state_maintenance_cb);
|
||||
state->timer.repeat = TIMEOUT_SESSIONS;
|
||||
ev_timer_again(zproxy_main.loop, &state->timer);
|
||||
@ -235,49 +344,97 @@ struct zproxy_http_state *zproxy_state_init(const struct zproxy_proxy_cfg *proxy
|
||||
}
|
||||
|
||||
list_for_each_entry(service_cfg, &proxy->service_list, list) {
|
||||
|
||||
auto service_state_pair = state->services.find(service_cfg->name);
|
||||
if (service_state_pair == state->services.end()) {
|
||||
service_state = std::make_shared<zproxy_service_state>();
|
||||
service_state->sessions = zproxy_sessions_alloc(service_cfg);
|
||||
state->services.emplace(make_pair(service_cfg->name, service_state));
|
||||
} else {
|
||||
service_state = service_state_pair->second;
|
||||
service_state->refcnt++;
|
||||
service_state = zproxy_state_service_lookup(&state->services,
|
||||
service_cfg->name);
|
||||
if (!service_state) {
|
||||
service_state = (struct zproxy_service_state*)
|
||||
calloc(1, sizeof(struct zproxy_service_state));
|
||||
if (!service_state) {
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
return NULL;
|
||||
}
|
||||
service_state->sessions =
|
||||
zproxy_sessions_alloc(service_cfg);
|
||||
snprintf(service_state->name, CONFIG_IDENT_MAX, "%s",
|
||||
service_cfg->name);
|
||||
INIT_LIST_HEAD(&service_state->backends);
|
||||
list_add_tail(&service_state->list, &state->services);
|
||||
}
|
||||
|
||||
if (zproxy_state_backend_init(service_cfg,
|
||||
&service_state->backends) < 0) {
|
||||
return NULL;
|
||||
}
|
||||
zproxy_state_backend_init(service_cfg, &service_state->backends);
|
||||
}
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
static void zproxy_backend_state_purge(struct zproxy_backend_state *backend_state)
|
||||
{
|
||||
list_del(&backend_state->list);
|
||||
free(backend_state);
|
||||
}
|
||||
|
||||
static void zproxy_service_state_purge(struct zproxy_service_state *service_state)
|
||||
{
|
||||
struct zproxy_backend_state *backend_state, *next;
|
||||
|
||||
zproxy_sessions_free(service_state->sessions);
|
||||
list_for_each_entry_safe(backend_state, next, &service_state->backends, list)
|
||||
zproxy_backend_state_purge(backend_state);
|
||||
list_del(&service_state->list);
|
||||
free(service_state);
|
||||
}
|
||||
|
||||
static void zproxy_proxy_state_purge(struct zproxy_http_state *state)
|
||||
{
|
||||
struct zproxy_service_state *service_state, *next;
|
||||
|
||||
if (--state->refcnt > 0)
|
||||
return;
|
||||
|
||||
list_for_each_entry_safe(service_state, next, &state->services, list)
|
||||
zproxy_service_state_purge(service_state);
|
||||
|
||||
ev_timer_stop(zproxy_main.loop, &state->timer);
|
||||
list_del(&state->list);
|
||||
free(state);
|
||||
}
|
||||
|
||||
void zproxy_state_purge(const struct zproxy_proxy_cfg *proxy)
|
||||
{
|
||||
struct zproxy_http_state *state;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
state = _zproxy_state_lookup(proxy->id);
|
||||
if (state)
|
||||
zproxy_proxy_state_purge(state);
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
}
|
||||
|
||||
static void zproxy_state_cfg_service_update(const struct zproxy_service_cfg *service,
|
||||
struct zproxy_service_state *service_state)
|
||||
{
|
||||
const struct zproxy_backend_cfg *backend;
|
||||
auto backend_state = service_state->backends.begin();
|
||||
int found;
|
||||
struct zproxy_backend_state *backend_state, *next;
|
||||
bool found;
|
||||
|
||||
zproxy_session_delete_old_backends(service, service_state->sessions);
|
||||
|
||||
while (backend_state != service_state->backends.end()) {
|
||||
found = 0;
|
||||
list_for_each_entry_safe(backend_state, next, &service_state->backends,
|
||||
list) {
|
||||
found = false;
|
||||
list_for_each_entry(backend, &service->backend_list, list) {
|
||||
if (strcmp(backend->runtime.id, backend_state->first.c_str())) {
|
||||
found = 1;
|
||||
if (strcmp(backend->runtime.id, backend_state->id) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
auto iter = backend_state;
|
||||
backend_state++;
|
||||
service_state->backends.erase(iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
backend_state++;
|
||||
if (!found)
|
||||
zproxy_backend_state_purge(backend_state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -285,29 +442,23 @@ static void zproxy_state_cfg_proxy_update(const struct zproxy_proxy_cfg *proxy,
|
||||
struct zproxy_http_state *http_state)
|
||||
{
|
||||
const struct zproxy_service_cfg *service;
|
||||
auto service_state = http_state->services.begin();
|
||||
int found;
|
||||
struct zproxy_service_state *service_state, *next;
|
||||
bool found;
|
||||
|
||||
while (service_state != http_state->services.end()) {
|
||||
found = 0;
|
||||
list_for_each_entry_safe(service_state, next, &http_state->services,
|
||||
list) {
|
||||
found = false;
|
||||
list_for_each_entry(service, &proxy->service_list, list) {
|
||||
if (strcmp(service->name, service_state->first.c_str()) == 0) {
|
||||
found = 1;
|
||||
if (strcmp(service->name, service_state->name) == 0) {
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
auto iter = service_state;
|
||||
service_state++;
|
||||
zproxy_sessions_free(iter->second->sessions);
|
||||
http_state->services.erase(iter);
|
||||
continue;
|
||||
}
|
||||
|
||||
zproxy_state_cfg_service_update(service,
|
||||
service_state->second.get());
|
||||
service_state++;
|
||||
if (!found)
|
||||
zproxy_service_state_purge(service_state);
|
||||
else
|
||||
zproxy_state_cfg_service_update(service, service_state);
|
||||
}
|
||||
}
|
||||
|
||||
@ -327,77 +478,23 @@ void zproxy_state_cfg_update(struct zproxy_cfg *cfg)
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
list_del(&http_state->list);
|
||||
if (--http_state->refcnt == 0)
|
||||
delete http_state;
|
||||
continue;
|
||||
}
|
||||
|
||||
zproxy_state_cfg_proxy_update(proxy, http_state);
|
||||
if (!found)
|
||||
zproxy_proxy_state_purge(http_state);
|
||||
else
|
||||
zproxy_state_cfg_proxy_update(proxy, http_state);
|
||||
}
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
}
|
||||
|
||||
void zproxy_backend_state_purge(struct std::shared_ptr<zproxy_service_state> services)
|
||||
struct zproxy_sessions *
|
||||
zproxy_state_get_service_sessions(const char *service_name,
|
||||
const struct list_head *service_list)
|
||||
{
|
||||
for (auto & backend_pair : services->backends) {
|
||||
if (--backend_pair.second->refcnt == 0)
|
||||
services->backends.erase(backend_pair.first);
|
||||
struct zproxy_service_state *service_state;
|
||||
list_for_each_entry(service_state, service_list, list) {
|
||||
if (strcmp(service_state->name, service_name) == 0)
|
||||
return service_state->sessions;
|
||||
}
|
||||
}
|
||||
|
||||
void zproxy_state_purge(struct zproxy_proxy_cfg *proxy)
|
||||
{
|
||||
struct zproxy_http_state *state_ptr, *next;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
list_for_each_entry_safe(state_ptr, next, &state_list, list) {
|
||||
if (proxy->id != state_ptr->proxy_id)
|
||||
continue;
|
||||
|
||||
if (--state_ptr->refcnt == 0) {
|
||||
for (auto &service_pair : state_ptr->services)
|
||||
zproxy_sessions_free(service_pair.second->sessions);
|
||||
ev_timer_stop(zproxy_main.loop, &state_ptr->timer);
|
||||
list_del(&state_ptr->list);
|
||||
delete state_ptr;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
}
|
||||
|
||||
struct zproxy_http_state *zproxy_state_lookup(uint32_t proxy_id)
|
||||
{
|
||||
struct zproxy_http_state *state;
|
||||
|
||||
pthread_mutex_lock(&list_mutex);
|
||||
list_for_each_entry(state, &state_list, list) {
|
||||
if(state->proxy_id == proxy_id) {
|
||||
state->refcnt++;
|
||||
return state;
|
||||
}
|
||||
}
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void zproxy_state_release(struct zproxy_http_state **http_state)
|
||||
{
|
||||
(*http_state)->refcnt--;
|
||||
*http_state = NULL;
|
||||
pthread_mutex_unlock(&list_mutex);
|
||||
}
|
||||
|
||||
struct zproxy_sessions *zproxy_state_get_session(const std::string &service,
|
||||
std::unordered_map<std::string, std::shared_ptr<zproxy_service_state>> *service_list)
|
||||
{
|
||||
auto session_pair = service_list->find(service);
|
||||
|
||||
if (session_pair == service_list->end())
|
||||
return NULL;
|
||||
|
||||
return session_pair->second->sessions;
|
||||
}
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 1,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 1,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -2,7 +2,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
@ -13,7 +13,7 @@
|
||||
{
|
||||
"backends": [
|
||||
{
|
||||
"2xx-code-hits": 0,
|
||||
"2xx-code-hits": 2,
|
||||
"3xx-code-hits": 0,
|
||||
"4xx-code-hits": 0,
|
||||
"5xx-code-hits": 0,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user