diff options
author | Valentin Bartenev <vbart@nginx.com> | 2022-08-29 14:27:09 +0800 |
---|---|---|
committer | Valentin Bartenev <vbart@nginx.com> | 2022-08-29 14:27:09 +0800 |
commit | ce26dd729e6842c9ec8cc83bf091167e4c50a1ec (patch) | |
tree | d215198f765faeefd46253bd118e8d058d31fd1e | |
parent | f2bab1b1be658e3456aa1cec84a1879d4b01577e (diff) | |
download | unit-ce26dd729e6842c9ec8cc83bf091167e4c50a1ec.tar.gz unit-ce26dd729e6842c9ec8cc83bf091167e4c50a1ec.tar.bz2 |
Implemented basic statistics API.
-rw-r--r-- | auto/sources | 1 | ||||
-rw-r--r-- | docs/changes.xml | 6 | ||||
-rw-r--r-- | src/nxt_conf.c | 14 | ||||
-rw-r--r-- | src/nxt_conf.h | 2 | ||||
-rw-r--r-- | src/nxt_conn.h | 23 | ||||
-rw-r--r-- | src/nxt_conn_accept.c | 9 | ||||
-rw-r--r-- | src/nxt_conn_close.c | 14 | ||||
-rw-r--r-- | src/nxt_controller.c | 169 | ||||
-rw-r--r-- | src/nxt_event_engine.h | 4 | ||||
-rw-r--r-- | src/nxt_h1proto.c | 13 | ||||
-rw-r--r-- | src/nxt_port.h | 5 | ||||
-rw-r--r-- | src/nxt_router.c | 81 | ||||
-rw-r--r-- | src/nxt_status.c | 102 | ||||
-rw-r--r-- | src/nxt_status.h | 32 |
14 files changed, 459 insertions, 16 deletions
diff --git a/auto/sources b/auto/sources index 560f3bf3..8548f812 100644 --- a/auto/sources +++ b/auto/sources @@ -85,6 +85,7 @@ NXT_LIB_SRCS=" \ src/nxt_router.c \ src/nxt_router_access_log.c \ src/nxt_h1proto.c \ + src/nxt_status.c \ src/nxt_http_request.c \ src/nxt_http_response.c \ src/nxt_http_error.c \ diff --git a/docs/changes.xml b/docs/changes.xml index 586063db..c3496715 100644 --- a/docs/changes.xml +++ b/docs/changes.xml @@ -86,6 +86,12 @@ customizable access log format. </para> </change> +<change type="feature"> +<para> +basic statistics API. +</para> +</change> + <change type="bugfix"> <para> an index file that didn't contain a file extension was incorrectly diff --git a/src/nxt_conf.c b/src/nxt_conf.c index a44b8c75..c6312f3d 100644 --- a/src/nxt_conf.c +++ b/src/nxt_conf.c @@ -278,6 +278,20 @@ nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, } +nxt_int_t +nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, nxt_str_t *name, + nxt_conf_value_t *value, uint32_t index) +{ + nxt_conf_object_member_t *member; + + member = &object->u.object->members[index]; + + member->value = *value; + + return nxt_conf_set_string_dup(&member->name, mp, name); +} + + void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index) diff --git a/src/nxt_conf.h b/src/nxt_conf.h index f95b61c1..c8a276c0 100644 --- a/src/nxt_conf.h +++ b/src/nxt_conf.h @@ -127,6 +127,8 @@ NXT_EXPORT nxt_uint_t nxt_conf_object_members_count(nxt_conf_value_t *value); nxt_conf_value_t *nxt_conf_create_object(nxt_mp_t *mp, nxt_uint_t count); void nxt_conf_set_member(nxt_conf_value_t *object, nxt_str_t *name, const nxt_conf_value_t *value, uint32_t index); +nxt_int_t nxt_conf_set_member_dup(nxt_conf_value_t *object, nxt_mp_t *mp, + nxt_str_t *name, nxt_conf_value_t *value, uint32_t index); void nxt_conf_set_member_string(nxt_conf_value_t *object, nxt_str_t *name, nxt_str_t *value, uint32_t index); nxt_int_t nxt_conf_set_member_string_dup(nxt_conf_value_t *object, nxt_mp_t *mp, diff --git a/src/nxt_conn.h b/src/nxt_conn.h index a443601f..8a703e9a 100644 --- a/src/nxt_conn.h +++ b/src/nxt_conn.h @@ -160,6 +160,7 @@ struct nxt_conn_s { uint8_t block_read; /* 1 bit */ uint8_t block_write; /* 1 bit */ uint8_t delayed; /* 1 bit */ + uint8_t idle; /* 1 bit */ #define NXT_CONN_SENDFILE_OFF 0 #define NXT_CONN_SENDFILE_ON 1 @@ -294,6 +295,28 @@ NXT_EXPORT void nxt_event_conn_job_sendfile(nxt_task_t *task, } while (0) +#define nxt_conn_idle(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_insert_head(&e->idle_connections, &c->link); \ + \ + c->idle = 1; \ + e->idle_conns_cnt++; \ + } while (0) + + +#define nxt_conn_active(engine, c) \ + do { \ + nxt_event_engine_t *e = engine; \ + \ + nxt_queue_remove(&c->link); \ + \ + c->idle = 0; \ + e->idle_conns_cnt--; \ + } while (0) + + extern nxt_conn_io_t nxt_unix_conn_io; diff --git a/src/nxt_conn_accept.c b/src/nxt_conn_accept.c index 77c44c58..720c7b64 100644 --- a/src/nxt_conn_accept.c +++ b/src/nxt_conn_accept.c @@ -187,7 +187,8 @@ nxt_conn_io_accept(nxt_task_t *task, void *obj, void *data) void nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) { - nxt_conn_t *next; + nxt_conn_t *next; + nxt_event_engine_t *engine; nxt_sockaddr_text(c->remote); @@ -195,7 +196,11 @@ nxt_conn_accept(nxt_task_t *task, nxt_listen_event_t *lev, nxt_conn_t *c) (size_t) c->remote->address_length, nxt_sockaddr_address(c->remote)); - nxt_queue_insert_head(&task->thread->engine->idle_connections, &c->link); + engine = task->thread->engine; + + engine->accepted_conns_cnt++; + + nxt_conn_idle(engine, c); c->listen = lev; lev->count++; diff --git a/src/nxt_conn_close.c b/src/nxt_conn_close.c index 7c130309..92bd8d1b 100644 --- a/src/nxt_conn_close.c +++ b/src/nxt_conn_close.c @@ -119,6 +119,8 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + engine->closed_conns_cnt++; + if (timers_pending == 0) { nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, @@ -137,8 +139,9 @@ nxt_conn_close_handler(nxt_task_t *task, void *obj, void *data) static void nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) { - nxt_conn_t *c; - nxt_timer_t *timer; + nxt_conn_t *c; + nxt_timer_t *timer; + nxt_event_engine_t *engine; timer = obj; @@ -146,13 +149,16 @@ nxt_conn_close_timer_handler(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "conn close timer handler fd:%d", c->socket.fd); + engine = task->thread->engine; + if (c->socket.fd != -1) { nxt_socket_close(task, c->socket.fd); c->socket.fd = -1; + + engine->closed_conns_cnt++; } - nxt_work_queue_add(&task->thread->engine->fast_work_queue, - c->write_state->ready_handler, + nxt_work_queue_add(&engine->fast_work_queue, c->write_state->ready_handler, task, c, c->socket.data); } diff --git a/src/nxt_controller.c b/src/nxt_controller.c index e1e9fade..09168821 100644 --- a/src/nxt_controller.c +++ b/src/nxt_controller.c @@ -9,6 +9,7 @@ #include <nxt_runtime.h> #include <nxt_main_process.h> #include <nxt_conf.h> +#include <nxt_status.h> #include <nxt_cert.h> @@ -85,6 +86,12 @@ static void nxt_controller_process_request(nxt_task_t *task, static void nxt_controller_process_config(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); static nxt_bool_t nxt_controller_check_postpone_request(nxt_task_t *task); +static void nxt_controller_process_status(nxt_task_t *task, + nxt_controller_request_t *req); +static void nxt_controller_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg, void *data); +static void nxt_controller_status_response(nxt_task_t *task, + nxt_controller_request_t *req, nxt_str_t *path); #if (NXT_TLS) static void nxt_controller_process_cert(nxt_task_t *task, nxt_controller_request_t *req, nxt_str_t *path); @@ -120,6 +127,7 @@ static nxt_uint_t nxt_controller_router_ready; static nxt_controller_conf_t nxt_controller_conf; static nxt_queue_t nxt_controller_waiting_requests; static nxt_bool_t nxt_controller_waiting_init_conf; +static nxt_conf_value_t *nxt_controller_status; static const nxt_event_conn_state_t nxt_controller_conn_read_state; @@ -1035,6 +1043,7 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) static nxt_str_t certificates = nxt_string("certificates"); #endif static nxt_str_t config = nxt_string("config"); + static nxt_str_t status = nxt_string("status"); c = req->conn; path = req->parser.path; @@ -1058,6 +1067,32 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (nxt_str_start(&path, "/status", 7) + && (path.length == 7 || path.start[7] == '/')) + { + if (!nxt_str_eq(&req->parser.method, "GET", 3)) { + goto invalid_method; + } + + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + if (path.length == 7) { + path.length = 1; + + } else { + path.length -= 7; + path.start += 7; + } + + nxt_controller_status_response(task, req, &path); + return; + } + #if (NXT_TLS) if (nxt_str_start(&path, "/certificates", 13) @@ -1085,15 +1120,18 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) return; } - nxt_memzero(&resp, sizeof(nxt_controller_response_t)); - if (path.length == 1 && path.start[0] == '/') { if (!nxt_str_eq(&req->parser.method, "GET", 3)) { goto invalid_method; } - count = 1; + if (nxt_controller_status == NULL) { + nxt_controller_process_status(task, req); + return; + } + + count = 2; #if (NXT_TLS) count++; #endif @@ -1114,7 +1152,8 @@ nxt_controller_process_request(nxt_task_t *task, nxt_controller_request_t *req) nxt_conf_set_member(value, &certificates, certs, i++); #endif - nxt_conf_set_member(value, &config, nxt_controller_conf.root, i); + nxt_conf_set_member(value, &config, nxt_controller_conf.root, i++); + nxt_conf_set_member(value, &status, nxt_controller_status, i); resp.status = 200; resp.conf = value; @@ -1451,6 +1490,128 @@ nxt_controller_check_postpone_request(nxt_task_t *task) } +static void +nxt_controller_process_status(nxt_task_t *task, nxt_controller_request_t *req) +{ + uint32_t stream; + nxt_int_t rc; + nxt_port_t *router_port, *controller_port; + nxt_runtime_t *rt; + nxt_controller_response_t resp; + + if (nxt_controller_check_postpone_request(task)) { + nxt_queue_insert_tail(&nxt_controller_waiting_requests, &req->link); + return; + } + + rt = task->thread->runtime; + + router_port = rt->port_by_type[NXT_PROCESS_ROUTER]; + + nxt_assert(router_port != NULL); + nxt_assert(nxt_controller_router_ready); + + controller_port = rt->port_by_type[NXT_PROCESS_CONTROLLER]; + + stream = nxt_port_rpc_register_handler(task, controller_port, + nxt_controller_status_handler, + nxt_controller_status_handler, + router_port->pid, req); + if (nxt_slow_path(stream == 0)) { + goto fail; + } + + rc = nxt_port_socket_write(task, router_port, NXT_PORT_MSG_STATUS, + -1, stream, controller_port->id, NULL); + + if (nxt_slow_path(rc != NXT_OK)) { + nxt_port_rpc_cancel(task, controller_port, stream); + + goto fail; + } + + nxt_queue_insert_head(&nxt_controller_waiting_requests, &req->link); + return; + +fail: + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; +} + + +static void +nxt_controller_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg, + void *data) +{ + nxt_conf_value_t *status; + nxt_controller_request_t *req; + nxt_controller_response_t resp; + + nxt_debug(task, "controller status handler"); + + req = data; + + if (msg->port_msg.type == NXT_PORT_MSG_RPC_READY) { + status = nxt_status_get((nxt_status_report_t *) msg->buf->mem.pos, + req->conn->mem_pool); + } else { + status = NULL; + } + + if (status == NULL) { + nxt_queue_remove(&req->link); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + resp.status = 500; + resp.title = (u_char *) "Failed to get status."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + } + + nxt_controller_status = status; + + nxt_controller_flush_requests(task); + + nxt_controller_status = NULL; +} + + +static void +nxt_controller_status_response(nxt_task_t *task, nxt_controller_request_t *req, + nxt_str_t *path) +{ + nxt_conf_value_t *status; + nxt_controller_response_t resp; + + status = nxt_conf_get_path(nxt_controller_status, path); + + nxt_memzero(&resp, sizeof(nxt_controller_response_t)); + + if (status == NULL) { + resp.status = 404; + resp.title = (u_char *) "Invalid path."; + resp.offset = -1; + + nxt_controller_response(task, req, &resp); + return; + } + + resp.status = 200; + resp.conf = status; + + nxt_controller_response(task, req, &resp); +} + + #if (NXT_TLS) static void diff --git a/src/nxt_event_engine.h b/src/nxt_event_engine.h index 91cfc0aa..4153742d 100644 --- a/src/nxt_event_engine.h +++ b/src/nxt_event_engine.h @@ -483,6 +483,10 @@ struct nxt_event_engine_s { nxt_queue_t idle_connections; nxt_array_t *mem_cache; + nxt_atomic_uint_t accepted_conns_cnt; + nxt_atomic_uint_t idle_conns_cnt; + nxt_atomic_uint_t closed_conns_cnt; + nxt_queue_link_t link; // STUB: router link nxt_queue_link_t link0; diff --git a/src/nxt_h1proto.c b/src/nxt_h1proto.c index 1473aaa0..852b4866 100644 --- a/src/nxt_h1proto.c +++ b/src/nxt_h1proto.c @@ -478,7 +478,7 @@ nxt_h1p_conn_request_init(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn request init"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); r = nxt_http_request_create(task); @@ -1739,7 +1739,7 @@ nxt_h1p_conn_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1754,7 +1754,7 @@ nxt_h1p_conn_error(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p conn error"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_shutdown(task, c); } @@ -1801,7 +1801,8 @@ nxt_h1p_keepalive(nxt_task_t *task, nxt_h1proto_t *h1p, nxt_conn_t *c) c->sent = 0; engine = task->thread->engine; - nxt_queue_insert_head(&engine->idle_connections, &c->link); + + nxt_conn_idle(engine, c); if (in == NULL) { c->read_state = &nxt_h1p_keepalive_state; @@ -1855,7 +1856,7 @@ nxt_h1p_idle_close(nxt_task_t *task, void *obj, void *data) nxt_debug(task, "h1p idle close"); - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } @@ -1874,7 +1875,7 @@ nxt_h1p_idle_timeout(nxt_task_t *task, void *obj, void *data) c = nxt_read_timer_conn(timer); c->block_read = 1; - nxt_queue_remove(&c->link); + nxt_conn_active(task->thread->engine, c); nxt_h1p_idle_response(task, c); } diff --git a/src/nxt_port.h b/src/nxt_port.h index 6b4d3c8f..3a8da5ad 100644 --- a/src/nxt_port.h +++ b/src/nxt_port.h @@ -53,6 +53,9 @@ struct nxt_port_handlers_s { nxt_port_handler_t data; nxt_port_handler_t app_restart; + /* Status report. */ + nxt_port_handler_t status; + nxt_port_handler_t oosm; nxt_port_handler_t shm_ack; nxt_port_handler_t read_queue; @@ -104,6 +107,7 @@ typedef enum { _NXT_PORT_MSG_DATA = nxt_port_handler_idx(data), _NXT_PORT_MSG_APP_RESTART = nxt_port_handler_idx(app_restart), + _NXT_PORT_MSG_STATUS = nxt_port_handler_idx(status), _NXT_PORT_MSG_OOSM = nxt_port_handler_idx(oosm), _NXT_PORT_MSG_SHM_ACK = nxt_port_handler_idx(shm_ack), @@ -145,6 +149,7 @@ typedef enum { NXT_PORT_MSG_DATA = _NXT_PORT_MSG_DATA, NXT_PORT_MSG_DATA_LAST = nxt_msg_last(_NXT_PORT_MSG_DATA), NXT_PORT_MSG_APP_RESTART = nxt_msg_last(_NXT_PORT_MSG_APP_RESTART), + NXT_PORT_MSG_STATUS = nxt_msg_last(_NXT_PORT_MSG_STATUS), NXT_PORT_MSG_OOSM = nxt_msg_last(_NXT_PORT_MSG_OOSM), NXT_PORT_MSG_SHM_ACK = nxt_msg_last(_NXT_PORT_MSG_SHM_ACK), diff --git a/src/nxt_router.c b/src/nxt_router.c index e1f4f6da..e7723a2d 100644 --- a/src/nxt_router.c +++ b/src/nxt_router.c @@ -7,6 +7,7 @@ #include <nxt_router.h> #include <nxt_conf.h> +#include <nxt_status.h> #if (NXT_TLS) #include <nxt_cert.h> #endif @@ -90,6 +91,8 @@ static void nxt_router_conf_data_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); static void nxt_router_app_restart_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); +static void nxt_router_status_handler(nxt_task_t *task, + nxt_port_recv_msg_t *msg); static void nxt_router_remove_pid_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg); @@ -269,6 +272,7 @@ static const nxt_port_handlers_t nxt_router_process_port_handlers = { .get_mmap = nxt_router_get_mmap_handler, .data = nxt_router_conf_data_handler, .app_restart = nxt_router_app_restart_handler, + .status = nxt_router_status_handler, .remove_pid = nxt_router_remove_pid_handler, .access_log = nxt_router_access_log_reopen_handler, .rpc_ready = nxt_port_rpc_handler, @@ -919,6 +923,83 @@ fail: static void +nxt_router_status_handler(nxt_task_t *task, nxt_port_recv_msg_t *msg) +{ + u_char *p; + size_t alloc; + nxt_app_t *app; + nxt_buf_t *b; + nxt_uint_t type; + nxt_port_t *port; + nxt_status_app_t *app_stat; + nxt_event_engine_t *engine; + nxt_status_report_t *report; + + port = nxt_runtime_port_find(task->thread->runtime, + msg->port_msg.pid, + msg->port_msg.reply_port); + if (nxt_slow_path(port == NULL)) { + nxt_alert(task, "nxt_router_status_handler(): reply port not found"); + return; + } + + alloc = sizeof(nxt_status_report_t); + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + + alloc += sizeof(nxt_status_app_t) + app->name.length; + + } nxt_queue_loop; + + b = nxt_buf_mem_alloc(port->mem_pool, alloc, 0); + if (nxt_slow_path(b == NULL)) { + type = NXT_PORT_MSG_RPC_ERROR; + goto fail; + } + + report = (nxt_status_report_t *) b->mem.free; + b->mem.free = b->mem.end; + + nxt_memzero(report, sizeof(nxt_status_report_t)); + + nxt_queue_each(engine, &nxt_router->engines, nxt_event_engine_t, link0) { + + report->accepted_conns += engine->accepted_conns_cnt; + report->idle_conns += engine->idle_conns_cnt; + report->closed_conns += engine->closed_conns_cnt; + + } nxt_queue_loop; + + report->apps_count = 0; + app_stat = report->apps; + p = b->mem.end; + + nxt_queue_each(app, &nxt_router->apps, nxt_app_t, link) { + p -= app->name.length; + + nxt_memcpy(p, app->name.start, app->name.length); + + app_stat->name.length = app->name.length; + app_stat->name.start = (u_char *) (p - b->mem.pos); + + app_stat->active_requests = app->active_requests; + app_stat->pending_processes = app->pending_processes; + app_stat->processes = app->processes; + app_stat->idle_processes = app->idle_processes; + + report->apps_count++; + app_stat++; + } nxt_queue_loop; + + type = NXT_PORT_MSG_RPC_READY_LAST; + +fail: + + nxt_port_socket_write(task, port, type, -1, msg->port_msg.stream, 0, b); +} + + +static void nxt_router_app_process_remove_pid(nxt_task_t *task, nxt_port_t *port, void *data) { diff --git a/src/nxt_status.c b/src/nxt_status.c new file mode 100644 index 00000000..529f6ebb --- /dev/null +++ b/src/nxt_status.c @@ -0,0 +1,102 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#include <nxt_main.h> +#include <nxt_conf.h> +#include <nxt_status.h> + + +nxt_conf_value_t * +nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp) +{ + size_t i; + nxt_str_t name; + nxt_int_t ret; + nxt_status_app_t *app; + nxt_conf_value_t *status, *obj, *apps, *app_obj; + + static nxt_str_t conns_str = nxt_string("connections"); + static nxt_str_t acc_str = nxt_string("accepted"); + static nxt_str_t active_str = nxt_string("active"); + static nxt_str_t idle_str = nxt_string("idle"); + static nxt_str_t closed_str = nxt_string("closed"); + static nxt_str_t reqs_str = nxt_string("requests"); + static nxt_str_t apps_str = nxt_string("applications"); + static nxt_str_t procs_str = nxt_string("processes"); + static nxt_str_t run_str = nxt_string("running"); + static nxt_str_t start_str = nxt_string("starting"); + + status = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(status == NULL)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 4); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &conns_str, obj, 0); + + nxt_conf_set_member_integer(obj, &acc_str, report->accepted_conns, 0); + nxt_conf_set_member_integer(obj, &active_str, report->accepted_conns + - report->closed_conns + - report->idle_conns, 1); + nxt_conf_set_member_integer(obj, &idle_str, report->idle_conns, 2); + nxt_conf_set_member_integer(obj, &closed_str, report->closed_conns, 3); + + obj = nxt_conf_create_object(mp, 0); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &reqs_str, obj, 1); + + apps = nxt_conf_create_object(mp, report->apps_count); + if (nxt_slow_path(obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(status, &apps_str, apps, 2); + + for (i = 0; i < report->apps_count; i++) { + app = &report->apps[i]; + + app_obj = nxt_conf_create_object(mp, 2); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + name.length = app->name.length; + name.start = nxt_pointer_to(report, (uintptr_t) app->name.start); + + ret = nxt_conf_set_member_dup(apps, mp, &name, app_obj, i); + if (nxt_slow_path(ret != NXT_OK)) { + return NULL; + } + + obj = nxt_conf_create_object(mp, 3); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &procs_str, obj, 0); + + nxt_conf_set_member_integer(obj, &run_str, app->processes, 0); + nxt_conf_set_member_integer(obj, &start_str, app->pending_processes, 1); + nxt_conf_set_member_integer(obj, &idle_str, app->idle_processes, 2); + + obj = nxt_conf_create_object(mp, 1); + if (nxt_slow_path(app_obj == NULL)) { + return NULL; + } + + nxt_conf_set_member(app_obj, &reqs_str, obj, 1); + + nxt_conf_set_member_integer(obj, &active_str, app->active_requests, 0); + } + + return status; +} diff --git a/src/nxt_status.h b/src/nxt_status.h new file mode 100644 index 00000000..b12eabcb --- /dev/null +++ b/src/nxt_status.h @@ -0,0 +1,32 @@ + +/* + * Copyright (C) NGINX, Inc. + */ + +#ifndef _NXT_STATUS_H_INCLUDED_ +#define _NXT_STATUS_H_INCLUDED_ + + +typedef struct { + nxt_str_t name; + uint32_t active_requests; + uint32_t pending_processes; + uint32_t processes; + uint32_t idle_processes; +} nxt_status_app_t; + + +typedef struct { + uint64_t accepted_conns; + uint64_t idle_conns; + uint64_t closed_conns; + + size_t apps_count; + nxt_status_app_t apps[]; +} nxt_status_report_t; + + +nxt_conf_value_t *nxt_status_get(nxt_status_report_t *report, nxt_mp_t *mp); + + +#endif /* _NXT_STATUS_H_INCLUDED_ */ |